├── MANIFEST.in ├── hulu ├── exceptions.py ├── __init__.py ├── compat.py └── api.py ├── .gitignore ├── setup.py ├── LICENSE └── README.rst /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE README.rst -------------------------------------------------------------------------------- /hulu/exceptions.py: -------------------------------------------------------------------------------- 1 | class HuluError(Exception): 2 | pass 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.py[cod] 2 | 3 | # C extensions 4 | *.so 5 | 6 | # Packages 7 | *.egg 8 | *.egg-info 9 | dist 10 | build 11 | eggs 12 | parts 13 | bin 14 | var 15 | sdist 16 | develop-eggs 17 | .installed.cfg 18 | lib 19 | lib64 20 | __pycache__ 21 | 22 | # Installer logs 23 | pip-log.txt 24 | 25 | # Unit test / coverage reports 26 | .coverage 27 | .tox 28 | nosetests.xml 29 | 30 | # Translations 31 | *.mo 32 | 33 | # Mr Developer 34 | .mr.developer.cfg 35 | .project 36 | .pydevproject 37 | -------------------------------------------------------------------------------- /hulu/__init__.py: -------------------------------------------------------------------------------- 1 | # __ __ __ __ __ __ __ 2 | # /\ \_\ \ /\ \/\ \ /\ \ /\ \/\ \ 3 | # \ \ __ \\ \ \_\ \\ \ \____\ \ \_\ \ 4 | # \ \_\ \_\\ \_____\\ \_____\\ \_____\ 5 | # \/_/\/_/ \/_____/ \/_____/ \/_____/ 6 | 7 | """ 8 | hulu 9 | ---- 10 | 11 | hulu is a Python library to help developers interact with Hulu's "hidden" API. 12 | """ 13 | 14 | __author__ = 'Mike Helmick' 15 | __version__ = '0.1.0' 16 | 17 | from .api import Hulu 18 | from .exceptions import HuluError 19 | -------------------------------------------------------------------------------- /hulu/compat.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | _ver = sys.version_info 4 | 5 | #: Python 2.x? 6 | is_py2 = (_ver[0] == 2) 7 | 8 | #: Python 3.x? 9 | is_py3 = (_ver[0] == 3) 10 | 11 | try: 12 | import simplejson as json 13 | except ImportError: 14 | import json 15 | 16 | if is_py2: 17 | builtin_str = str 18 | bytes = str 19 | str = unicode 20 | basestring = basestring 21 | numeric_types = (int, long, float) 22 | 23 | 24 | elif is_py3: 25 | builtin_str = str 26 | str = str 27 | bytes = bytes 28 | basestring = (str, bytes) 29 | numeric_types = (int, float) 30 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | from setuptools import setup 5 | 6 | packages = [ 7 | 'hulu' 8 | ] 9 | 10 | if sys.argv[-1] == 'publish': 11 | os.system('python setup.py sdist upload') 12 | sys.exit() 13 | 14 | setup( 15 | # Basic package information. 16 | name='hulu', 17 | version='0.1.0', 18 | packages=packages, 19 | include_package_data=True, 20 | install_requires=['requests>=1.0.0, <2.0.0', 'requests_oauthlib==0.3.0'], 21 | author='Mike Helmick', 22 | author_email='me@michaelhelmick.com', 23 | license=open('LICENSE').read(), 24 | url='http://github.com/michaelhelmick/hulu/tree/master', 25 | keywords='hulu python api json', 26 | description='A Python library to interact with Hulu\'s "hidden" 2.0 API.', 27 | long_description=open('README.rst').read(), 28 | classifiers=[ 29 | 'Development Status :: 4 - Beta', 30 | 'Intended Audience :: Developers', 31 | 'License :: OSI Approved :: MIT License', 32 | 'Topic :: Software Development :: Libraries :: Python Modules' 33 | ] 34 | ) 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2013, Mike Helmick 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 5 | 6 | * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 7 | * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 8 | 9 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Hulu 2 | ==== 3 | 4 | ``hulu`` attempts to make it easy for developers to interact with the `Hulu`_ "hidden" 2.0 API 5 | 6 | The Story 7 | --------- 8 | 9 | A friend of mine, (`@adammagana `_) created a PHP library (`found here `_) to interact with the `Hulu`_ "hidden" 1.0 API. The 1.0 API only returns XML, but someone opened up an issue revealing some 2.0 endpoints that return JSON. 10 | 11 | Since JSON is easier to work with in Python than XML is, I took it upon myself to try an open up their API to other developers. 12 | 13 | Features 14 | -------- 15 | 16 | - List companies that have shows/videos on Hulu 17 | - List videos from a specific show 18 | - List trailers available on Hulu 19 | - Find the position of a given video within the shows video list 20 | - (Kind of) Much more! 21 | 22 | Installation 23 | ------------ 24 | 25 | :: 26 | 27 | $ pip install hulu 28 | 29 | Example Usage 30 | ------------- 31 | :: 32 | 33 | from hulu import Hulu 34 | h = HuluAPI() 35 | try: 36 | h.get_companies() 37 | except HuluError as e: 38 | print e 39 | 40 | try: 41 | h.get_video_info(441295) 42 | except HuluError as e: 43 | print e 44 | 45 | 46 | Contribute 47 | ---------- 48 | 49 | If anyone has additional information (such as; paramters taken to given API methods, extra API methods not yet found, etc.) please feel free to open a Pull Request! :) 50 | 51 | TODO 52 | ---- 53 | 54 | - Figure out authentication! 55 | 56 | Some API methods require authentication, yet I haven't been able to figure out how to authenticate to make those API calls, these API calls include: 57 | :: 58 | 59 | api/2.0/plus_upsell.json 60 | api/2.0/favorited_show_ids 61 | api/2.0/queued_video_ids 62 | 63 | 64 | .. _Hulu: http://hulu.com/ 65 | .. _adammagana: https://github.com/adammagana -------------------------------------------------------------------------------- /hulu/api.py: -------------------------------------------------------------------------------- 1 | import requests 2 | 3 | from . import __version__ 4 | from .compat import json 5 | from .exceptions import HuluError 6 | 7 | 8 | class Hulu(object): 9 | def __init__(self): 10 | self.base_url = 'http://www.hulu.com/api/2.0/' 11 | 12 | def _request(self, endpoint, params): 13 | url = self.base_url + endpoint 14 | headers = {'User-Agent': 'Python Hulu v' + __version__} 15 | response = requests.get(url, params=params, headers=headers) 16 | try: 17 | content = json.loads(response.content.decode('utf8')) 18 | except ValueError: 19 | raise HuluError('Unable to decode response, not valid JSON.') 20 | 21 | return content 22 | 23 | def get(self, endpoint, **kwargs): 24 | return self._request(endpoint, params=kwargs) 25 | 26 | def get_companies(self, **kwargs): 27 | """Returns a list of companies that have shows/videos on Hulu""" 28 | return self.get('companies.json', **kwargs) 29 | 30 | def get_video_position_in_show(self, video_id, **kwargs): 31 | """Returns video position in list of videos from the show 32 | 33 | :param video_id: ID of the video you want to obtain the position of 34 | """ 35 | kwargs['video_id'] = video_id 36 | return self.get('video_position_in_show', **kwargs) 37 | 38 | def get_videos(self, **kwargs): 39 | """Returns a list of videos""" 40 | return self.get('videos', **kwargs) 41 | 42 | def get_video_info(self, id, **kwargs): 43 | """Returns information about a specific video 44 | 45 | :param id: ID of the episode you want to obtain the position of 46 | """ 47 | kwargs['id'] = id 48 | return self.get('info/video.json', **kwargs) 49 | 50 | def get_shows(self, **kwargs): 51 | """Returns list of shows available on Hulu""" 52 | return self.get('shows.json', **kwargs) 53 | 54 | def get_show_info(self, id, **kwargs): 55 | """Returns information about a specific show 56 | 57 | :param id: ID of the episode you want to obtain the position of 58 | """ 59 | kwargs['id'] = id 60 | return self.get('info/show.json', **kwargs) 61 | 62 | def get_featured(self, **kwargs): 63 | """Returns featured content""" 64 | return self.get('featured.json', **kwargs) 65 | 66 | def get_video_games(self, **kwargs): 67 | """Returns a list of video games""" 68 | return self.get('video_games.json', **kwargs) 69 | 70 | def get_video_game(self, id, **kwargs): 71 | """Returns information about a specific video game 72 | 73 | :param id: ID of the episode you want to obtain the position of 74 | """ 75 | kwargs['id'] = id 76 | return self.get('video_game.json', **kwargs) 77 | 78 | def get_criterions(self, **kwargs): 79 | """Return a list of criterions""" 80 | return self.get('criterions.json', **kwargs) 81 | 82 | def get_trailers(self, **kwargs): 83 | """Returns a list of trailers available on Hulu""" 84 | return self.get('trailers.json', **kwargs) 85 | --------------------------------------------------------------------------------