Select Git revision
yggtorrent.py
yggtorrent.py 6.97 KiB
# coding=utf-8
# Author: adaur <adaur.underground@gmail.com>
# Contributor: PHD <phd59fr@gmail.com>
#
# URL: https://sickrage.github.io
#
# This file is part of SickRage.
#
# SickRage is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# SickRage is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with SickRage. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals
import re
from requests.compat import urljoin
from requests.utils import dict_from_cookiejar
from sickbeard import logger, tvcache
from sickbeard.bs4_parser import BS4Parser
from sickrage.helper.common import convert_size, try_int
from sickrage.providers.torrent.TorrentProvider import TorrentProvider
class YggTorrentProvider(TorrentProvider): # pylint: disable=too-many-instance-attributes
def __init__(self):
# Provider Init
TorrentProvider.__init__(self, 'YggTorrent')
# Credentials
self.username = None
self.password = None
# Torrent Stats
self.minseed = None
self.minleech = None
# URLs
self.url = 'https://ww2.yggtorrent.is/'
self.urls = {
'login': urljoin(self.url, 'user/login'),
'search': urljoin(self.url, 'engine/search')
}
# Proper Strings
self.proper_strings = ['PROPER']
# Cache
self.cache = tvcache.TVCache(self, min_time=30)
def login(self):
login_params = {
'id': self.username,
'pass': self.password,
}
response = self.get_url(self.urls['login'], post_data=login_params, returns='response')
# The login is now an AJAX call (401 : Bad credentials, 200 : Logged in, other : server failure)
if not response or response.status_code != 200:
logger.log('Unable to connect to provider', logger.WARNING)
return False
else:
# It seems we are logged, let's verify that !
response = self.get_url(self.url, returns='response')
if response.status_code != 200:
logger.log('Unable to connect to provider', logger.WARNING)
return False
if 'logout' not in response.text:
logger.log('Invalid username or password. Check your settings', logger.WARNING)
return False
return True
def search(self, search_strings, age=0, ep_obj=None): # pylint: disable=too-many-locals, too-many-branches
results = []
for mode in search_strings:
items = []
logger.log('Search Mode: {0}'.format(mode), logger.DEBUG)
for search_string in search_strings[mode]:
if mode != 'RSS':
logger.log('Search string: {0}'.format
(search_string.decode('utf-8')), logger.DEBUG)
# search string needs to be normalized, single quotes are apparently not allowed on the site
# ç should also be replaced, people tend to use c instead
replace_chars = {
"'": '',
"ç": 'c'
}
for k, v in replace_chars.iteritems():
search_string = search_string.replace(k, v)
logger.log('Sanitized string: {0}'.format
(search_string.decode('utf-8')), logger.DEBUG)
try:
search_params = {
'category': "2145",
'sub_category' : "2184",
'name': re.sub(r'[()]', '', search_string),
'do': 'search'
}
data = self.get_url(self.urls['search'], params=search_params, returns='text')
if not data:
continue
if 'logout' not in data:
logger.log('Refreshing cookies', logger.DEBUG)
self.login()
with BS4Parser(data, 'html5lib') as html:
torrent_table = html.find(class_='table')
torrent_rows = torrent_table('tr') if torrent_table else []
# Continue only if at least one Release is found
if len(torrent_rows) < 2:
logger.log('Data returned from provider does not contain any torrents', logger.DEBUG)
continue
# Skip column headers
for result in torrent_rows[1:]:
cells = result('td')
if len(cells) < 9:
continue
title = cells[1].find('a').get_text(strip=True)
id = cells[2].find('a')['target']
download_url = urljoin(self.url, 'engine/download_torrent?id=' + id)
if not (title and download_url):
continue
seeders = try_int(cells[7].get_text(strip=True))
leechers = try_int(cells[8].get_text(strip=True))
torrent_size = cells[5].get_text()
size = convert_size(torrent_size) or -1
# Filter unseeded torrent
if seeders < self.minseed or leechers < self.minleech:
if mode != 'RSS':
logger.log('Discarding torrent because it doesn\'t meet the minimum seeders or leechers: {0} (S:{1} L:{2})'.format
(title, seeders, leechers), logger.DEBUG)
continue
item = {'title': title, 'link': download_url, 'size': size, 'seeders': seeders, 'leechers': leechers, 'hash': ''}
if mode != 'RSS':
logger.log('Found result: {0} with {1} seeders and {2} leechers'.format
(title, seeders, leechers), logger.DEBUG)
items.append(item)
except (AttributeError, TypeError, KeyError, ValueError):
logger.log('Failed parsing provider {}.'.format(self.name), logger.ERROR)
# For each search mode sort all the items by seeders if available
items.sort(key=lambda d: try_int(d.get('seeders', 0)), reverse=True)
results += items
return results
provider = YggTorrentProvider()