├── .gitignore ├── MANIFEST.in ├── README.md ├── README.rst ├── netflix.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.mo 2 | *.egg-info 3 | *.egg 4 | *.EGG 5 | *.EGG-INFO 6 | bin 7 | build 8 | develop-eggs 9 | downloads 10 | eggs 11 | fake-eggs 12 | parts 13 | dist 14 | .installed.cfg 15 | .mr.developer.cfg 16 | .hg 17 | .bzr 18 | .svn 19 | *.pyc 20 | *.pyo 21 | *.tmp* 22 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.rst 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Python-Netflix 2 | ============== 3 | 4 | `Python-Netflix` is a Python library to help interface with [Netflix REST API](http://developer.netflix.com/docs/REST_API_Reference "Netflix REST API") & OAuth 5 | 6 | Installation 7 | ------------ 8 | ``` $ pip install python-netflix``` 9 | 10 | Usage 11 | ----- 12 | 13 | ###### Authorization URL 14 | ```python 15 | n = NetflixAPI(api_key='*your app key*', 16 | api_secret='*your app secret*', 17 | callback_url='http://www.example.com/callback/') 18 | 19 | auth_props = n.get_authentication_tokens() 20 | auth_url = auth_props['auth_url'] 21 | 22 | #Store this token in a session or something for later use in the next step. 23 | oauth_token_secret = auth_props['oauth_token_secret'] 24 | 25 | print 'Connect with Netflix via %s' % auth_url 26 | ``` 27 | 28 | Once you click "Allow" be sure that there is a URL set up to handle getting finalized tokens and possibly adding them to your database to use their information at a later date.' 29 | 30 | ###### Handling the callback 31 | ```python 32 | # In Django, you'd do something like 33 | # oauth_token = request.GET.get('oauth_verifier') 34 | # oauth_verifier = request.GET.get('oauth_verifier') 35 | 36 | oauth_token = *Grab oauth token from URL* 37 | oauth_verifier = *Grab oauth verifier from URL* 38 | 39 | #Initiate the NetflixAPI class in your callback. 40 | n = NetflixAPI(api_key='*your app key*', 41 | api_secret='*your app secret*', 42 | oauth_token=oauth_token, 43 | oauth_token_secret=session['netflix_session_keys']['oauth_token_secret']) 44 | 45 | authorized_tokens = n.get_auth_tokens(oauth_verifier) 46 | 47 | final_oauth_token = authorized_tokens['oauth_token'] 48 | final_oauth_token_secret = authorized_tokens['oauth_token_secret'] 49 | final_user_id = authorized_tokens['user_id'] 50 | 51 | # Save those tokens and user_id to the database for a later use? 52 | ``` 53 | 54 | ###### Return a list of the users Instant Queue. 55 | ```python 56 | # Get the final tokens from the database or wherever you have them stored 57 | 58 | n = NetflixAPI(api_key = '*your app key*', 59 | api_secret = '*your app secret*', 60 | oauth_token=final_tokens['oauth_token'], 61 | oauth_token_secret=final_tokens['oauth_token_secret']) 62 | 63 | 64 | instant_queue = n.get('users/*final_user_id*/queues/instant') 65 | print instant_queue 66 | ``` 67 | 68 | ###### Add Gabriel Iglesias: Hot and Fluffy to Instant Queue 69 | ```python 70 | try: 71 | add_to_queue = n.post('users/*final_user_id*/queues/instant', params={'title_ref': 'http://api.netflix.com/catalog/titles/movies/70072945'}) 72 | 73 | print add_to_queue 74 | 75 | # You can also added "position" to the params to set where this media will be positioned on the users queue. 76 | except NetflixAPIError: 77 | # This returns the added item if successful. 78 | # If it's already in the queue, it will return a NetflixAPIError, code 412 79 | ``` 80 | 81 | ###### Remove Gabriel Iglesias: Hot and Fluffy to Instant Queue 82 | ```python 83 | # When querying for the users Queue, when iterating over the Queue items 84 | # you can use the 'id' for the next call. Where it says *final_user_id* 85 | # that is automatically returned from the Netflix Instant Queue response. 86 | del_from_queue = n.delete('http://api-public.netflix.com/users/*final_user_id*/queues/instant/available/2/70072945') 87 | 88 | print del_from_queue 89 | ``` 90 | 91 | ###### Rate Gabriel Iglesias: Hot and Fluffy 92 | ```python 93 | try: 94 | # Create a new rating 95 | create_rating = n.post('users/*final_user_id*/ratings/title/actual/70072945', params={'rating': '5'}) 96 | 97 | print create_rating 98 | except NetflixAPIError: 99 | # This returns a status message if successful. 100 | # If it's already been rated, it will return a NetflixAPIError, code 422 101 | pass 102 | 103 | 104 | # Update/Clear rating 105 | update_rating = n.put('users/*final_user_id*/ratings/title/actual/70072945', params={'rating': 'no_opinion'}) 106 | 107 | print update_rating 108 | ``` -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Python-Netflix 2 | ============== 3 | 4 | Python-Netflix is a Python Library to interface with `Netflix REST API `_ & OAuth 5 | 6 | Features 7 | -------- 8 | 9 | * Retrieve user information 10 | * Retrieve queue information 11 | * Add items to queue 12 | * And many more, supports all REST endpoints 13 | 14 | 15 | Installation 16 | ------------ 17 | 18 | Installing Python-Netflix is simple: :: 19 | 20 | $ pip install python-netflix 21 | 22 | Usage 23 | ----- 24 | 25 | Authorization URL 26 | ~~~~~~~~~~~~~~~~~ 27 | :: 28 | 29 | n = NetflixAPI(api_key='*your app key*', 30 | api_secret='*your app secret*', 31 | callback_url='http://www.example.com/callback/') 32 | 33 | auth_props = n.get_authentication_tokens() 34 | auth_url = auth_props['auth_url'] 35 | 36 | #Store this token in a session or something for later use in the next step. 37 | oauth_token_secret = auth_props['oauth_token_secret'] 38 | 39 | print 'Connect with Netflix via %s' % auth_url 40 | 41 | Once you click "Allow" be sure that there is a URL set up to handle getting finalized tokens and possibly adding them to your database to use their information at a later date. 42 | 43 | Handling the callback 44 | ~~~~~~~~~~~~~~~~~~~~~ 45 | :: 46 | 47 | # In Django, you'd do something like 48 | # oauth_token = request.GET.get('oauth_verifier') 49 | # oauth_verifier = request.GET.get('oauth_verifier') 50 | 51 | oauth_token = *Grab oauth token from URL* 52 | oauth_verifier = *Grab oauth verifier from URL* 53 | 54 | #Initiate the NetflixAPI class in your callback. 55 | n = NetflixAPI(api_key='*your app key*', 56 | api_secret='*your app secret*', 57 | oauth_token=oauth_token, 58 | oauth_token_secret=session['netflix_session_keys'][ 'oauth_token_secret']) 59 | 60 | authorized_tokens = n.get_auth_tokens(oauth_verifier) 61 | 62 | final_oauth_token = authorized_tokens['oauth_token'] 63 | final_oauth_token_secret = authorized_tokens['oauth_token_secret'] 64 | final_user_id = authorized_tokens['user_id'] 65 | 66 | Save those tokens and user_id to the database for a later use? 67 | 68 | Return a list of the users Instant Queue 69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | :: 71 | 72 | n = NetflixAPI(api_key = '*your app key*', 73 | api_secret = '*your app secret*', 74 | oauth_token=final_tokens['oauth_token'], 75 | oauth_token_secret=final_tokens['oauth_token_secret']) 76 | 77 | instant_queue = n.get('users/*final_user_id*/queues/instant') 78 | print instant_queue 79 | 80 | Add Gabriel Iglesias: Hot and Fluffy to Instant Queue 81 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 82 | :: 83 | 84 | # Assume you are using the same NetflixAPI instance as above 85 | try: 86 | add_to_queue = n.post('users/*final_user_id*/queues/instant', params={'title_ref': 'http://api.netflix.com/catalog/titles/movies/70072945'}) 87 | 88 | print add_to_queue 89 | 90 | # You can also added "position" to the params to set where this media will be positioned on the users queue. 91 | except NetflixAPIError: 92 | # This returns the added item if successful. 93 | # If it's already in the queue, it will return a NetflixAPIError, code 412 94 | 95 | Remove Gabriel Iglesias: Hot and Fluffy to Instant Queue 96 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 97 | :: 98 | 99 | # Assume you are using the same NetflixAPI instance as above 100 | # When querying for the users Queue, when iterating over the Queue items 101 | # you can use the 'id' for the next call. Where it says *final_user_id* 102 | # that is automatically returned from the Netflix Instant Queue response. 103 | 104 | del_from_queue = n.delete('http://api-public.netflix.com/users/*final_user_id*/queues/instant/available/2/70072945') 105 | 106 | print del_from_queue 107 | 108 | Rate Gabriel Iglesias: Hot and Fluffy 109 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 110 | :: 111 | 112 | try: 113 | # Create a new rating 114 | create_rating = n.post('users/*final_user_id*/ratings/title/actual/70072945', params={'rating': '5'}) 115 | 116 | print create_rating 117 | except NetflixAPIError: 118 | # This returns a status message if successful. 119 | # If it's already been rated, it will return a NetflixAPIError, code 422 120 | pass 121 | 122 | 123 | # Update/Clear rating 124 | update_rating = n.put('users/*final_user_id*/ratings/title/actual/70072945', params={'rating': 'no_opinion'}) 125 | 126 | print update_rating -------------------------------------------------------------------------------- /netflix.py: -------------------------------------------------------------------------------- 1 | """ Python-Netflix """ 2 | ''' 3 | For Netflix API documentation, visit: http://developer.netflix.com/docs 4 | ''' 5 | 6 | __author__ = 'Mike Helmick ' 7 | __version__ = '0.3.0' 8 | 9 | import urllib 10 | 11 | import requests 12 | from requests.auth import OAuth1 13 | 14 | try: 15 | from urlparse import parse_qsl 16 | except ImportError: 17 | from cgi import parse_qsl 18 | 19 | try: 20 | import simplejson as json 21 | except ImportError: 22 | try: 23 | import json 24 | except ImportError: 25 | try: 26 | from django.utils import simplejson as json 27 | except ImportError: 28 | raise ImportError('A json library is required to use this python library. Lol, yay for being verbose. ;)') 29 | 30 | 31 | class NetflixAPIError(Exception): pass 32 | class NetflixAuthError(NetflixAPIError): pass 33 | 34 | 35 | class NetflixAPI(object): 36 | def __init__(self, api_key=None, api_secret=None, oauth_token=None, \ 37 | oauth_token_secret=None, callback_url='', headers=None): 38 | 39 | self.api_key = api_key and u'%s' % api_key 40 | self.api_secret = api_secret and u'%s' % api_secret 41 | self.oauth_token = oauth_token and u'%s' % oauth_token 42 | self.oauth_token_secret = oauth_token_secret and u'%s' % oauth_token_secret 43 | self.callback_url = callback_url 44 | 45 | self.request_token_url = 'http://api-public.netflix.com/oauth/request_token' 46 | self.access_token_url = 'http://api-public.netflix.com/oauth/access_token' 47 | self.authorize_url = 'https://api-user.netflix.com/oauth/login' 48 | 49 | self.old_api_base = 'http://api.netflix.com/' 50 | self.api_base = 'http://api-public.netflix.com/' 51 | 52 | default_headers = {'User-agent': 'Python-Netflix v%s' % __version__} 53 | self.headers = default_headers.update(headers or {}) 54 | 55 | self.client = requests.session(headers=self.headers) 56 | self.auth = None 57 | 58 | if self.api_key is not None and self.api_secret is not None: 59 | self.auth = OAuth1(self.api_key, self.api_secret, 60 | signature_type='auth_header') 61 | 62 | if self.oauth_token is not None and self.oauth_token_secret is not None: 63 | self.auth = OAuth1(self.api_key, self.api_secret, 64 | self.oauth_token, self.oauth_token_secret, 65 | signature_type='auth_header') 66 | 67 | if self.auth is not None: 68 | self.client = requests.session(headers=self.headers, auth=self.auth) 69 | 70 | def get_authentication_tokens(self): 71 | """ Returns an authentication tokens, includes an 'auth_url' for user 72 | """ 73 | 74 | url = self.request_token_url + '?oauth_callback=' + self.callback_url 75 | response = self.client.get(url, headers=self.headers, auth=self.auth) 76 | 77 | if response.status_code != 200: 78 | raise NetflixAuthError('There was a problem retrieving an authentication url.') 79 | 80 | try: 81 | request_tokens = dict(parse_qsl(response.content)) 82 | except requests.exceptions.RequestException: 83 | raise NetflixAuthError('Unable to obtain auth tokens.') 84 | 85 | auth_url_params = { 86 | 'oauth_token': request_tokens['oauth_token'], 87 | 'oauth_callback': self.callback_url, 88 | 'oauth_consumer_key': self.api_key, 89 | } 90 | 91 | request_tokens['auth_url'] = '%s?%s' % (self.authorize_url, urllib.urlencode(auth_url_params)) 92 | return request_tokens 93 | 94 | def get_auth_tokens(self, oauth_verifier): 95 | """ Returns 'final' tokens to store and used to make authorized calls to Netflix. 96 | """ 97 | 98 | url = self.access_token_url + '?oauth_verifier=' + oauth_verifier 99 | 100 | try: 101 | response = self.client.get(url, headers=self.headers, auth=self.auth) 102 | except requests.exceptions.RequestException: 103 | raise NetflixAuthError('An unknown error occurred.') 104 | 105 | if response.status_code != 200: 106 | raise NetflixAuthError('Getting access tokens failed: %s Response Status' % response.status_code) 107 | 108 | try: 109 | auth_tokens = dict(parse_qsl(response.content)) 110 | except AttributeError: 111 | raise NetflixAuthError('Unable to obtain auth tokens.') 112 | 113 | return auth_tokens 114 | 115 | def api_request(self, endpoint, method='GET', params=None): 116 | method = method.lower() 117 | if not method in ('get', 'put', 'post', 'delete'): 118 | raise NetflixAPIError('Method must be of GET, PUT, POST or DELETE') 119 | 120 | if endpoint.startswith(self.api_base) or endpoint.startswith(self.old_api_base): 121 | url = endpoint 122 | else: 123 | url = self.api_base + endpoint 124 | 125 | params = params or {} 126 | params.update({'output': 'json'}) 127 | 128 | if method == 'put': 129 | params.update({'method': 'PUT'}) 130 | method = 'post' 131 | 132 | func = getattr(self.client, method) 133 | try: 134 | if method == 'get': 135 | # After requests is patched with https://github.com/kennethreitz/requests/pull/684 136 | # we can do func(url, params=params) 137 | response = func(url + '?' + urllib.urlencode(params)) 138 | else: 139 | response = func(url, data=params) 140 | except requests.exceptions.RequestException: 141 | raise NetflixAPIError('An unknown error occurred.') 142 | 143 | status = response.status_code 144 | content = response.content 145 | 146 | #try except for if content is able to be decoded 147 | try: 148 | content = json.loads(content) 149 | except ValueError: 150 | raise NetflixAPIError('Content is not valid JSON, unable to be decoded.') 151 | 152 | if status < 200 or status >= 300: 153 | raise NetflixAPIError('Code %d: %s' % (status, content['status']['message'])) 154 | 155 | return dict(content) 156 | 157 | def get(self, endpoint, params=None): 158 | return self.api_request(endpoint, params=params) 159 | 160 | def put(self, endpoint, params=None): 161 | return self.api_request(endpoint, method='PUT', params=params) 162 | 163 | def post(self, endpoint, params=None): 164 | return self.api_request(endpoint, method='POST', params=params) 165 | 166 | def delete(self, endpoint, params=None): 167 | return self.api_request(endpoint, method='DELETE', params=params) 168 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | from setuptools import setup 4 | 5 | setup( 6 | name='python-netflix', 7 | version='0.3.0', 8 | install_requires=['requests>=0.13.0', 'simplejson'], 9 | author='Mike Helmick', 10 | author_email='me@michaelhelmick.com', 11 | license='MIT License', 12 | url='https://github.com/michaelhelmick/python-netflix/', 13 | keywords='python netflix oauth api', 14 | description='A Python Library to interface with Netflix REST API & OAuth', 15 | long_description=open('README.rst').read(), 16 | download_url="https://github.com/michaelhelmick/python-netflix/zipball/master", 17 | py_modules=["netflix"], 18 | classifiers=[ 19 | 'Development Status :: 4 - Beta', 20 | 'Intended Audience :: Developers', 21 | 'License :: OSI Approved :: MIT License', 22 | 'Topic :: Software Development :: Libraries :: Python Modules', 23 | 'Topic :: Communications :: Chat', 24 | 'Topic :: Internet' 25 | ] 26 | ) 27 | --------------------------------------------------------------------------------