From 159e8ceb7c712b49e553d31fed567339c8b37211 Mon Sep 17 00:00:00 2001 From: djoole Date: Sat, 6 Sep 2014 02:16:04 +0200 Subject: [PATCH] Added the torrent provider for www.t411.me tracker --- gui/slick/images/providers/t411.png | Bin 0 -> 6957 bytes sickbeard/__init__.py | 2 +- sickbeard/providers/__init__.py | 3 +- sickbeard/providers/generic.py | 7 +- sickbeard/providers/t411.py | 294 ++++++++++++++++++++++++++++ 5 files changed, 302 insertions(+), 4 deletions(-) create mode 100644 gui/slick/images/providers/t411.png create mode 100644 sickbeard/providers/t411.py diff --git a/gui/slick/images/providers/t411.png b/gui/slick/images/providers/t411.png new file mode 100644 index 0000000000000000000000000000000000000000..cc41c5edce68f2c5b626c151f540f900cad6e890 GIT binary patch literal 6957 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 Lg+i*8t)KlD*SWF~ literal 0 HcmV?d00001 diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 88248e48..e5771b0f 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -32,7 +32,7 @@ from sickbeard import providers, metadata, config, webserveInit from sickbeard.providers.generic import GenericProvider from providers import ezrss, tvtorrents, btn, newznab, womble, thepiratebay, torrentleech, kat, iptorrents, \ omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, nextgen, speedcd, nyaatorrents, fanzub, torrentbytes, animezb, \ - freshontv, bitsoup + freshontv, bitsoup, t411 from sickbeard.config import CheckSection, check_setting_int, check_setting_str, check_setting_float, ConfigMigrator, \ naming_ep_type from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \ diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index 7fb02eda..c1800ca1 100755 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -36,7 +36,8 @@ __all__ = ['ezrss', 'torrentbytes', 'animezb', 'freshontv', - 'bitsoup' + 'bitsoup', + 't411' ] import sickbeard diff --git a/sickbeard/providers/generic.py b/sickbeard/providers/generic.py index 95bdc169..07131109 100644 --- a/sickbeard/providers/generic.py +++ b/sickbeard/providers/generic.py @@ -27,7 +27,7 @@ import sickbeard import requests from sickbeard import helpers, classes, logger, db -from sickbeard.common import MULTI_EP_RESULT, SEASON_RESULT +from sickbeard.common import MULTI_EP_RESULT, SEASON_RESULT, USER_AGENT from sickbeard import tvcache from sickbeard import encodingKludge as ek from sickbeard.exceptions import ex @@ -63,7 +63,10 @@ class GenericProvider: self.session = requests.session() self.headers = { - 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'} + #Using USER_AGENT instead of Mozilla to keep same user agent along authentication and download phases, + #otherwise session might be broken and download fail, asking again for authentication + #'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.107 Safari/537.36'} + 'User-Agent': USER_AGENT} def getID(self): return GenericProvider.makeID(self.name) diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py new file mode 100644 index 00000000..45b3100a --- /dev/null +++ b/sickbeard/providers/t411.py @@ -0,0 +1,294 @@ +# -*- coding: latin-1 -*- +# Author: djoole +# URL: http://code.google.com/p/sickbeard/ +# +# This file is part of Sick Beard. +# +# Sick Beard 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. +# +# Sick Beard 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 Sick Beard. If not, see . + +import traceback +import time +import re +import datetime +import sickbeard +import generic +from lib import requests +from sickbeard.common import USER_AGENT, Quality, cpu_presets +from sickbeard import logger +from sickbeard import tvcache +from sickbeard import show_name_helpers +from sickbeard.bs4_parser import BS4Parser + +class T411Provider(generic.TorrentProvider): + urls = {'base_url': 'http://www.t411.me/', + 'search': 'http://www.t411.me/torrents/search/?name=%s&cat=210&subcat=433&search=%s&submit=Recherche', + 'login_page': 'http://www.t411.me/users/login/', + 'download': 'http://www.t411.me/torrents/download/?id=%s', + } + + def __init__(self): + + generic.TorrentProvider.__init__(self, "T411") + + self.supportsBacklog = True + + self.enabled = False + self.username = None + self.password = None + self.ratio = None + + self.cache = T411Cache(self) + + self.url = self.urls['base_url'] + + self.last_login_check = None + + self.login_opener = None + + def isEnabled(self): + return self.enabled + + def imageName(self): + return 't411.png' + + def getQuality(self, item, anime=False): + + quality = Quality.sceneQuality(item[0], anime) + return quality + + def getLoginParams(self): + return { + 'login': self.username, + 'password': self.password, + 'remember': '1', + } + + def loginSuccess(self, output): + if "Ratio: 0: + for result in entries: + + try: + link = result.find('a', title=True) + torrentName = link['title'] + torrent_name = str(torrentName) + torrentId = result.find_all('td')[2].find_all('a')[0]['href'][1:].replace('torrents/nfo/?id=','') + torrent_download_url = (self.urls['download'] % torrentId).encode('utf8') + except (AttributeError, TypeError): + continue + + if not torrent_name or not torrent_download_url: + continue + + item = torrent_name, torrent_download_url + logger.log(u"Found result: " + torrent_name + " (" + torrent_download_url + ")", logger.DEBUG) + items[mode].append(item) + + else: + logger.log(u"The Data returned from " + self.name + " do not contains any torrent", + logger.WARNING) + continue + + except Exception, e: + logger.log(u"Failed parsing " + self.name + " Traceback: " + traceback.format_exc(), + logger.ERROR) + + results += items[mode] + + return results + + def _get_title_and_url(self, item): + + title, url = item + + if title: + title = u'' + title + title = title.replace(' ', '.') + + if url: + url = str(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 T411Cache(tvcache.TVCache): + def __init__(self, provider): + + tvcache.TVCache.__init__(self, provider) + + # Only poll T411 every 10 minutes max + self.minTime = 10 + + def _getDailyData(self): + search_params = {'RSS': ['']} + return self.provider._doSearch(search_params) + + +provider = T411Provider()