Source code for flexget.components.sites.sites.torrentleech

from urllib.parse import quote

from loguru import logger
from requests.exceptions import RequestException

from flexget import plugin
from flexget.components.sites.urlrewriting import UrlRewritingError
from flexget.components.sites.utils import normalize_unicode, torrent_availability
from flexget.config_schema import one_or_more
from flexget.entry import Entry
from flexget.event import event
from flexget.plugin import PluginError
from flexget.utils.tools import parse_filesize

logger = logger.bind(name='torrentleech')

CATEGORIES = {
    'all': 0,
    # Movies
    'Cam': 8,
    'TS': 9,
    'TS/TC': 9,
    'DVDRip/DVDScreener': 11,
    'WEBRip': 37,
    'HDRip': 43,
    'BlurayRip': 14,
    'DVD-R': 12,
    'Bluray': 13,
    '4KUpscaled': 41,
    'Real4K': 47,
    'Boxsets': 15,
    'Documentaries': 29,
    # TV
    'Episodes': 26,
    'TV Boxsets': 27,
    'Episodes HD': 32,
}


[docs] class UrlRewriteTorrentleech: """Torrentleech urlrewriter and search plugin. :: torrentleech: rss_key: xxxxxxxxx (required) username: xxxxxxxx (required) password: xxxxxxxx (required) category: HD Category is any combination of: all, Cam, TS, TS/TC, DVDRip, DVDRip/DVDScreener, WEBRip': 37, HDRip': 43, BDRip, DVDR, DVD-R, HD, Bluray, 4KUpscaled, Real4K, Movie Boxsets, Boxsets': 15, Documentaries, Episodes, TV Boxsets, Episodes HD """ schema = { 'type': 'object', 'properties': { 'rss_key': {'type': 'string'}, 'username': {'type': 'string'}, 'password': {'type': 'string'}, 'category': one_or_more({ 'oneOf': [{'type': 'integer'}, {'type': 'string', 'enum': list(CATEGORIES)}] }), }, 'required': ['rss_key', 'username', 'password'], 'additionalProperties': False, } # urlrewriter API
[docs] def url_rewritable(self, task, entry): url = entry['url'] if url.endswith('.torrent'): return False return bool(url.startswith('https://www.torrentleech.org/'))
# urlrewriter API
[docs] def url_rewrite(self, task, entry): if 'url' not in entry: logger.error("Didn't actually get a URL...") else: logger.debug('Got the URL: {}', entry['url']) if entry['url'].startswith('https://www.torrentleech.org/torrents/browse/list/query/'): # use search results = self.search(task, entry) if not results: raise UrlRewritingError('No search results found') # TODO: Search doesn't enforce close match to title, be more picky entry['url'] = results[0]['url']
@plugin.internet(logger) def search(self, task, entry, config=None): """Search for name from torrentleech.""" request_headers = {'User-Agent': 'curl/7.54.0'} rss_key = config['rss_key'] # build the form request: data = {'username': config['username'], 'password': config['password']} # POST the login form: try: login = task.requests.post( 'https://www.torrentleech.org/user/account/login/', data=data, headers=request_headers, allow_redirects=True, ) except RequestException as e: raise PluginError(f'Could not connect to torrentleech: {e!s}') if login.url.endswith('/user/account/login/'): raise PluginError('Could not login to torrentleech, faulty credentials?') if not isinstance(config, dict): config = {} # sort = SORT.get(config.get('sort_by', 'seeds')) # if config.get('sort_reverse'): # sort += 1 categories = config.get('category', 'all') # Make sure categories is a list if not isinstance(categories, list): categories = [categories] # If there are any text categories, turn them into their id number categories = [c if isinstance(c, int) else CATEGORIES[c] for c in categories] filter_url = '/categories/{}'.format(','.join(str(c) for c in categories)) entries = set() for search_string in entry.get('search_strings', [entry['title']]): query = normalize_unicode(search_string).replace(':', '') # urllib.quote will crash if the unicode string has non ascii characters, # so encode in utf-8 beforehand url = ( 'https://www.torrentleech.org/torrents/browse/list/query/' + quote(query.encode('utf-8')) + filter_url ) logger.debug('Using {} as torrentleech search url', url) results = task.requests.get(url, headers=request_headers, cookies=login.cookies).json() for torrent in results['torrentList']: entry = Entry() entry['download_headers'] = request_headers entry['title'] = torrent['name'] # construct download URL torrent_url = 'https://www.torrentleech.org/rss/download/{}/{}/{}'.format( torrent['fid'], rss_key, torrent['filename'] ) logger.debug('RSS-ified download link: {}', torrent_url) entry['url'] = torrent_url # seeders/leechers entry['torrent_seeds'] = torrent['seeders'] entry['torrent_leeches'] = torrent['leechers'] entry['torrent_availability'] = torrent_availability( entry['torrent_seeds'], entry['torrent_leeches'] ) entry['content_size'] = parse_filesize(str(torrent['size']) + ' b') entries.add(entry) return sorted(entries, reverse=True, key=lambda x: x.get('torrent_availability'))
[docs] @event('plugin.register') def register_plugin(): plugin.register( UrlRewriteTorrentleech, 'torrentleech', interfaces=['urlrewriter', 'search'], api_ver=2 )