From fc9f583987feb4a747b7bcf48f48154872b97abd Mon Sep 17 00:00:00 2001 From: Mike Crute Date: Wed, 29 Jul 2015 18:20:25 -0700 Subject: Final commit before moving to git. --- milkman/__init__.py | 11 +++ milkman/auth.py | 170 +++++++++++++++++++++++++++++++++++++++++++++ milkman/tests/test_auth.py | 16 +++++ 3 files changed, 197 insertions(+) create mode 100644 milkman/__init__.py create mode 100644 milkman/auth.py create mode 100644 milkman/tests/test_auth.py diff --git a/milkman/__init__.py b/milkman/__init__.py new file mode 100644 index 0000000..727ff90 --- /dev/null +++ b/milkman/__init__.py @@ -0,0 +1,11 @@ +# vim: set filencoding=utf8 +""" +Milkman - A Remember The Milk API + +@author: Mike Crute (mcrute@ag.com) +@organization: American Greetings Interactive +@date: February 03, 2010 +""" + + +API_URL = "http://api.rememberthemilk.com/services" diff --git a/milkman/auth.py b/milkman/auth.py new file mode 100644 index 0000000..0dfb36d --- /dev/null +++ b/milkman/auth.py @@ -0,0 +1,170 @@ +# vim: set filencoding=utf8 +""" +Remember The Milk Authentication + +@author: Mike Crute (mcrute@ag.com) +@organization: American Greetings Interactive +@date: February 03, 2010 +""" + +import json +import urllib +from logging import getLogger +from hashlib import md5 +from milkman import API_URL + + +logger = getLogger('rtmapi') + + +class APIPerms(object): + + READ = "read" + WRITE = "write" + DELETE = "delete" + + +def flatten_sorted_dict(in_dict): + items = sorted(in_dict.items()) + flat_items = [''.join(item) for item in items] + return ''.join(flat_items) + + +class APIError(Exception): + pass + + +class Request(object): + + def __init__(self, api_key, secret, service='rest'): + self.service = service + self.secret = secret + self.params = { + 'format': 'json', + 'api_key': api_key, + } + + @classmethod + def get_factory(cls, api_key, secret): + return lambda: cls(api_key, secret) + + @property + def url(self): + self._sign_request() + params = urllib.urlencode(self.params) + return '{0}/{1}?{2}'.format(API_URL, self.service, params) + + def _sign_request(self): + param_string = self.secret + param_string += flatten_sorted_dict(self.params) + self.params['api_sig'] = md5(param_string).hexdigest() + + def __setitem__(self, key, value): + self.params[key] = value + + def __getitem__(self, key): + return self.params[key] + + def _parse_json_data(self, data): + body = data['rsp'] + status = body['stat'] + + if status == 'fail': + error = APIError(body['err']['msg']) + error.code = int(body['err']['code']) + raise error + + del body['stat'] + + return body + + def execute(self): + data = urllib.urlopen(self.url) + raw_data = data.read() + json_data = json.loads(raw_data) + + return self._parse_json_data(json_data) + + +class Authenticator(object): + + def __init__(self, request_factory): + self.request_factory = request_factory + self.token = None + + def authenticate(self, token=None): + if token: + self.token = token + + if not self.check_token(self.token): + raw_input("Please visit: {0}".format(self.get_auth_url())) + self.token = self.get_token() + + def get_auth_url(self): + req = self.request_factory() + req.service = 'auth' + req['perms'] = APIPerms.DELETE + req['frob'] = self._get_frob() + + return req.url + + def _get_frob(self): + req = self.request_factory() + req['method'] = 'rtm.auth.getFrob' + self.frob = req.execute()['frob'] + + return self.frob + + def get_token(self): + req = self.request_factory() + req['method'] = 'rtm.auth.getToken' + req['frob'] = self.frob + + print req.execute() + + def check_token(self, token): + if not token: + return False + + req = self.request_factory() + req['method'] = 'rtm.auth.checkToken' + req['token'] = token + + try: + req.execute() + return True + except APIError, err: + if err.code == 98: + return False + raise + + +class APIConnection(object): + + def __init__(self, api_key, secret): + self.request_factory = Request.get_factory(api_key, secret) + self.auth = Authenticator(self.request_factory) + + def authenticate(self, token=None): + self.auth.authenticate(token) + print self.auth.token + + def get_lists(self): + req = self.request_factory() + req['method'] = 'rtm.lists.getList' + req['auth_token'] = self.auth.token + + print req.execute() + + + +if __name__ == '__main__': + API_KEY = "38816a01a7937588081d33ea74b6f5ee" + SECRET = "d4caed275cf9a63e" + + TOKEN = "54f3378cb114e6cc330e1c2fd34a11e96e2a26c5" + + api = APIConnection(API_KEY, SECRET) + api.authenticate(TOKEN) + api.get_lists() + diff --git a/milkman/tests/test_auth.py b/milkman/tests/test_auth.py new file mode 100644 index 0000000..8a4e7d2 --- /dev/null +++ b/milkman/tests/test_auth.py @@ -0,0 +1,16 @@ +# vim: set filencoding=utf8 +""" +Authentication Test Suite + +@author: Mike Crute (mcrute@ag.com) +@organization: American Greetings Interactive +@date: February 03, 2010 +""" + +from milkman.auth import flatten_sorted_dict, md5_sign + + +def test_sort_dict(): + input = { 'alpha': '1', 'ahla': '2', 'beta': '3' } + output = flatten_sorted_dict(input) + assert output == 'ahla2alpha1beta3' -- cgit v1.2.3