diff --git a/sickbeard/providers/extratorrent.py b/sickbeard/providers/extratorrent.py index a34bf7a5b9ffd349c7e4a6d5cf6caca2d64f9256..585a8e13f04e1b81b6bc9c2b2229322b020c4bf6 100644 --- a/sickbeard/providers/extratorrent.py +++ b/sickbeard/providers/extratorrent.py @@ -58,9 +58,6 @@ class ExtraTorrentProvider(generic.TorrentProvider): def isEnabled(self): return self.enabled - def getQuality(self, item, anime=False): - return Quality.sceneQuality(item[0], anime) - def _get_season_search_strings(self, ep_obj): search_string = {'Season': []} @@ -159,7 +156,7 @@ class ExtraTorrentProvider(generic.TorrentProvider): title, url, seeders, leechers, size, info_hash = item return size - def findPropers(self, search_date=datetime.datetime.today()): + def findPropers(self, search_date=datetime.datetime.today()-datetime.timedelta(days=1)): results = [] myDB = db.DBConnection() sqlResults = myDB.select( diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index 0e07817e02e8ca0149f0c40d1380737225f5eed5..b82c8d1e09c83970c8e751e5926781b6aea1a664 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -221,9 +221,9 @@ class KATProvider(generic.TorrentProvider): if show: curEp = show.getEpisode(int(sqlshow["season"]), int(sqlshow["episode"])) - searchString = self._get_episode_search_strings(curEp, add_string='PROPER|REPACK') + searchStrings = self._get_episode_search_strings(curEp, add_string='PROPER|REPACK') - for item in self._doSearch(searchString[0]): + for item in self._doSearch(searchStrings): title, url = self._get_title_and_url(item) pubdate = item[6] diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 90cf5bd761bbb27e613216cd6edb874265a95677..a4f14bcd7c0815307c99e6f0b17d99dfce2299bf 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -19,11 +19,10 @@ from __future__ import with_statement import re -import urllib import datetime import sickbeard -import generic +from sickbeard.providers import generic from sickbeard.common import Quality from sickbeard.common import USER_AGENT from sickbeard import db @@ -32,7 +31,6 @@ from sickbeard import logger from sickbeard import tvcache from sickbeard import helpers from sickbeard.show_name_helpers import allPossibleShowNames, sanitizeSceneName -from unidecode import unidecode class ThePirateBayProvider(generic.TorrentProvider): @@ -45,125 +43,121 @@ class ThePirateBayProvider(generic.TorrentProvider): self.enabled = False self.ratio = None - self.confirmed = False + self.confirmed = True self.minseed = None self.minleech = None self.cache = ThePirateBayCache(self) - self.urls = {'base_url': 'https://thepiratebay.gd/'} + self.urls = { + 'base_url': 'https://thepiratebay.gd/', + 'search': 'https://thepiratebay.gd/s/', + 'rss': 'https://thepiratebay.gd/tv/latest' + } self.url = self.urls['base_url'] - - self.searchurl = self.url + 'search/%s/0/7/200' # order by seed self.headers.update({'User-Agent': USER_AGENT}) - self.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' + """ + 205 = SD, 208 = HD, 200 = All Videos + https://thepiratebay.gd/s/?q=Game of Thrones&type=search&orderby=7&page=0&category=200 + """ + self.search_params = { + 'q': '', + 'type': 'search', + 'orderby': 7, + 'page': 0, + 'category': 200 + } + + self.re_title_url = r'/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?Size (?P<size>[\d\.]* [TGKMiB]{2,3}).+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' def isEnabled(self): return self.enabled - def imageName(self): - return 'thepiratebay.png' - def _get_season_search_strings(self, ep_obj): - search_string = {'Season': []} - for show_name in set(allPossibleShowNames(self.show)): + search_strings = {'Season': []} + for show_name in set(allPossibleShowNames(ep_obj.show)): if ep_obj.show.air_by_date or ep_obj.show.sports: ep_string = show_name + ' ' + str(ep_obj.airdate).split('-')[0] - search_string['Season'].append(ep_string) + search_strings['Season'].append(ep_string) ep_string = show_name + ' Season ' + str(ep_obj.airdate).split('-')[0] - search_string['Season'].append(ep_string) elif ep_obj.show.anime: - ep_string = show_name + ' ' + "%02d" % ep_obj.scene_absolute_number - search_string['Season'].append(ep_string) + ep_string = show_name + ' %02d' % ep_obj.scene_absolute_number else: ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) - search_string['Season'].append(ep_string) + search_strings['Season'].append(ep_string) ep_string = show_name + ' Season ' + str(ep_obj.scene_season) + ' -Ep*' - search_string['Season'].append(ep_string) - search_string['Season'].append(ep_string) + search_strings['Season'].append(ep_string) - return [search_string] + return [search_strings] def _get_episode_search_strings(self, ep_obj, add_string=''): - search_string = {'Episode': []} - - if self.show.air_by_date: - for show_name in set(allPossibleShowNames(self.show)): - ep_string = sanitizeSceneName(show_name) + ' ' + \ - str(ep_obj.airdate).replace('-', ' ') - search_string['Episode'].append(ep_string) - elif self.show.sports: - for show_name in set(allPossibleShowNames(self.show)): - ep_string = sanitizeSceneName(show_name) + ' ' + \ - str(ep_obj.airdate).replace('-', '|') + '|' + \ - ep_obj.airdate.strftime('%b') - search_string['Episode'].append(ep_string) - elif self.show.anime: - for show_name in set(allPossibleShowNames(self.show)): - ep_string = sanitizeSceneName(show_name) + ' ' + \ - "%02i" % int(ep_obj.scene_absolute_number) - search_string['Episode'].append(ep_string) - else: - for show_name in set(allPossibleShowNames(self.show)): - ep_string = sanitizeSceneName(show_name) + ' ' + \ - sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season, - 'episodenumber': ep_obj.scene_episode} + '|' + \ - sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season, - 'episodenumber': ep_obj.scene_episode} + ' %s' % add_string - search_string['Episode'].append(re.sub('\s+', ' ', ep_string)) - - return [search_string] - - def _doSearch(self, search_params, search_mode='eponly', epcount=0, age=0, epObj=None): + search_strings = {'Episode': []} + for show_name in set(allPossibleShowNames(ep_obj.show)): + ep_string = sanitizeSceneName(show_name) + ' ' + if ep_obj.show.air_by_date: + ep_string += str(ep_obj.airdate).replace('-', ' ') + elif ep_obj.show.sports: + ep_string += str(ep_obj.airdate).replace('-', '|') + '|' + ep_obj.airdate.strftime('%b') + elif ep_obj.show.anime: + ep_string += "%02i" % int(ep_obj.scene_absolute_number) + else: + ep_string += sickbeard.config.naming_ep_type[2] % {'seasonnumber': ep_obj.scene_season, + 'episodenumber': ep_obj.scene_episode} + '|' + \ + sickbeard.config.naming_ep_type[0] % {'seasonnumber': ep_obj.scene_season, + 'episodenumber': ep_obj.scene_episode} - results = [] - items = {'Season': [], 'Episode': [], 'RSS': []} + if add_string: + ep_string += ' %s' % add_string + + search_strings['Episode'].append(re.sub(r'\s+', ' ', ep_string).strip()) + + return [search_strings] - for mode in search_params.keys(): - for search_string in search_params[mode]: - if isinstance(search_string, unicode): - search_string = unidecode(search_string) + def _doSearch(self, search_strings, search_mode='eponly', epcount=0, age=0, epObj=None): - if mode != 'RSS': - searchURL = self.searchurl % (urllib.quote(search_string)) - else: - searchURL = self.url + 'tv/latest/' + results = [] + items = {'Season': [], 'Episode': [], 'RSS': []} - logger.log(u"Search string: " + searchURL, logger.DEBUG) + for mode in search_strings.keys(): + for search_string in search_strings[mode]: + self.search_params.update({'q': search_string.strip()}) + logger.log(u"Search string: " + search_string.strip(), logger.DEBUG) - data = self.getURL(searchURL) + data = self.getURL(self.urls[('search', 'rss')[mode == 'RSS']], params=self.search_params) if not data: continue re_title_url = self.proxy._buildRE(self.re_title_url).replace('&f=norefer', '') - matches = re.compile(re_title_url, re.DOTALL).finditer(urllib.unquote(data)) + matches = re.compile(re_title_url, re.DOTALL).finditer(data) for torrent in matches: title = torrent.group('title') url = torrent.group('url') - id = int(torrent.group('id')) + #id = int(torrent.group('id')) + size = self._convertSize(torrent.group('size')) seeders = int(torrent.group('seeders')) leechers = int(torrent.group('leechers')) - #Filter unseeded torrent - if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): - logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(name, seeders, leechers), logger.DEBUG) + # Continue before we check if we need to log anything, + # if there is no url or title. + if not title or not url: continue - #Accept Torrent only from Good People for every Episode Search - if self.confirmed and re.search('(VIP|Trusted|Helper|Moderator)', torrent.group(0)) is None: - logger.log(u"ThePirateBay Provider found result " + torrent.group( - 'title') + " but that doesn't seem like a trusted result so I'm ignoring it", logger.DEBUG) + #Filter unseeded torrent + if not seeders or seeders < self.minseed or leechers < self.minleech: + logger.log(u"Discarding torrent because it doesn't meet the minimum seeders or leechers: {0} (S:{1} L:{2})".format(title, seeders, leechers), logger.DEBUG) continue - if not title or not url: + #Accept Torrent only from Good People for every Episode Search + if self.confirmed and re.search(r'(VIP|Trusted|Helper|Moderator)', torrent.group(0)) is None: + logger.log(u"ThePirateBay Provider found result " + title + " but that doesn't seem like a trusted result so I'm ignoring it", logger.DEBUG) continue - item = title, url, id, seeders, leechers + item = title, url, size, seeders, leechers items[mode].append(item) @@ -174,9 +168,27 @@ class ThePirateBayProvider(generic.TorrentProvider): return results - def _get_title_and_url(self, item): + def _convertSize(self, size): + size, modifier = size.split(' ') + size = float(size) + if modifier in 'KiB': + size = size * 1024 + elif modifier in 'MiB': + size = size * 1024**2 + elif modifier in 'GiB': + size = size * 1024**3 + elif modifier in 'TiB': + size = size * 1024**4 + return size + + def _get_size(self, item): + # pylint: disable=W0612 + title, url, size, seeders, leechers = item + return size - title, url, id, seeders, leechers = item + def _get_title_and_url(self, item): + # pylint: disable=W0612 + title, url, size, seeders, leechers = item if title: title = self._clean_title_from_provider(title) @@ -186,7 +198,7 @@ class ThePirateBayProvider(generic.TorrentProvider): return (title, url) - def findPropers(self, search_date=datetime.datetime.today()): + def findPropers(self, search_date=datetime.datetime.today()-datetime.timedelta(days=1)): results = [] @@ -199,20 +211,14 @@ class ThePirateBayProvider(generic.TorrentProvider): ' OR (e.status IN (' + ','.join([str(x) for x in Quality.SNATCHED]) + ')))' ) - if not sqlResults: - return [] - - for sqlshow in sqlResults: - self.show = helpers.findCertainShow(sickbeard.showList, int(sqlshow["showid"])) - - if self.show: - curEp = self.show.getEpisode(int(sqlshow["season"]), int(sqlshow["episode"])) - - searchString = self._get_episode_search_strings(curEp, add_string='PROPER|REPACK') - - for item in self._doSearch(searchString[0]): + for sqlshow in sqlResults or []: + show = helpers.findCertainShow(sickbeard.showList, int(sqlshow["showid"])) + if show: + curEp = show.getEpisode(int(sqlshow["season"]), int(sqlshow["episode"])) + searchStrings = self._get_episode_search_strings(curEp, add_string='PROPER|REPACK') + for item in self._doSearch(searchStrings): title, url = self._get_title_and_url(item) - results.append(classes.Proper(title, url, search_date, self.show)) + results.append(classes.Proper(title, url, search_date, show)) return results @@ -221,15 +227,15 @@ class ThePirateBayProvider(generic.TorrentProvider): class ThePirateBayCache(tvcache.TVCache): - def __init__(self, provider): + def __init__(self, provider_obj): - tvcache.TVCache.__init__(self, provider) + tvcache.TVCache.__init__(self, provider_obj) - # only poll ThePirateBay every 10 minutes max - self.minTime = 20 + # only poll ThePirateBay every 30 minutes max + self.minTime = 30 def _getRSSData(self): - search_params = {'RSS': ['rss']} + search_params = {'RSS': ['']} return {'entries': self.provider._doSearch(search_params)} provider = ThePirateBayProvider()