├── .gitignore ├── LICENSE ├── MANIFEST.in ├── README.md ├── Torapi ├── Filters.py ├── Torapi.py └── __init__.py ├── requirements.txt ├── setup.py └── torapi_test.py /.gitignore: -------------------------------------------------------------------------------- 1 | *.pyc 2 | *.pyo 3 | *.DS_Store 4 | *.log 5 | #*# 6 | Thumbs.db 7 | /*.egg-info/ 8 | /build/ 9 | /dist/ 10 | /.idea/ 11 | /.venv/ 12 | /.vscode/ 13 | /env/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2016 Eugene Tan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include README.md LICENSE -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Torapi 2 | ============ 3 | 4 | Unofficial http://torrentapi.org/ API library 5 | 6 | https://torrentapi.org/apidocs_v2.txt 7 | 8 | **The api has a 1req/2s limit.** 9 | 10 | Installation 11 | ------------ 12 | 13 | ``` 14 | pip install requests 15 | python setup.py install 16 | 17 | Run this to test if it was successful 18 | python torapi_test.py 19 | 20 | Successful if no error returns 21 | ``` 22 | 23 | Usage 24 | ------------ 25 | 26 | ```python 27 | from Torapi import Torapi 28 | from Torapi.Filters import * 29 | import time 30 | 31 | t = Torapi() 32 | 33 | # Everything is returned in JSON 34 | # !! IMPORTANT: Notice the time.sleep(1) before each Get() request 35 | # !! The api has a 1req/2s limit. 36 | 37 | # Returning a simple list 38 | time.sleep(1) 39 | t.Get() 40 | 41 | time.sleep(1) 42 | t.List().Get() 43 | 44 | # Searches 45 | # Simple Torrent search 46 | time.sleep(1) 47 | t.Search('torrent name').Get() 48 | 49 | time.sleep(1) 50 | t.SearchIMDB("tt123456").Get() # Searches movie id from http://www.imdb.com/ 51 | 52 | time.sleep(1) 53 | t.SearchTVDB("123456").Get() # Searches http://thetvdb.com/ 54 | 55 | time.sleep(1) 56 | t.SearchTheMovieDB("123456").Get() # Searches https://www.themoviedb.org/ 57 | 58 | # Filtering searches and list 59 | 60 | # By category 61 | time.sleep(1) 62 | t.List().Category(Category.ALL).Get() # Returns list of torrents from a category (More categories below) 63 | 64 | time.sleep(1) 65 | t.Search('torrent name').Category(Category.ALL).Get() 66 | 67 | # Limit 68 | # 25, 50 or 100 69 | time.sleep(1) 70 | t.List().Limit(25).Get() 71 | 72 | # Sorting 73 | # Seeders, leechers or last 74 | time.sleep(1) 75 | t.List().Sort(Sort.LAST).Get() 76 | 77 | # Minimum seeders/leechers 78 | time.sleep(1) 79 | t.List().MinSeeders(10).Get() 80 | 81 | time.sleep(1) 82 | t.List().MinLeechers(10).Get() 83 | 84 | # Extended JSON information 85 | time.sleep(1) 86 | t.List().Extended(True).Get() # Returns a list of torrents with extended information 87 | 88 | # Ranked torrents 89 | # Information from https://torrentapi.org/apidocs_v2.txt 90 | # By default the api will return only ranked torrents ( internal ) , scene releases + -rarbg releases + -rartv releases. 91 | # If you want other groups included in the results use the ranked parameter with a value of 0 to get them included. 92 | time.sleep(1) 93 | t.List().Ranked(False).Get() 94 | 95 | # All methods can be mixed together in any order 96 | time.sleep(1) 97 | t.List().Limit(25).Sort(Sort.LAST).Ranked(False).Extended(True).Get() 98 | 99 | # Every method can be simplified with just Get() 100 | time.sleep(1) 101 | t.Get(search_string = "Torrent Name", search_IMDB = "tt123456", search_TVDB = "123456", search_moviedb = "123456", 102 | category = Category.ALL, limit = 25, sort = Sort.LAST, min_seeders = 10, min_leechers = 10, extended = False, 103 | ranked = True) 104 | ``` 105 | 106 | Categories 107 | ------------ 108 | 109 | Category.* 110 | 111 | * ALL 112 | * XXX 113 | * NON_XXX 114 | * MUSIC 115 | * MUSIC_MP3 116 | * MUSIC_FLAC 117 | * EBOOKS 118 | * MOVIES 119 | * MOVIES_FULL_BD 120 | * MOVIES_X264_1080 121 | * MOVIES_X264_720 122 | * MOVIES_BD_REMUX 123 | * MOVIES_X264_3D 124 | * MOVIES_XVID_720 125 | * MOVIES_XVID 126 | * MOVIES_X264 127 | * TV 128 | * TV_SHOWS 129 | * TV_EPISODES 130 | * TV_HD_EPISODES 131 | * GAMES 132 | * GAMES_PS3 133 | * GAMES_PC_ISO 134 | * GAMES_PC_RIP 135 | * GAMES_XBOX360 136 | * SOFTWARE 137 | * SOFTWARE_PC_ISO 138 | ``` 139 | -------------------------------------------------------------------------------- /Torapi/Filters.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | class Category(object): 3 | XXX = "4" 4 | MOVIES_XVID = "14" 5 | MOVIES_X264 = "17" 6 | TV_EPISODES = "18" 7 | MUSIC_MP3 = "23" 8 | MUSIC_FLAC = "25" 9 | GAMES_PC_ISO = "27" 10 | GAMES_PC_RIP = "28" 11 | GAMES_XBOX360 = "32" 12 | SOFTWARE_PC_ISO = "33" 13 | EBOOKS = "35" 14 | GAMES_PS3 = "40" 15 | TV_HD_EPISODES = "41" 16 | MOVIES_FULL_BD = "42" 17 | MOVIES_X264_1080 = "44" 18 | MOVIES_X264_720 = "45" 19 | MOVIES_BD_REMUX = "46" 20 | MOVIES_X264_3D = "47" 21 | MOVIES_XVID_720 = "48" 22 | MOVIES = "movies" 23 | TV = "tv" 24 | TV_SHOWS = "1;18;41" 25 | GAMES = "1;27;28;29;30;31;32;40" 26 | MUSIC = "1;23;24;25;26" 27 | SOFTWARE = "1;33;34;43" 28 | NON_XXX = "1;14;15;16;17;21;22;42;18;19;41;27;28;29;30;31;32;40;23;24;25;26;33;34;43;44;45;46;47;48" 29 | ALL = "1;4;14;15;16;17;21;22;42;18;19;41;27;28;29;30;31;32;40;23;24;25;26;33;34;43;44;45;46;47;48" 30 | 31 | class Sort(object): 32 | SEEDERS = "seeders" 33 | LEECHERS = "leechers" 34 | LAST = "last" -------------------------------------------------------------------------------- /Torapi/Torapi.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #!/usr/bin/env python 3 | import requests 4 | from Filters import Category, Sort 5 | 6 | # Torapi().Search(filter).json(); 7 | class Torapi(object): 8 | def __init__(self, *args): 9 | super(Torapi, self).__init__(*args) 10 | self.Filter = "" 11 | self._searched = False 12 | 13 | def List(self): 14 | self.Filter = self.Filter + "&mode=list" 15 | return self 16 | 17 | def SearchTheMovieDB(self, id): 18 | self.Filter = self.Filter + "&mode=search&search_themoviedb={0}".format(id) 19 | self._searched = True 20 | return self 21 | 22 | def SearchIMDB(self, id): 23 | self.Filter = self.Filter + "&mode=search&search_imdb={0}".format(id) 24 | self._searched = True 25 | return self 26 | 27 | def SearchTVDB(self, id): 28 | self.Filter = self.Filter + "&mode=search&search_tvdb={0}".format(id) 29 | self._searched = True 30 | return self 31 | 32 | def Search(self, string): 33 | self.Filter = self.Filter + "&mode=search&search_string={0}".format(string) 34 | self._searched = True 35 | return self 36 | 37 | def Category(self, category = Category.ALL): 38 | self.Filter = self.Filter + "&category=" + category 39 | return self 40 | 41 | def Limit(self, integer = 25): 42 | self.Filter = self.Filter + "&limit=" + str(integer) 43 | return self 44 | 45 | def Sort(self, sort = Sort.LAST): 46 | self.Filter = self.Filter + "&sort=" + sort 47 | return self 48 | 49 | def MinSeeders(self, integer = 0): 50 | self.Filter = self.Filter + "&min_seeders={0}".format(integer) 51 | return self 52 | 53 | def MinLeechers(self, integer = 0): 54 | self.Filter = self.Filter + "&min_leechers={0}".format(integer) 55 | return self 56 | 57 | def Extended(self, boolean = False): 58 | if boolean: 59 | self.Filter = self.Filter + "&format=json_extended" 60 | else: 61 | self.Filter = self.Filter + "&format=json" 62 | return self 63 | 64 | def Ranked(self, boolean = True): 65 | if boolean: 66 | self.Filter = self.Filter + "&ranked=1" 67 | else: 68 | self.Filter = self.Filter + "&ranked=0" 69 | return self 70 | 71 | def Get(self, search_string = None, search_IMDB = None, search_TVDB = None, search_moviedb = None, 72 | category = None, limit = None, sort = None, min_seeders = None, min_leechers = None, extended = False, 73 | ranked = True): 74 | if not search_string and not search_IMDB and not search_TVDB and not search_moviedb and not self._searched: 75 | self.List() 76 | 77 | if search_string: 78 | self.Search(search_string) 79 | 80 | if search_IMDB: 81 | self.SearchIMDB(search_IMDB) 82 | 83 | if search_TVDB: 84 | self.SearchTVDB(search_TVDB) 85 | 86 | if search_moviedb: 87 | self.SearchTheMovieDB(search_moviedb) 88 | 89 | if category: 90 | self.Category(category) 91 | 92 | if limit: 93 | self.Limit(limit) 94 | 95 | if sort: 96 | self.Sort(sort) 97 | 98 | if min_seeders: 99 | self.MinSeeders(min_seeders) 100 | 101 | if min_leechers: 102 | self.MinLeechers(min_leechers) 103 | 104 | if extended: 105 | self.Extended(extended) 106 | 107 | if not ranked: 108 | self.Ranked(ranked) 109 | 110 | request = session.get(BASE_URL + "?app_id=Torapi&token=" + TOKEN + self.Filter) 111 | return request.json() 112 | 113 | @staticmethod 114 | def GetToken(): 115 | """ Gets a token required to make other requests """ 116 | request = session.get(BASE_URL, params={'app_id': 'Torapi', 'get_token': 'get_token'}) 117 | token = request.json()["token"] 118 | return token 119 | 120 | BASE_URL = "https://torrentapi.org/pubapi_v2.php" 121 | 122 | session = requests.Session() 123 | session.headers.update({'Accept': 'application/json', 'User-Agent': 'Torapi/Torapi'}) 124 | TOKEN = Torapi.GetToken() -------------------------------------------------------------------------------- /Torapi/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Torapi 4 | ~~~~~~~ 5 | Unofficial simple http://torrentapi.org/ API library 6 | 7 | MIT License 8 | 9 | Copyright (c) 2016 Eugene Tan 10 | 11 | Permission is hereby granted, free of charge, to any person obtaining a copy 12 | of this software and associated documentation files (the "Software"), to deal 13 | in the Software without restriction, including without limitation the rights 14 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | copies of the Software, and to permit persons to whom the Software is 16 | furnished to do so, subject to the following conditions: 17 | 18 | The above copyright notice and this permission notice shall be included in all 19 | copies or substantial portions of the Software. 20 | 21 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 22 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 23 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 24 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 25 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 26 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 27 | SOFTWARE. 28 | """ 29 | __version__ = '1.0.0' 30 | __author__ = 'Yuuji' 31 | __email__ = 'hello@yuuyu.dev' 32 | 33 | from Torapi import Torapi 34 | from Filters import * -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | requests==2.22.0 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | try: 3 | from setuptools import setup 4 | except ImportError: 5 | from distutils.core import setup 6 | 7 | # patch distutils if it can't cope with the "classifiers" or 8 | # "download_url" keywords 9 | from sys import version 10 | if version < '2.2.3': 11 | from distutils.dist import DistributionMetadata 12 | DistributionMetadata.classifiers = None 13 | DistributionMetadata.download_url = None 14 | 15 | from Torapi import __version__, __author__, __email__ 16 | 17 | license_text = open('LICENSE').read() 18 | long_description = open('README.md').read() 19 | 20 | setup( 21 | name='Torapi', 22 | version=__version__, 23 | url = 'https://github.com/Yuuyuuei/Torapi', 24 | install_requires=['requests'], 25 | author=__author__, 26 | author_email=__email__, 27 | description='Unofficial simple http://torrentapi.org/ API library', 28 | long_description=long_description, 29 | license=license_text, 30 | packages=['Torapi'], 31 | data_files=[('Torapi', ['LICENSE', 'README.md'])], 32 | classifiers=[ 33 | 'Development Status :: 4 - Beta', 34 | 'License :: OSI Approved :: MIT License', 35 | 'Intended Audience :: Developers', 36 | 'Programming Language :: Python', 37 | 'Programming Language :: Python :: 2.7' 38 | ] 39 | ) 40 | -------------------------------------------------------------------------------- /torapi_test.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | from Torapi import Torapi 3 | from Torapi.Filters import * 4 | import time 5 | 6 | # !! IMPORTANT: Notice the time.sleep(1) before each Get() request 7 | 8 | t = Torapi() 9 | 10 | # Everything is returned in JSON 11 | 12 | # Returning a simple list 13 | time.sleep(1) 14 | t.Get() 15 | 16 | time.sleep(1) 17 | t.List().Get() 18 | 19 | # Searches 20 | # Simple Torrent search 21 | time.sleep(1) 22 | t.Search('torrent name').Get() 23 | 24 | time.sleep(1) 25 | t.SearchIMDB("tt123456").Get() # Searches movie id from http://www.imdb.com/ 26 | 27 | time.sleep(1) 28 | t.SearchTVDB("123456").Get() # Searches http://thetvdb.com/ 29 | 30 | time.sleep(1) 31 | t.SearchTheMovieDB("123456").Get() # Searches https://www.themoviedb.org/ 32 | 33 | # Filtering searches and list 34 | 35 | # By category 36 | time.sleep(1) 37 | t.List().Category(Category.ALL).Get() # Returns list of torrents from a category (More categories below) 38 | 39 | time.sleep(1) 40 | t.Search('torrent name').Category(Category.ALL).Get() 41 | 42 | # Limit 43 | # 25, 50 or 100 44 | time.sleep(1) 45 | t.List().Limit(25).Get() 46 | 47 | # Sorting 48 | # Seeders, leechers or last 49 | time.sleep(1) 50 | t.List().Sort(Sort.LAST).Get() 51 | 52 | # Minimum seeders/leechers 53 | time.sleep(1) 54 | t.List().MinSeeders(10).Get() 55 | 56 | time.sleep(1) 57 | t.List().MinLeechers(10).Get() 58 | 59 | # Extended JSON information 60 | time.sleep(1) 61 | t.List().Extended(True).Get() # Returns a list of torrents with extended information 62 | 63 | # Ranked torrents 64 | # Information from https://torrentapi.org/apidocs_v2.txt 65 | # By default the api will return only ranked torrents ( internal ) , scene releases + -rarbg releases + -rartv releases. 66 | # If you want other groups included in the results use the ranked parameter with a value of 0 to get them included. 67 | time.sleep(1) 68 | t.List().Ranked(False).Get() 69 | 70 | # All methods can be mixed together in any order 71 | time.sleep(1) 72 | t.List().Limit(25).Sort(Sort.LAST).Ranked(False).Extended(True).Get() 73 | 74 | # Every method can be simplified with just Get() 75 | time.sleep(1) 76 | t.Get(search_string = "Torrent Name", search_IMDB = "tt123456", search_TVDB = "123456", search_moviedb = "123456", 77 | category = Category.ALL, limit = 25, sort = Sort.LAST, min_seeders = 10, min_leechers = 10, extended = False, 78 | ranked = True) --------------------------------------------------------------------------------