From 084997d33e963bfb1f9358683e49c49514c681dc Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Wed, 6 Feb 2019 21:19:52 -0500 Subject: [PATCH] Removal of stride:// as service is going down on 2019.02.15; refs #56 --- README.md | 1 - apprise/plugins/NotifyStride.py | 253 -------------------------------- apprise/plugins/__init__.py | 3 +- test/test_rest_plugins.py | 92 ------------ 4 files changed, 1 insertion(+), 348 deletions(-) delete mode 100644 apprise/plugins/NotifyStride.py diff --git a/README.md b/README.md index 5ba74e69..130606c4 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,6 @@ The table below identifies the services this tool supports and some example serv | [Pushover](https://github.com/caronc/apprise/wiki/Notify_pushover) | pover:// | (TCP) 443 | pover://user@token
pover://user@token/DEVICE
pover://user@token/DEVICE1/DEVICE2/DEVICEN
_Note: you must specify both your user_id and token_ | [Rocket.Chat](https://github.com/caronc/apprise/wiki/Notify_rocketchat) | rocket:// or rockets:// | (TCP) 80 or 443 | rocket://user:password@hostname/RoomID/Channel
rockets://user:password@hostname:443/Channel1/Channel1/RoomID
rocket://user:password@hostname/Channel | [Slack](https://github.com/caronc/apprise/wiki/Notify_slack) | slack:// | (TCP) 443 | slack://TokenA/TokenB/TokenC/Channel
slack://botname@TokenA/TokenB/TokenC/Channel
slack://user@TokenA/TokenB/TokenC/Channel1/Channel2/ChannelN -| [Stride](https://github.com/caronc/apprise/wiki/Notify_stride) | stride:// | (TCP) 443 | stride://auth_token/cloud_id/convo_id | [Super Toasty](https://github.com/caronc/apprise/wiki/Notify_toasty) | toasty:// | (TCP) 80 | toasty://user@DEVICE
toasty://user@DEVICE1/DEVICE2/DEVICEN
_Note: you must specify both your user_id and at least 1 device!_ | [Telegram](https://github.com/caronc/apprise/wiki/Notify_telegram) | tgram:// | (TCP) 443 | tgram://bottoken/ChatID
tgram://bottoken/ChatID1/ChatID2/ChatIDN | [Twitter](https://github.com/caronc/apprise/wiki/Notify_twitter) | tweet:// | (TCP) 443 | tweet://user@CKey/CSecret/AKey/ASecret diff --git a/apprise/plugins/NotifyStride.py b/apprise/plugins/NotifyStride.py deleted file mode 100644 index 1a8ec1e8..00000000 --- a/apprise/plugins/NotifyStride.py +++ /dev/null @@ -1,253 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Copyright (C) 2019 Chris Caron -# All rights reserved. -# -# This code is licensed under the MIT License. -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files(the "Software"), to deal -# in the Software without restriction, including without limitation the rights -# to use, copy, modify, merge, publish, distribute, sublicense, and / or sell -# copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions : -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -# THE SOFTWARE. - -# When you sign-up with stride.com they'll ask if you want to join a channel -# or create your own. -# -# Once you get set up, you'll have the option of creating a channel. -# -# Now you'll want to connect apprise up. To do this, you need to go to -# the App Manager an choose to 'Connect your own app'. It will get you -# to provide a 'token name' which can be whatever you want. Call it -# 'Apprise' if you want (it really doesn't matter) and then click the -# 'Create' button. -# -# When it completes it will generate a token that looks something like: -# HQFtq4pF8rKFOlKTm9Th -# -# This will become your AUTH_TOKEN -# -# It will also provide you a conversation URL that might look like: -# https://api.atlassian.com/site/ce171c45-79ae-4fec-a73d-5a4b7a322872/\ -# conversation/a54a80b3-eaad-4564-9a3a-f6653bcfb100/message -# -# Simplified, it looks like this: -# https://api.atlassian.com/site/CLOUD_ID/conversation/CONVO_ID/message -# -# This plugin will simply work using the url of: -# stride://AUTH_TOKEN/CLOUD_ID/CONVO_ID -# -import requests -import re -from json import dumps - -from .NotifyBase import NotifyBase -from .NotifyBase import HTTP_ERROR_MAP -from ..common import NotifyImageSize - -# A Simple UUID4 checker -IS_VALID_TOKEN = re.compile( - r'([0-9a-f]{8})-*([0-9a-f]{4})-*(4[0-9a-f]{3})-*' - r'([89ab][0-9a-f]{3})-*([0-9a-f]{12})', re.I) - - -class NotifyStride(NotifyBase): - """ - A wrapper to Stride Notifications - - """ - # The default descriptive name associated with the Notification - service_name = 'Stride' - - # The services URL - service_url = 'https://www.stride.com/' - - # The default secure protocol - secure_protocol = 'stride' - - # A URL that takes you to the setup/help of the specific protocol - setup_url = 'https://github.com/caronc/apprise/wiki/Notify_stride' - - # Stride Webhook - notify_url = 'https://api.atlassian.com/site/{cloud_id}/' \ - 'conversation/{convo_id}/message' - - # Allows the user to specify the NotifyImageSize object - image_size = NotifyImageSize.XY_256 - - # The maximum allowable characters allowed in the body per message - body_maxlen = 2000 - - def __init__(self, auth_token, cloud_id, convo_id, **kwargs): - """ - Initialize Stride Object - - """ - super(NotifyStride, self).__init__(**kwargs) - - if not auth_token: - raise TypeError( - 'An invalid Authorization token was specified.' - ) - - if not cloud_id: - raise TypeError('No Cloud ID was specified.') - - cloud_id_re = IS_VALID_TOKEN.match(cloud_id) - if cloud_id_re is None: - raise TypeError('The specified Cloud ID is not a valid UUID.') - - if not convo_id: - raise TypeError('No Conversation ID was specified.') - - convo_id_re = IS_VALID_TOKEN.match(convo_id) - if convo_id_re is None: - raise TypeError( - 'The specified Conversation ID is not a valid UUID.') - - # Store our validated token - self.cloud_id = '{0}-{1}-{2}-{3}-{4}'.format( - cloud_id_re.group(0), - cloud_id_re.group(1), - cloud_id_re.group(2), - cloud_id_re.group(3), - cloud_id_re.group(4), - ) - - # Store our validated token - self.convo_id = '{0}-{1}-{2}-{3}-{4}'.format( - convo_id_re.group(0), - convo_id_re.group(1), - convo_id_re.group(2), - convo_id_re.group(3), - convo_id_re.group(4), - ) - - self.auth_token = auth_token - - return - - def notify(self, title, body, notify_type, **kwargs): - """ - Perform Stride Notification - """ - - headers = { - 'User-Agent': self.app_id, - 'Authorization': 'Bearer {auth_token}'.format( - auth_token=self.auth_token), - 'Content-Type': 'application/json', - } - - # Prepare JSON Object - payload = { - "body": { - "version": 1, - "type": "doc", - "content": [{ - "type": "paragraph", - "content": [{ - "type": "text", - "text": body, - }], - }], - } - } - - # Construct Notify URL - notify_url = self.notify_url.format( - cloud_id=self.cloud_id, - convo_id=self.convo_id, - ) - - self.logger.debug('Stride POST URL: %s (cert_verify=%r)' % ( - notify_url, self.verify_certificate, - )) - self.logger.debug('Stride Payload: %s' % str(payload)) - try: - r = requests.post( - notify_url, - data=dumps(payload), - headers=headers, - verify=self.verify_certificate, - ) - if r.status_code not in ( - requests.codes.ok, requests.codes.no_content): - # We had a problem - try: - self.logger.warning( - 'Failed to send Stride notification: ' - '%s (error=%s).' % ( - HTTP_ERROR_MAP[r.status_code], - r.status_code)) - - except KeyError: - self.logger.warning( - 'Failed to send Stride notification ' - '(error=%s).' % r.status_code) - - self.logger.debug('Response Details: %s' % r.raw.read()) - - # Return; we're done - return False - - else: - self.logger.info('Sent Stride notification.') - - except requests.RequestException as e: - self.logger.warning( - 'A Connection error occured sending Stride ' - 'notification.' - ) - self.logger.debug('Socket Exception: %s' % str(e)) - return False - - return True - - @staticmethod - def parse_url(url): - """ - Parses the URL and returns enough arguments that can allow - us to substantiate this object. - - Syntax: - stride://auth_token/cloud_id/convo_id - - """ - results = NotifyBase.parse_url(url) - - if not results: - # We're done early as we couldn't load the results - return results - - # Store our Authentication Token - auth_token = results['host'] - - # Now fetch our tokens - try: - (ta, tb) = [x for x in filter(bool, NotifyBase.split_path( - results['fullpath']))][0:2] - - except (ValueError, AttributeError, IndexError): - # Force some bad values that will get caught - # in parsing later - ta = None - tb = None - - results['cloud_id'] = ta - results['convo_id'] = tb - results['auth_token'] = auth_token - - return results diff --git a/apprise/plugins/__init__.py b/apprise/plugins/__init__.py index 30675004..a0dbb6e4 100644 --- a/apprise/plugins/__init__.py +++ b/apprise/plugins/__init__.py @@ -46,7 +46,6 @@ from .NotifyPushjet.NotifyPushjet import NotifyPushjet from .NotifyPushover import NotifyPushover from .NotifyRocketChat import NotifyRocketChat from .NotifySlack import NotifySlack -from .NotifyStride import NotifyStride from .NotifyTelegram import NotifyTelegram from .NotifyToasty import NotifyToasty from .NotifyTwitter.NotifyTwitter import NotifyTwitter @@ -69,7 +68,7 @@ __all__ = [ 'NotifyFaast', 'NotifyGnome', 'NotifyGrowl', 'NotifyIFTTT', 'NotifyJoin', 'NotifyJSON', 'NotifyMatrix', 'NotifyMatterMost', 'NotifyProwl', 'NotifyPushalot', 'NotifyPushBullet', 'NotifyPushjet', 'NotifyPushover', - 'NotifyRocketChat', 'NotifySlack', 'NotifyStride', 'NotifyToasty', + 'NotifyRocketChat', 'NotifySlack', 'NotifyToasty', 'NotifyTwitter', 'NotifyTelegram', 'NotifyXBMC', 'NotifyXML', 'NotifyWindows', diff --git a/test/test_rest_plugins.py b/test/test_rest_plugins.py index 63b41df8..d59f58df 100644 --- a/test/test_rest_plugins.py +++ b/test/test_rest_plugins.py @@ -31,7 +31,6 @@ from apprise.utils import compat_is_basestring from apprise.common import NotifyFormat from json import dumps -import uuid import requests import mock @@ -252,63 +251,6 @@ TEST_URLS = ( 'test_requests_exceptions': True, }), - ################################## - # NotifyStride - ################################## - # no auth_key specified - ('stride://', { - 'instance': None, - }), - # No token_a specified - ('stride://auth_key', { - # Missing a token - 'instance': TypeError, - }), - # No token_b specified - ('stride://auth_key/{0}'.format( - str(uuid.uuid4())), { - 'instance': TypeError, - }), - # invalid uuid entries - ('stride://auth_key/{0}/{1}'.format( - 'invalid-uuid', str(uuid.uuid4())), { - 'instance': TypeError, - }), - ('stride://auth_key/{0}/{1}'.format( - str(uuid.uuid4()), 'invalid-uuid'), { - 'instance': TypeError, - }), - # A valid url - ('stride://auth_key/{0}/{1}'.format( - str(uuid.uuid4()), str(uuid.uuid4())), { - 'instance': plugins.NotifyStride, - }), - # A very invalid URL - ('stride://:@/', { - 'instance': None, - }), - ('stride://auth_key/{0}/{1}'.format( - str(uuid.uuid4()), str(uuid.uuid4())), { - 'instance': plugins.NotifyStride, - # force a failure - 'response': False, - 'requests_response_code': requests.codes.internal_server_error, - }), - ('stride://auth_key/{0}/{1}'.format( - str(uuid.uuid4()), str(uuid.uuid4())), { - 'instance': plugins.NotifyStride, - # throw a bizzare code forcing us to fail to look it up - 'response': False, - 'requests_response_code': 999, - }), - ('stride://auth_key/{0}/{1}'.format( - str(uuid.uuid4()), str(uuid.uuid4())), { - 'instance': plugins.NotifyStride, - # Throws a series of connection and transfer exceptions when this flag - # is set and tests that we gracfully handle them - 'test_requests_exceptions': True, - }), - ################################## # NotifyIFTTT - If This Than That ################################## @@ -2143,40 +2085,6 @@ def test_notify_ifttt_plugin(mock_post, mock_get): notify_type=NotifyType.INFO) is True -def test_notify_stride_plugin(): - """ - API: NotifyStride() Extra Checks - - """ - try: - # Initializes the plugin with devices set to a string - plugins.NotifyStride( - auth_token=None, - cloud_id=str(uuid.uuid4()), - convo_id=str(uuid.uuid4()), - ) - # The code shouldn't make it here, we should throw an exception - # on the previous line - assert False - - except TypeError: - assert True - - try: - # Initializes the plugin with devices set to a string - plugins.NotifyStride( - auth_token='key', - cloud_id=str(uuid.uuid4()), - convo_id=None, - ) - # The code shouldn't make it here, we should throw an exception - # on the previous line - assert False - - except TypeError: - assert True - - @mock.patch('requests.get') @mock.patch('requests.post') def test_notify_join_plugin(mock_post, mock_get):