Commits

Jeffrey Goettsch committed 6ac8644

Added methods retrieve_token and retrieve_apikey to the Prowl client.

Comments (0)

Files changed (2)

pushnotify/prowl.py

 PUBLIC_API_URL = u'https://api.prowlapp.com/publicapi'
 VERIFY_URL = u'/'.join([PUBLIC_API_URL, 'verify'])
 NOTIFY_URL = u'/'.join([PUBLIC_API_URL, 'add'])
+RETRIEVE_TOKEN_URL = u'/'.join([PUBLIC_API_URL, 'retrieve', 'token'])
+RETRIEVE_APIKEY_URL = u'/'.join([PUBLIC_API_URL, 'retrieve', 'apikey'])
 
 
 class Client(object):
         self._last_message = None
         self._last_remaining = None
         self._last_resetdate = None
+        self._last_token = None
+        self._last_token_url = None
+        self._last_apikey = None
 
         self.apikeys = [] if apikeys is None else apikeys
         self.providerkey = providerkey
             return response_stream
 
     def _parse_response(self, response, verify=False):
+
         xmlresp = response.read()
-        print xmlresp
         root = ElementTree.fromstring(xmlresp)
 
         self._last_type = root[0].tag.lower()
         else:
             raise exceptions.UnrecognizedResponseError(xmlresp, -1)
 
+        if len(root) > 1:
+            if root[1].tag.lower() == 'retrieve':
+                if 'token' in root[1].attrib:
+                    self._last_token = root[1].attrib['token']
+                    self._last_token_url = root[1].attrib['url']
+                    self._last_apikey = None
+                elif 'apikey' in root[1].attrib:
+                    self._last_token = None
+                    self.last_token_url = None
+                    self._last_apikey = root[1].attrib['apikey']
+                else:
+                    raise exceptions.UnrecognizedResponseError(xmlresp, -1)
+            else:
+                raise exceptions.UnrecognizedResponseError(xmlresp, -1)
+
         return root
 
     def _post(self, url, data):
         response = self._post(NOTIFY_URL, data)
         self._parse_response(response)
 
+    def retrieve_apikey(self, token):
+        """Get an API key for a given token.
+
+        Once a user has approved you sending them push notifications,
+        you can supply the returned token here and get an API key.
+
+        Args:
+            token: A string containing a registration token returned
+                from the retrieve_token method.
+
+        Returns:
+            A string containing the API key.
+
+        """
+
+        data = {'providerkey': self.providerkey,
+                'token': token}
+
+        querystring = urllib.urlencode(data)
+        url = '?'.join([RETRIEVE_APIKEY_URL, querystring])
+
+        response = self._get(url)
+        self._parse_response(response)
+
+        return self._last_apikey
+
+    def retrieve_token(self):
+        """Get a registration token and approval URL.
+
+        A user follows the URL and logs in to the Prowl website to
+        approve you sending them push notifications. If you've
+        associated a 'Retrieve success URL' with your provider key, they
+        will be redirected there.
+
+        Returns:
+            A two-item tuple where the first item is a string containing
+            a registration token, and the second item is a string
+            containing the associated URL.
+        """
+
+        data = {'providerkey': self.providerkey}
+
+        querystring = urllib.urlencode(data)
+        url = '?'.join([RETRIEVE_TOKEN_URL, querystring])
+
+        response = self._get(url)
+        self._parse_response(response)
+
+        return self._last_token, self._last_token_url
+
     def verify_user(self, apikey):
         """Verify an API key for a user.
 

pushnotify/tests/tests.py

 #!/usr/bin/env python
 # vim: set fileencoding=utf-8
 
-"""copyright: Copyright (c) Jeffrey Goettsch and other contributors.
+"""Unit tests.
+
+copyright: Copyright (c) Jeffrey Goettsch and other contributors.
 license: BSD, see LICENSE for details.
 
 """
 except ImportError:
     PROWL_API_KEYS = []
     PROWL_PROVIDER_KEY = ''
+    PROWL_REG_TOKEN = ''
 else:
     from pushnotify.tests.prowlkeys import API_KEYS as PROWL_API_KEYS
     from pushnotify.tests.prowlkeys import PROVIDER_KEY as PROWL_PROVIDER_KEY
+    from pushnotify.tests.prowlkeys import REG_TOKEN as PROWL_REG_TOKEN
 try:
     imp.find_module('pushoverkeys', [os.path.dirname(__file__)])
 except ImportError:
 
 
 class NMATest(unittest.TestCase):
+    """Test the Notify my Android client.
+
+    """
 
     def setUp(self):
 
 
         """
 
-        """valid notification"""
+        # valid notification
 
         self.client.notify(self.app, self.event, self.desc)
 
-        """valid notification, extra arguments, html"""
+        # valid notification, extra arguments, html
 
         html_desc = '<h1>{0}</h1><p>{1}<br>{2}</p>'.format(
             self.app, self.event, self.desc)
 
         """
 
-        """invalid API key"""
+        # invalid API key
 
         char = self.client.apikeys[0][0]
         apikey = self.client.apikeys[0].replace(char, '_')
         self.client.apikeys = NMA_API_KEYS
         self.client.developerkey = NMA_DEVELOPER_KEY
 
-        """invalid argument lengths"""
+        # invalid argument lengths
 
         bad_app = 'a' * 257
         self.assertRaises(exceptions.FormatError,
 
         """
 
-        """invalid API key of incorrect length"""
+        # invalid API key of incorrect length
 
         apikey = u'{0}{1}'.format(self.client.apikeys[0], '1')
 
         self.assertFalse(self.client.verify(apikey))
 
-        """invalid API key of correct length"""
+        # invalid API key of correct length
 
         char = self.client.apikeys[0][0]
         apikey = self.client.apikeys[0].replace(char, '_')
 
 
 class ProwlTest(unittest.TestCase):
+    """Test the Prowl client.
+
+    """
 
     def setUp(self):
 
 
         """
 
-        """invalid API key"""
+        # invalid API key
 
         char = self.client.apikeys[0][0]
         apikey = self.client.apikeys[0].replace(char, '_')
         self.client.apikeys = NMA_API_KEYS
         self.client.developerkey = NMA_DEVELOPER_KEY
 
-        """invalid argument lengths"""
+        # invalid argument lengths
 
         bad_app = 'a' * 257
         self.assertRaises(exceptions.FormatError,
                           self.client.notify, bad_app, self.event, self.desc)
 
+    def test_retrieve_apikey_valid(self):
+        """Test retrieve_apikey with a valid token.
+
+        """
+
+        apikey = self.client.retrieve_apikey(PROWL_REG_TOKEN)
+        self.assertTrue(apikey)
+        self.assertIs(type(apikey), str)
+
+    def test_retrieve_apikey_invalid(self):
+        """Test retrieve_apikey with an invalid token and provider key.
+
+        """
+
+        # invalid registration token
+
+        self.assertRaises(exceptions.PermissionDenied,
+                          self.client.retrieve_apikey, PROWL_REG_TOKEN[0:-1])
+
+        # invalid providerkey
+
+        self.client.providerkey = self.client.providerkey[0:-1]
+        self.assertRaises(exceptions.ApiKeyError,
+                          self.client.retrieve_apikey, PROWL_REG_TOKEN)
+
+    def test_retrieve_token_valid(self):
+        """Test retrieve_token with a valid providerkey.
+
+        """
+
+        token = self.client.retrieve_token()
+        self.assertTrue(token)
+        self.assertEqual(len(token), 2)
+        self.assertIs(type(token[0]), str)
+        self.assertIs(type(token[1]), str)
+
+    def test_retrieve_token_invalid(self):
+        """Test retrieve_token with an invalid providerkey.
+
+        """
+
+        self.client.providerkey = self.client.providerkey[0:-1]
+        self.assertRaises(exceptions.ApiKeyError,
+                          self.client.retrieve_token)
+
     def test_verify_user_valid(self):
         """Test verify_user with a valid API key.
 
 
         """
 
-        """invalid API key of incorrect length"""
+        # invalid API key of incorrect length
 
         apikey = u'{0}{1}'.format(self.client.apikeys[0], '1')
 
         self.assertFalse(self.client.verify_user(apikey))
 
-        """invalid API key of correct length"""
+        # invalid API key of correct length
 
         char = self.client.apikeys[0][0]
         apikey = self.client.apikeys[0].replace(char, '_')
 
 
 class PushoverTest(unittest.TestCase):
+    """Test the Pushover client.
+
+    """
 
     def setUp(self):
 
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.