From 0d90a821d58387783609e685cf654fa769b92854 Mon Sep 17 00:00:00 2001 From: Martin Warnaar Date: Sat, 31 Jan 2015 19:48:20 +0100 Subject: [PATCH 1/3] Added separate providers for thepiratebay and oldpiratebay --- gui/slick/images/providers/oldpiratebay.png | Bin 0 -> 3745 bytes sickbeard/__init__.py | 2 +- sickbeard/providers/__init__.py | 1 + sickbeard/providers/oldpiratebay.py | 340 ++++++++++++++++++++ sickbeard/providers/thepiratebay.py | 12 +- 5 files changed, 347 insertions(+), 8 deletions(-) create mode 100644 gui/slick/images/providers/oldpiratebay.png create mode 100644 sickbeard/providers/oldpiratebay.py diff --git a/gui/slick/images/providers/oldpiratebay.png b/gui/slick/images/providers/oldpiratebay.png new file mode 100644 index 0000000000000000000000000000000000000000..6e52fd53d9bae6e991c591d14a1a61af8f640c77 GIT binary patch literal 3745 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 LNkvXXu0mjfW#b{k literal 0 HcmV?d00001 diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 8ab13859..6d339ea3 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -32,7 +32,7 @@ from github import Github from sickbeard import providers, metadata, config, webserveInit from sickbeard.providers.generic import GenericProvider -from providers import ezrss, btn, newznab, womble, thepiratebay, torrentleech, kat, iptorrents, \ +from providers import ezrss, btn, newznab, womble, thepiratebay, oldpiratebay, torrentleech, kat, iptorrents, \ omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, hounddawgs, nextgen, speedcd, nyaatorrents, fanzub, torrentbytes, animezb, \ freshontv, bitsoup, t411, tokyotoshokan from sickbeard.config import CheckSection, check_setting_int, check_setting_str, check_setting_float, ConfigMigrator, \ diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 8c6ffc66..a1d5474c 100755 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -20,6 +20,7 @@ __all__ = ['ezrss', 'womble', 'btn', 'thepiratebay', + 'oldpiratebay', 'kat', 'torrentleech', 'scc', diff --git a/sickbeard/providers/oldpiratebay.py b/sickbeard/providers/oldpiratebay.py new file mode 100644 index 00000000..fb0a6503 --- /dev/null +++ b/sickbeard/providers/oldpiratebay.py @@ -0,0 +1,340 @@ +# Author: Mr_Orange +# URL: http://code.google.com/p/sickbeard/ +# +# 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 . + +from __future__ import with_statement + +import time +import re +import urllib, urllib2, urlparse +import sys +import os +import datetime + +import sickbeard +import generic +from sickbeard.common import Quality, cpu_presets +from sickbeard.name_parser.parser import NameParser, InvalidNameException, InvalidShowException +from sickbeard import db +from sickbeard import classes +from sickbeard import logger +from sickbeard import tvcache +from sickbeard import helpers +from sickbeard import clients +from sickbeard.show_name_helpers import allPossibleShowNames, sanitizeSceneName +from sickbeard.common import Overview +from sickbeard.exceptions import ex +from sickbeard import encodingKludge as ek +from lib import requests +from lib.requests import exceptions +from lib.unidecode import unidecode + + +class OldPirateBayProvider(generic.TorrentProvider): + def __init__(self): + + generic.TorrentProvider.__init__(self, "OldPirateBay") + + self.supportsBacklog = True + + self.enabled = False + self.ratio = None + self.confirmed = False + self.minseed = None + self.minleech = None + + self.cache = OldPirateBayCache(self) + + self.urls = {'base_url': 'https://oldpiratebay.org/'} + + self.url = self.urls['base_url'] + + self.searchurl = self.url + 'search.php?q=%s&Torrent_sort=seeders.desc' # order by seed + + self.re_title_url = '/torrent/(?P\d+)/(?P.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' + + def isEnabled(self): + return self.enabled + + def imageName(self): + return 'oldpiratebay.png' + + def getQuality(self, item, anime=False): + + quality = Quality.sceneQuality(item[0], anime) + return quality + + def _reverseQuality(self, quality): + + quality_string = '' + + if quality == Quality.SDTV: + quality_string = 'HDTV x264' + if quality == Quality.SDDVD: + quality_string = 'DVDRIP' + elif quality == Quality.HDTV: + quality_string = '720p HDTV x264' + elif quality == Quality.FULLHDTV: + quality_string = '1080p HDTV x264' + elif quality == Quality.RAWHDTV: + quality_string = '1080i HDTV mpeg2' + elif quality == Quality.HDWEBDL: + quality_string = '720p WEB-DL h264' + elif quality == Quality.FULLHDWEBDL: + quality_string = '1080p WEB-DL h264' + elif quality == Quality.HDBLURAY: + quality_string = '720p Bluray x264' + elif quality == Quality.FULLHDBLURAY: + quality_string = '1080p Bluray x264' + + return quality_string + + def _find_season_quality(self, title, torrent_id, ep_number): + """ Return the modified title of a Season Torrent with the quality found inspecting torrent file list """ + + mediaExtensions = ['avi', 'mkv', 'wmv', 'divx', + 'vob', 'dvr-ms', 'wtv', 'ts' + 'ogv', 'rar', 'zip', 'mp4'] + + quality = Quality.UNKNOWN + + fileName = None + + fileURL = self.url + 'ajax_details_filelist.php?id=' + str(torrent_id) + data = self.getURL(fileURL) + if not data: + return None + + filesList = re.findall('<td.+>(.*?)</td>', data) + + if not filesList: + logger.log(u"Unable to get the torrent file list for " + title, logger.ERROR) + + videoFiles = filter(lambda x: x.rpartition(".")[2].lower() in mediaExtensions, filesList) + + #Filtering SingleEpisode/MultiSeason Torrent + if len(videoFiles) < ep_number or len(videoFiles) > float(ep_number * 1.1): + logger.log( + u"Result " + title + " have " + str(ep_number) + " episode and episodes retrived in torrent are " + str( + len(videoFiles)), logger.DEBUG) + logger.log(u"Result " + title + " Seem to be a Single Episode or MultiSeason torrent, skipping result...", + logger.DEBUG) + return None + + if Quality.sceneQuality(title) != Quality.UNKNOWN: + return title + + for fileName in videoFiles: + quality = Quality.sceneQuality(os.path.basename(fileName)) + if quality != Quality.UNKNOWN: break + + if fileName is not None and quality == Quality.UNKNOWN: + quality = Quality.assumeQuality(os.path.basename(fileName)) + + if quality == Quality.UNKNOWN: + logger.log(u"Unable to obtain a Season Quality for " + title, logger.DEBUG) + return None + + try: + myParser = NameParser(showObj=self.show) + parse_result = myParser.parse(fileName) + except (InvalidNameException, InvalidShowException): + return None + + logger.log(u"Season quality for " + title + " is " + Quality.qualityStrings[quality], logger.DEBUG) + + if parse_result.series_name and parse_result.season_number: + title = parse_result.series_name + ' S%02d' % int(parse_result.season_number) + ' ' + self._reverseQuality( + quality) + + return title + + def _get_season_search_strings(self, ep_obj): + + search_string = {'Season': []} + for show_name in set(allPossibleShowNames(self.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) + 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) + else: + ep_string = show_name + ' S%02d' % int(ep_obj.scene_season) + search_string['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) + + return [search_string] + + 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): + + results = [] + items = {'Season': [], 'Episode': [], 'RSS': []} + + for mode in search_params.keys(): + for search_string in search_params[mode]: + if isinstance(search_string, unicode): + search_string = unidecode(search_string) + + if mode != 'RSS': + searchURL = self.searchurl % (urllib.quote(search_string)) + else: + searchURL = self.url + 'tv/latest/' + + logger.log(u"Search string: " + searchURL, logger.DEBUG) + + data = self.getURL(searchURL) + if not data: + continue + + re_title_url = self.proxy._buildRE(self.re_title_url) + + match = re.compile(re_title_url, re.DOTALL).finditer(urllib.unquote(data)) + + for torrent in match: + title = torrent.group('title').replace('_', + '.') #Do not know why but SickBeard skip release with '_' in name + url = torrent.group('url') + print 'torrent url: ' + url + id = int(torrent.group('id')) + seeders = int(torrent.group('seeders')) + leechers = int(torrent.group('leechers')) + + #Filter unseeded torrent + if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): + 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"OldPirateBay Provider found result " + torrent.group( + 'title') + " but that doesn't seem like a trusted result so I'm ignoring it", logger.DEBUG) + continue + + #Check number video files = episode in season and find the real Quality for full season torrent analyzing files in torrent + if mode == 'Season' and search_mode == 'sponly': + ep_number = int(epcount / len(set(allPossibleShowNames(self.show)))) + title = self._find_season_quality(title, id, ep_number) + + if not title or not url: + continue + + item = title, url, id, seeders, leechers + + items[mode].append(item) + + #For each search mode sort all the items by seeders + items[mode].sort(key=lambda tup: tup[3], reverse=True) + + results += items[mode] + + return results + + def _get_title_and_url(self, item): + + title, url, id, seeders, leechers = item + + if title: + title = u'' + title.replace(' ', '.') + + if url: + url = url.replace('&', '&') + + return (title, url) + + def findPropers(self, search_date=datetime.datetime.today()): + + results = [] + + myDB = db.DBConnection() + sqlResults = myDB.select( + 'SELECT s.show_name, e.showid, e.season, e.episode, e.status, e.airdate FROM tv_episodes AS e' + + ' INNER JOIN tv_shows AS s ON (e.showid = s.indexer_id)' + + ' WHERE e.airdate >= ' + str(search_date.toordinal()) + + ' AND (e.status IN (' + ','.join([str(x) for x in Quality.DOWNLOADED]) + ')' + + ' 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]): + title, url = self._get_title_and_url(item) + results.append(classes.Proper(title, url, datetime.datetime.today(), self.show)) + + return results + + def seedRatio(self): + return self.ratio + + +class OldPirateBayCache(tvcache.TVCache): + def __init__(self, provider): + + tvcache.TVCache.__init__(self, provider) + + # only poll OldPirateBay every 10 minutes max + self.minTime = 20 + + def _getRSSData(self): + search_params = {'RSS': ['rss']} + return {'entries': self.provider._doSearch(search_params)} + +provider = OldPirateBayProvider() diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 1d5df98b..52f0da0c 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -59,11 +59,11 @@ class ThePirateBayProvider(generic.TorrentProvider): self.cache = ThePirateBayCache(self) - self.urls = {'base_url': 'https://oldpiratebay.org/'} + self.urls = {'base_url': 'https://thepiratebay.se/'} self.url = self.urls['base_url'] - self.searchurl = self.url + 'search.php?q=%s&Torrent_sort=seeders.desc' # order by seed + self.searchurl = self.url + 'search/%s/0/7/200' # order by seed self.re_title_url = '/torrent/(?P<id>\d+)/(?P<title>.*?)//1".+?(?P<url>magnet.*?)//1".+?(?P<seeders>\d+)</td>.+?(?P<leechers>\d+)</td>' @@ -231,6 +231,7 @@ class ThePirateBayProvider(generic.TorrentProvider): else: searchURL = self.url + 'tv/latest/' + print searchURL logger.log(u"Search string: " + searchURL, logger.DEBUG) data = self.getURL(searchURL) @@ -238,17 +239,14 @@ class ThePirateBayProvider(generic.TorrentProvider): continue re_title_url = self.proxy._buildRE(self.re_title_url) - match = re.compile(re_title_url, re.DOTALL).finditer(urllib.unquote(data)) - - for torrent in match: - + matches = re.compile(re_title_url, re.DOTALL).finditer(urllib.unquote(data)) + for torrent in matches: title = torrent.group('title').replace('_', '.') #Do not know why but SickBeard skip release with '_' in name url = torrent.group('url') id = int(torrent.group('id')) seeders = int(torrent.group('seeders')) leechers = int(torrent.group('leechers')) - #Filter unseeded torrent if mode != 'RSS' and (seeders < self.minseed or leechers < self.minleech): continue From 999767b77e9d39c8662b578a1156cd64ee0ab864 Mon Sep 17 00:00:00 2001 From: Martin Warnaar <martinwarnaar@gmail.com> Date: Sat, 31 Jan 2015 19:49:48 +0100 Subject: [PATCH 2/3] Removed print statement --- sickbeard/providers/thepiratebay.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sickbeard/providers/thepiratebay.py b/sickbeard/providers/thepiratebay.py index 52f0da0c..1c1e285e 100644 --- a/sickbeard/providers/thepiratebay.py +++ b/sickbeard/providers/thepiratebay.py @@ -231,7 +231,6 @@ class ThePirateBayProvider(generic.TorrentProvider): else: searchURL = self.url + 'tv/latest/' - print searchURL logger.log(u"Search string: " + searchURL, logger.DEBUG) data = self.getURL(searchURL) From 1babd3ec3b5b6e639fa456effb6e4c0d40731290 Mon Sep 17 00:00:00 2001 From: Martin Warnaar <martinwarnaar@gmail.com> Date: Thu, 12 Feb 2015 14:24:15 +0100 Subject: [PATCH 3/3] Updated kickasstorrents URL to kickass.to --- sickbeard/providers/kat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sickbeard/providers/kat.py b/sickbeard/providers/kat.py index d9692a85..dbcc2c9f 100644 --- a/sickbeard/providers/kat.py +++ b/sickbeard/providers/kat.py @@ -55,7 +55,7 @@ class KATProvider(generic.TorrentProvider): self.cache = KATCache(self) - self.urls = {'base_url': 'http://kickass.so/'} + self.urls = {'base_url': 'http://kickass.to/'} self.url = self.urls['base_url']