forked from michaelhelmick/python-netflix
/
netflix.py
167 lines (125 loc) · 5.96 KB
/
netflix.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
""" Python-Netflix """
'''
For Netflix API documentation, visit: http://developer.netflix.com/docs
'''
__author__ = 'Mike Helmick <mikehelmick@me.com>'
__version__ = '0.3.0'
import urllib
import requests
from requests.auth import OAuth1
try:
from urlparse import parse_qsl
except ImportError:
from cgi import parse_qsl
try:
import simplejson as json
except ImportError:
try:
import json
except ImportError:
try:
from django.utils import simplejson as json
except ImportError:
raise ImportError('A json library is required to use this python library. Lol, yay for being verbose. ;)')
class NetflixAPIError(Exception): pass
class NetflixAuthError(NetflixAPIError): pass
class NetflixAPI(object):
def __init__(self, api_key=None, api_secret=None, oauth_token=None, \
oauth_token_secret=None, callback_url='', headers=None):
self.api_key = api_key and u'%s' % api_key
self.api_secret = api_secret and u'%s' % api_secret
self.oauth_token = oauth_token and u'%s' % oauth_token
self.oauth_token_secret = oauth_token_secret and u'%s' % oauth_token_secret
self.callback_url = callback_url
self.request_token_url = 'http://api.netflix.com/oauth/request_token'
self.access_token_url = 'http://api.netflix.com/oauth/access_token'
self.authorize_url = 'https://api-user.netflix.com/oauth/login'
self.old_api_base = 'http://api.netflix.com/'
self.api_base = 'http://api-public.netflix.com/'
default_headers = {'User-agent': 'Python-Netflix v%s' % __version__}
self.headers = default_headers.update(headers or {})
self.client = requests.session(headers=self.headers)
self.auth = None
if self.api_key is not None and self.api_secret is not None:
self.auth = OAuth1(self.api_key, self.api_secret,
signature_type='auth_header')
if self.oauth_token is not None and self.oauth_token_secret is not None:
self.auth = OAuth1(self.api_key, self.api_secret,
self.oauth_token, self.oauth_token_secret,
signature_type='auth_header')
if self.auth is not None:
self.client = requests.session(headers=self.headers, auth=self.auth)
def get_authentication_tokens(self):
""" Returns an authentication tokens, includes an 'auth_url' for user
"""
url = self.request_token_url + '?oauth_callback=' + self.callback_url
response = self.client.get(url, headers=self.headers, auth=self.auth)
if response.status_code != 200:
raise NetflixAuthError('There was a problem retrieving an authentication url.')
try:
request_tokens = dict(parse_qsl(response.content))
except requests.exceptions.RequestException:
raise NetflixAuthError('Unable to obtain auth tokens.')
auth_url_params = {
'oauth_token': request_tokens['oauth_token'],
'oauth_callback': self.callback_url,
'oauth_consumer_key': self.api_key,
}
request_tokens['auth_url'] = '%s?%s' % (self.authorize_url, urllib.urlencode(auth_url_params))
return request_tokens
def get_auth_tokens(self, oauth_verifier):
""" Returns 'final' tokens to store and used to make authorized calls to Netflix.
"""
url = self.access_token_url + '?oauth_verifier=' + oauth_verifier
try:
response = self.client.get(url, headers=self.headers, auth=self.auth)
except requests.exceptions.RequestException:
raise NetflixAuthError('An unknown error occurred.')
if response.status_code != 200:
raise NetflixAuthError('Getting access tokens failed: %s Response Status' % response.status_code)
try:
auth_tokens = dict(parse_qsl(response.content))
except AttributeError:
raise NetflixAuthError('Unable to obtain auth tokens.')
return auth_tokens
def api_request(self, endpoint, method='GET', params=None):
method = method.lower()
if not method in ('get', 'put', 'post', 'delete'):
raise NetflixAPIError('Method must be of GET, PUT, POST or DELETE')
if endpoint.startswith(self.api_base) or endpoint.startswith(self.old_api_base):
url = endpoint
else:
url = self.api_base + endpoint
params = params or {}
params.update({'output': 'json'})
if method == 'put':
params.update({'method': 'PUT'})
method = 'post'
func = getattr(self.client, method)
try:
if method == 'get':
# After requests is patched with https://github.com/kennethreitz/requests/pull/684
# we can do func(url, params=params)
response = func(url + '?' + urllib.urlencode(params))
else:
response = func(url, data=params)
except requests.exceptions.RequestException:
raise NetflixAPIError('An unknown error occurred.')
status = response.status_code
content = response.content
#try except for if content is able to be decoded
try:
content = json.loads(content)
except ValueError:
raise NetflixAPIError('Content is not valid JSON, unable to be decoded.')
if status < 200 or status >= 300:
raise NetflixAPIError('Code %d: %s' % (status, content['status']['message']))
return dict(content)
def get(self, endpoint, params=None):
return self.api_request(endpoint, params=params)
def put(self, endpoint, params=None):
return self.api_request(endpoint, method='PUT', params=params)
def post(self, endpoint, params=None):
return self.api_request(endpoint, method='POST', params=params)
def delete(self, endpoint, params=None):
return self.api_request(endpoint, method='DELETE', params=params)