-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathrdio.py
132 lines (106 loc) · 4.6 KB
/
rdio.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
'''A Python library for accessing the Rdio REST API with OAuth'''
import sys, os
# depends on oauth2 from https://github.com/simplegeo/python-oauth2
import oauth2 as oauth
from cgi import parse_qsl
import urllib, logging
try:
from django.utils import simplejson as json
except:
import json
DEV = False
AUTH = True
class RdioMethod(object):
def __init__(self, name, rdio):
self.name = name
self.rdio = rdio
def __call__(self, **args):
return self.rdio.call(self.name, **args)
class RdioException(BaseException):
pass
class RdioProtocolException(RdioException):
def __init__(self, code, content):
RdioException.__init__(self)
self.code = code
self.content = content
def __str__(self):
return 'RdioProtocolException %s: %s' % (self.code, self.content)
class RdioAPIException(RdioException):
def __init__(self, message):
RdioException.__init__(self, message)
class Rdio(object):
if DEV:
REQUEST_TOKEN='http://rdio-dev.api.mashery.com/oauth/request_token'
ACCESS_TOKEN='http://rdio-dev.api.mashery.com/oauth/access_token'
if AUTH:
API='http://rdio-dev.api.mashery.com/1/'
else:
API='http://localhost:8000/api/1/'
else:
REQUEST_TOKEN='http://api.rdio.com/oauth/request_token'
ACCESS_TOKEN='http://api.rdio.com/oauth/access_token'
API='http://api.rdio.com/1/'
def __init__(self, consumer_token, consumer_secret, data_store):
self.__consumer = oauth.Consumer(consumer_token, consumer_secret)
self.__data_store = data_store
@property
def authenticating(self):
return self.__data_store.has_key('request_token') and self.__data_store['request_token']
@property
def authenticated(self):
return self.__data_store.has_key('access_token') and self.__data_store['access_token']
def begin_authentication(self, callback_url):
assert not self.authenticating and not self.authenticated
resp, content = self.__client().request(Rdio.REQUEST_TOKEN, 'POST',
urllib.urlencode({'oauth_callback':callback_url}))
if resp['status'] != '200':
raise RdioProtocolException(resp['status'], content)
request_token = dict(parse_qsl(content))
self.__data_store['request_token'] = request_token
return (request_token['login_url']+'?oauth_token='+request_token['oauth_token'])
def complete_authentication(self, oauth_verifier):
assert self.authenticating and not self.authenticated
client = self.__client(oauth_verifier)
resp, content = client.request(Rdio.ACCESS_TOKEN, "POST")
if resp['status'] != '200':
raise RdioProtocolException(resp['status'], content)
access_token = dict(parse_qsl(content))
self.__data_store['access_token'] = access_token
del self.__data_store['request_token']
def logout(self):
if self.authenticating:
del self.__data_store['request_token']
if self.authenticated:
del self.__data_store['access_token']
def __client(self, oauth_verifier=None):
token = None
if self.authenticated:
at = self.__data_store['access_token']
token = oauth.Token(at['oauth_token'], at['oauth_token_secret'])
elif self.authenticating:
rt = self.__data_store['request_token']
token = oauth.Token(rt['oauth_token'], rt['oauth_token_secret'])
if token is not None and oauth_verifier is not None:
token.set_verifier(oauth_verifier)
return oauth.Client(self.__consumer, token)
def call(self, method, **args):
'''Call a method on the Rdio service and return the result as a
Python object. If there's an error then throw an appropriate
exception.'''
resp, content = self.call_raw(method, **args)
if resp['status'] != '200':
raise RdioProtocolException(resp['status'], content)
response = json.loads(content)
if response['status'] == 'ok':
return response['result']
else:
raise RdioAPIException(response['message'])
def call_raw(self, method, **args):
'''Call a method on the Rdio service and return the raw HTTP result,
a response object and the content object. See the httplib2 request
method for examples'''
args['method'] = method
client = self.__client()
return client.request(Rdio.API, 'POST', urllib.urlencode(args))
def __getattr__(self, name):
return RdioMethod(name, self)