From 53c66a3854e1cdde07fd33b3af218276133ea8ac Mon Sep 17 00:00:00 2001 From: Erik Weber Date: Sat, 27 Feb 2016 00:38:16 +0100 Subject: [PATCH 1/7] Norbits provider --- gui/slick/images/providers/norbits.png | Bin 0 -> 531 bytes sickbeard/providers/__init__.py | 6 +- sickbeard/providers/norbits.py | 144 +++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 2 deletions(-) create mode 100644 gui/slick/images/providers/norbits.png create mode 100644 sickbeard/providers/norbits.py diff --git a/gui/slick/images/providers/norbits.png b/gui/slick/images/providers/norbits.png new file mode 100644 index 0000000000000000000000000000000000000000..84e7c55951357e59084aa78b0bbe8519dd3e9e0a GIT binary patch literal 531 zcmV+u0_^>XP)Y4D4@P+qP}nwr%g&wr$(CU6Y(#`=J^^#oFAh7uL_+cCljawhNfE^#bVI2>utD zwVZqi>ot0m&)q5tD>#>zYZP^A*5-4VX@OZ=&SMT4lHMq@&=b*=w&B=4+j_%%m zoW1`UH(&k1_{4;Tehi)6eYo=MC$yJ8e9_Y0g}ZP6;oO5S3fG?hLS17U{`f_c{6E^e zdQ{}ICi>dOR`^AvFo7Rx8d|aL$X(3b#C4umsb%Ds!6P^xcgeA#r2|_}KT`4qJ1%48 zft$!HsYYmgrVudOhGX|Jd#j9c(XK1V%rA#K5!|87IPJpnT4WbhDioB}U~p&zUp>NH zAb4Y+;Imt(^gsyiSrIrYA-|MLh|4g~V9pk+3~V;>`U`4uQyVogSu&s|N(PGHA`@^E znZSCCqcY}>?p|EwG443~1ec%wz>+=J literal 0 HcmV?d00001 diff --git a/sickbeard/providers/__init__.py b/sickbeard/providers/__init__.py index a61b8ae375..8cf3c5e6c0 100644 --- a/sickbeard/providers/__init__.py +++ b/sickbeard/providers/__init__.py @@ -25,7 +25,8 @@ from sickbeard.providers import btn, newznab, rsstorrent, womble, thepiratebay, torrentleech, kat, iptorrents, torrentz, \ omgwtfnzbs, scc, hdtorrents, torrentday, hdbits, hounddawgs, speedcd, nyaatorrents, bluetigers, xthor, abnormal, phxbit, torrentbytes, cpasbien,\ freshontv, morethantv, bitsoup, t411, tokyotoshokan, shazbat, rarbg, alpharatio, tntvillage, binsearch, torrentproject, extratorrent, \ - scenetime, btdigg, transmitthenet, tvchaosuk, bitcannon, pretome, gftracker, hdspace, newpct, elitetorrent, bitsnoop, danishbits, hd4free, limetorrents + scenetime, btdigg, transmitthenet, tvchaosuk, bitcannon, pretome, gftracker, hdspace, newpct, elitetorrent, bitsnoop, danishbits, hd4free, limetorrents, \ + norbits __all__ = [ 'womble', 'btn', 'thepiratebay', 'kat', 'torrentleech', 'scc', 'hdtorrents', @@ -35,7 +36,8 @@ 'shazbat', 'rarbg', 'tntvillage', 'binsearch', 'bluetigers', 'xthor', 'abnormal', 'phxbit', 'scenetime', 'btdigg', 'transmitthenet', 'tvchaosuk', 'torrentproject', 'extratorrent', 'bitcannon', 'torrentz', 'pretome', 'gftracker', - 'hdspace', 'newpct', 'elitetorrent', 'bitsnoop', 'danishbits', 'hd4free', 'limetorrents' + 'hdspace', 'newpct', 'elitetorrent', 'bitsnoop', 'danishbits', 'hd4free', 'limetorrents', + 'norbits' ] diff --git a/sickbeard/providers/norbits.py b/sickbeard/providers/norbits.py new file mode 100644 index 0000000000..d888def778 --- /dev/null +++ b/sickbeard/providers/norbits.py @@ -0,0 +1,144 @@ +# coding=utf-8 +# +# 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 . + +import datetime +from requests.compat import urlencode + +from sickbeard import classes, logger, tvcache + +from sickbeard.helpers import sanitizeSceneName +from sickrage.helper.common import episode_num +from sickrage.helper.exceptions import AuthException +from sickrage.providers.torrent.TorrentProvider import TorrentProvider + +try: + import json +except ImportError: + import simplejson as json + + +class NorbitsProvider(TorrentProvider): + + def __init__(self): + + TorrentProvider.__init__(self, "Norbits") + + self.username = None + self.passkey = None + self.ratio = None + + self.cache = NorbitsCache(self, min_time=15) # only poll Norbits every 15 minutes max + + self.urls = {'base_url': 'https://norbits.net', + 'search': 'https://norbits.net/api2.php?action=torrents', + 'download': 'https://norbits.net/download.php?'} + + self.url = self.urls['base_url'] + + def _check_auth(self): + + if not self.username or not self.passkey: + raise AuthException("Your authentication credentials for " + self.name + " are missing, check your config.") + + return True + + def _checkAuthFromData(self, parsedJSON): + + if 'status' in parsedJSON and 'message' in parsedJSON: + if parsedJSON.get('status') == 3: + logger.log(u"Invalid username or password. Check your settings", logger.WARNING) + + return True + + def _get_season_search_strings(self, ep_obj): + season_search_string = [self._make_post_data_JSON(show=ep_obj.show, season=ep_obj)] + return season_search_string + + def _get_episode_search_strings(self, ep_obj, add_string=''): + episode_search_string = [self._make_post_data_JSON(show=ep_obj.show, episode=ep_obj)] + return episode_search_string + + def _get_title_and_url(self, item): + title = item.get('name', '').replace(' ', '.') + url = self.urls['download'] + urlencode({'id': item['id'], 'passkey': self.passkey}) + return title, url + + def search(self, search_params, age=0, ep_obj=None): + + # FIXME + results = [] + + logger.log(u"Search string: %s" % search_params, logger.DEBUG) + + self._check_auth() + parsedJSON = self.get_url(self.urls['search'], post_data=search_params, json=True) + if not parsedJSON: + return [] + + if self._checkAuthFromData(parsedJSON): + if parsedJSON and 'data' in parsedJSON: + items = parsedJSON['data'] + else: + logger.log(u"Resulting JSON from provider isn't correct, not parsing it", logger.ERROR) + items = [] + if 'torrents' in items: + for item in items['torrents']: + results.append(item) + # FIXME SORTING + logger.log(u'results: %s' % results, logger.DEBUG) + return results + + + def _make_post_data_JSON(self, show=None, episode=None, season=None, search_term=None): + post_data = { + 'username': self.username, + 'passkey': self.passkey, + 'category': '2', + # TV Category + } + ep_num = episode_num(episode.scene_season, episode.scene_episode) + show_name = sanitizeSceneName(episode.show.name) + search = "%s.%s" % (show_name, ep_num) + post_data['search'] = search + + if search_term: + post_data['search'] = search_term + + return json.dumps(post_data) + + def seed_ratio(self): + return self.ratio + + +class NorbitsCache(tvcache.TVCache): + def _getRSSData(self): + self.search_params = None # Norbits cache does not use search_params so set it to None + results = [] + + try: + parsedJSON = self.provider.getURL(self.provider.urls['rss'], post_data=self.provider._make_post_data_JSON(), returns='json') + + if self.provider._checkAuthFromData(parsedJSON): + results = parsedJSON['data'] + except Exception: + pass + + return {'entries': results} + +provider = NorbitsProvider() From 24e338fe144fad6200d22943113b247bfbee6212 Mon Sep 17 00:00:00 2001 From: Erik Weber Date: Sat, 27 Feb 2016 01:31:51 +0100 Subject: [PATCH 2/7] Fix docstrings, quotes and some other coding style issues --- sickbeard/providers/norbits.py | 82 +++++++++++++++++----------------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/sickbeard/providers/norbits.py b/sickbeard/providers/norbits.py index d888def778..604c77b2d6 100644 --- a/sickbeard/providers/norbits.py +++ b/sickbeard/providers/norbits.py @@ -1,5 +1,6 @@ # coding=utf-8 -# +'''A Norbits (https://norbits.net) provider, based on hdbits.py''' + # URL: https://sickrage.github.io # # This file is part of SickRage. @@ -17,10 +18,9 @@ # You should have received a copy of the GNU General Public License # along with SickRage. If not, see . -import datetime from requests.compat import urlencode -from sickbeard import classes, logger, tvcache +from sickbeard import logger, tvcache from sickbeard.helpers import sanitizeSceneName from sickrage.helper.common import episode_num @@ -34,35 +34,40 @@ class NorbitsProvider(TorrentProvider): + '''Main provider object''' def __init__(self): - - TorrentProvider.__init__(self, "Norbits") + ''' Initialize the class ''' + TorrentProvider.__init__(self, 'Norbits') self.username = None self.passkey = None self.ratio = None - self.cache = NorbitsCache(self, min_time=15) # only poll Norbits every 15 minutes max + self.cache = tvcache.TVCache(self, min_time=20) # only poll Norbits every 15 minutes max self.urls = {'base_url': 'https://norbits.net', 'search': 'https://norbits.net/api2.php?action=torrents', 'download': 'https://norbits.net/download.php?'} self.url = self.urls['base_url'] + self.logger = logger.Logger() def _check_auth(self): if not self.username or not self.passkey: - raise AuthException("Your authentication credentials for " + self.name + " are missing, check your config.") + raise AuthException(('Your authentication credentials for %s are ' + 'missing, check your config.') % self.name) return True - def _checkAuthFromData(self, parsedJSON): + def _checkAuthFromData(self, parsed_json): # pylint: disable=invalid-name + ''' Check that we are authenticated. ''' - if 'status' in parsedJSON and 'message' in parsedJSON: - if parsedJSON.get('status') == 3: - logger.log(u"Invalid username or password. Check your settings", logger.WARNING) + if 'status' in parsed_json and 'message' in parsed_json: + if parsed_json.get('status') == 3: + self.logger.log((u'Invalid username or password. ' + 'Check your settings'), logger.WARNING) return True @@ -80,43 +85,46 @@ def _get_title_and_url(self, item): return title, url def search(self, search_params, age=0, ep_obj=None): + ''' Do the actual searching and JSON parsing''' - # FIXME results = [] - logger.log(u"Search string: %s" % search_params, logger.DEBUG) + self.logger.log(u'Search string: %s' % search_params, logger.DEBUG) self._check_auth() - parsedJSON = self.get_url(self.urls['search'], post_data=search_params, json=True) - if not parsedJSON: + parsed_json = self.get_url(self.urls['search'], post_data=search_params, json=True) + if not parsed_json: return [] - if self._checkAuthFromData(parsedJSON): - if parsedJSON and 'data' in parsedJSON: - items = parsedJSON['data'] + if self._checkAuthFromData(parsed_json): + if parsed_json and 'data' in parsed_json: + items = parsed_json['data'] else: - logger.log(u"Resulting JSON from provider isn't correct, not parsing it", logger.ERROR) + self.logger.log((u'Resulting JSON from provider is not correct, ' + 'not parsing it'), logger.ERROR) items = [] if 'torrents' in items: for item in items['torrents']: results.append(item) - # FIXME SORTING - logger.log(u'results: %s' % results, logger.DEBUG) + self.logger.log(u'results: %s' % results, logger.DEBUG) return results - - def _make_post_data_JSON(self, show=None, episode=None, season=None, search_term=None): + def _make_post_data_JSON(self, show=None, episode=None, season=None, search_term=None): # pylint: disable=invalid-name + ''' Make post data for our JSON query''' post_data = { 'username': self.username, 'passkey': self.passkey, 'category': '2', # TV Category } - ep_num = episode_num(episode.scene_season, episode.scene_episode) - show_name = sanitizeSceneName(episode.show.name) - search = "%s.%s" % (show_name, ep_num) - post_data['search'] = search - + if episode: + ep_num = episode_num(episode.scene_season, episode.scene_episode) + show_name = sanitizeSceneName(show.name) + search = '%s.%s' % (show_name, ep_num) + post_data['search'] = search + + if season: + self.logger.log(u'season: %s' % dir(season), logger.DEBUG) if search_term: post_data['search'] = search_term @@ -127,18 +135,10 @@ def seed_ratio(self): class NorbitsCache(tvcache.TVCache): - def _getRSSData(self): - self.search_params = None # Norbits cache does not use search_params so set it to None - results = [] - - try: - parsedJSON = self.provider.getURL(self.provider.urls['rss'], post_data=self.provider._make_post_data_JSON(), returns='json') + ''' Hold our cache''' - if self.provider._checkAuthFromData(parsedJSON): - results = parsedJSON['data'] - except Exception: - pass - - return {'entries': results} + def _getRSSData(self): + ''' We don't want to do RSS searchs''' + pass -provider = NorbitsProvider() +provider = NorbitsProvider() # pylint: disable=invalid-name From 5b8ae9ca533163ffa8f43f934f86f414b935be1b Mon Sep 17 00:00:00 2001 From: Erik Weber Date: Sat, 27 Feb 2016 01:39:27 +0100 Subject: [PATCH 3/7] use str.format instead of %s for search string --- sickbeard/providers/norbits.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sickbeard/providers/norbits.py b/sickbeard/providers/norbits.py index 604c77b2d6..bf0cbdb123 100644 --- a/sickbeard/providers/norbits.py +++ b/sickbeard/providers/norbits.py @@ -120,7 +120,7 @@ def _make_post_data_JSON(self, show=None, episode=None, season=None, search_term if episode: ep_num = episode_num(episode.scene_season, episode.scene_episode) show_name = sanitizeSceneName(show.name) - search = '%s.%s' % (show_name, ep_num) + search = '{}.{}'.format(show_name, ep_num) post_data['search'] = search if season: From 3ec5b3bfb6f9c730739da364576067be9810e9c0 Mon Sep 17 00:00:00 2001 From: Erik Weber Date: Sat, 27 Feb 2016 23:28:55 +0100 Subject: [PATCH 4/7] rewrite, got rid of unnecessary methods and based the provider on abnormal.py --- sickbeard/providers/norbits.py | 138 ++++++++++++++++----------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/sickbeard/providers/norbits.py b/sickbeard/providers/norbits.py index bf0cbdb123..8d8abbf9c9 100644 --- a/sickbeard/providers/norbits.py +++ b/sickbeard/providers/norbits.py @@ -1,5 +1,5 @@ # coding=utf-8 -'''A Norbits (https://norbits.net) provider, based on hdbits.py''' +'''A Norbits (https://norbits.net) provider''' # URL: https://sickrage.github.io # @@ -22,8 +22,6 @@ from sickbeard import logger, tvcache -from sickbeard.helpers import sanitizeSceneName -from sickrage.helper.common import episode_num from sickrage.helper.exceptions import AuthException from sickrage.providers.torrent.TorrentProvider import TorrentProvider @@ -33,7 +31,7 @@ import simplejson as json -class NorbitsProvider(TorrentProvider): +class NorbitsProvider(TorrentProvider): # pylint: disable=too-many-instance-attributes '''Main provider object''' def __init__(self): @@ -43,14 +41,15 @@ def __init__(self): self.username = None self.passkey = None self.ratio = None + self.minseed = None + self.minleech = None self.cache = tvcache.TVCache(self, min_time=20) # only poll Norbits every 15 minutes max - self.urls = {'base_url': 'https://norbits.net', - 'search': 'https://norbits.net/api2.php?action=torrents', - 'download': 'https://norbits.net/download.php?'} + self.url = 'https://norbits.net' + self.urls = {'search': self.url + '/api2.php?action=torrents', + 'download': self.url + '/download.php?'} - self.url = self.urls['base_url'] self.logger = logger.Logger() def _check_auth(self): @@ -71,74 +70,75 @@ def _checkAuthFromData(self, parsed_json): # pylint: disable=invalid-name return True - def _get_season_search_strings(self, ep_obj): - season_search_string = [self._make_post_data_JSON(show=ep_obj.show, season=ep_obj)] - return season_search_string - - def _get_episode_search_strings(self, ep_obj, add_string=''): - episode_search_string = [self._make_post_data_JSON(show=ep_obj.show, episode=ep_obj)] - return episode_search_string - - def _get_title_and_url(self, item): - title = item.get('name', '').replace(' ', '.') - url = self.urls['download'] + urlencode({'id': item['id'], 'passkey': self.passkey}) - return title, url - - def search(self, search_params, age=0, ep_obj=None): + def search(self, search_params, age=0, ep_obj=None): # pylint: disable=too-many-locals ''' Do the actual searching and JSON parsing''' results = [] - self.logger.log(u'Search string: %s' % search_params, logger.DEBUG) - - self._check_auth() - parsed_json = self.get_url(self.urls['search'], post_data=search_params, json=True) - if not parsed_json: - return [] - - if self._checkAuthFromData(parsed_json): - if parsed_json and 'data' in parsed_json: - items = parsed_json['data'] - else: - self.logger.log((u'Resulting JSON from provider is not correct, ' - 'not parsing it'), logger.ERROR) - items = [] - if 'torrents' in items: - for item in items['torrents']: - results.append(item) - self.logger.log(u'results: %s' % results, logger.DEBUG) - return results + for mode in search_params: + items = [] + self.logger.log(u'Search Mode: {}'.format(mode), logger.DEBUG) + + for search_string in search_params[mode]: + if mode != 'RSS': + self.logger.log('Search string: {}'.format(search_string.decode('utf-8')), + logger.DEBUG) + + post_data = { + 'username': self.username, + 'passkey': self.passkey, + 'category': '2', # TV Category + 'search': search_string, + } + + self._check_auth() + parsed_json = self.get_url(self.urls['search'], + post_data=json.dumps(post_data), + json=True) + + if not parsed_json: + return [] + + if self._checkAuthFromData(parsed_json): + if parsed_json and 'data' in parsed_json: + json_items = parsed_json['data'] + else: + self.logger.log((u'Resulting JSON from provider is not correct, ' + 'not parsing it'), logger.ERROR) + if 'torrents' in json_items: + for item in json_items['torrents']: + seeders = item['seeders'] + leechers = item['leechers'] + title = item['name'] + info_hash = item['info_hash'] + size = item['size'] + download_url = ('{}{}'.format(self.urls['download'], + urlencode({'id': item['id'], + 'passkey': self.passkey}))) + + if seeders < self.minseed or leechers < self.minleech: + self.logger.log((u'Discarding torrent because it does not meet ' + 'the minimum seeders or leechers: ' + '{} (S:{} L:{})').format + (title, seeders, leechers), logger.DEBUG) + continue + else: + item = title, download_url, size, seeders, leechers, info_hash + if mode != "RSS": + self.logger.log((u'Found result: {} with {} seeders and {}' + 'leechers').format(title, + seeders, + leechers), logger.DEBUG) + + items.append(item) + # For each search mode sort all the items by seeders if available + items.sort(key=lambda tup: tup[3], reverse=True) + + results += items - def _make_post_data_JSON(self, show=None, episode=None, season=None, search_term=None): # pylint: disable=invalid-name - ''' Make post data for our JSON query''' - post_data = { - 'username': self.username, - 'passkey': self.passkey, - 'category': '2', - # TV Category - } - if episode: - ep_num = episode_num(episode.scene_season, episode.scene_episode) - show_name = sanitizeSceneName(show.name) - search = '{}.{}'.format(show_name, ep_num) - post_data['search'] = search - - if season: - self.logger.log(u'season: %s' % dir(season), logger.DEBUG) - if search_term: - post_data['search'] = search_term - - return json.dumps(post_data) + return results def seed_ratio(self): return self.ratio - -class NorbitsCache(tvcache.TVCache): - ''' Hold our cache''' - - def _getRSSData(self): - ''' We don't want to do RSS searchs''' - pass - provider = NorbitsProvider() # pylint: disable=invalid-name From cd4b972cd193a3e6ce6ef6edf4ee5b4cb8f6f000 Mon Sep 17 00:00:00 2001 From: miigotu Date: Sat, 27 Feb 2016 20:21:37 -0800 Subject: [PATCH 5/7] Change UA for statistical reasons --- sickbeard/common.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sickbeard/common.py b/sickbeard/common.py index c1054437b9..5653014916 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -47,7 +47,7 @@ # This is disabled, was only added for testing, and has no config.ini or web ui setting. To enable, set SPOOF_USER_AGENT = True SPOOF_USER_AGENT = False INSTANCE_ID = str(uuid.uuid1()) -USER_AGENT = ('SickRage/(' + platform.system() + '; ' + platform.release() + '; ' + INSTANCE_ID + ')') +USER_AGENT = ('Sick-Rage.CE.1/(' + platform.system() + '; ' + platform.release() + '; ' + INSTANCE_ID + ')') UA_SETTINGS.DB = ek(path.abspath, ek(path.join, ek(path.dirname, __file__), '../lib/fake_useragent/ua.json')) UA_POOL = UserAgent() if SPOOF_USER_AGENT: From cba38b41b2921bde0b5afca67fc640fb6b2e6f08 Mon Sep 17 00:00:00 2001 From: adaur Date: Sun, 28 Feb 2016 22:07:51 +0100 Subject: [PATCH 6/7] Update T411 domain name --- sickbeard/providers/t411.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py index b6994e2267..f4b3690b13 100644 --- a/sickbeard/providers/t411.py +++ b/sickbeard/providers/t411.py @@ -43,11 +43,11 @@ def __init__(self): self.cache = tvcache.TVCache(self, min_time=10) # Only poll T411 every 10 minutes max - self.urls = {'base_url': 'http://www.t411.in/', - 'search': 'https://api.t411.in/torrents/search/%s*?cid=%s&limit=100', - 'rss': 'https://api.t411.in/torrents/top/today', - 'login_page': 'https://api.t411.in/auth', - 'download': 'https://api.t411.in/torrents/download/%s'} + self.urls = {'base_url': 'http://www.t411.ch/', + 'search': 'https://api.t411.ch/torrents/search/%s*?cid=%s&limit=100', + 'rss': 'https://api.t411.ch/torrents/top/today', + 'login_page': 'https://api.t411.ch/auth', + 'download': 'https://api.t411.ch/torrents/download/%s'} self.url = self.urls['base_url'] From 2505409d42fd636bf4f3d7786e2090396e5ee2d9 Mon Sep 17 00:00:00 2001 From: miigotu Date: Sun, 28 Feb 2016 14:53:34 -0800 Subject: [PATCH 7/7] Fix tvchaosuk, there is one persistent cookie for CF, then totals 4 cookies when authed Fix tntvillage login, has 3 cookies when logged in. RSS search still disabled in this provider Fixes https://github.com/SickRage/sickrage-issues/issues/1072 --- sickbeard/providers/tntvillage.py | 4 ++-- sickbeard/providers/tvchaosuk.py | 16 ++++++++++++++-- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/sickbeard/providers/tntvillage.py b/sickbeard/providers/tntvillage.py index a36ac32321..6148b89f3f 100644 --- a/sickbeard/providers/tntvillage.py +++ b/sickbeard/providers/tntvillage.py @@ -123,12 +123,12 @@ def _check_auth(self): return True def login(self): - if any(dict_from_cookiejar(self.session.cookies).values()): + if len(dict_from_cookiejar(self.session.cookies)) == 3: return True login_params = {'UserName': self.username, 'PassWord': self.password, - 'CookieDate': 0, + 'CookieDate': 1, 'submit': 'Connettiti al Forum'} response = self.get_url(self.urls['login'], post_data=login_params, timeout=30) diff --git a/sickbeard/providers/tvchaosuk.py b/sickbeard/providers/tvchaosuk.py index 4e890ffd87..c2e13b6ed7 100644 --- a/sickbeard/providers/tvchaosuk.py +++ b/sickbeard/providers/tvchaosuk.py @@ -18,6 +18,7 @@ # along with SickRage. If not, see . import re +import time from requests.utils import dict_from_cookiejar from sickbeard import logger, tvcache @@ -65,7 +66,9 @@ def _check_auth(self): raise AuthException('Your authentication credentials for ' + self.name + ' are missing, check your config.') def login(self): - if any(dict_from_cookiejar(self.session.cookies).values()): + # cloudflare leaves __cfduid cookie even if cookie is expired, + # there are 4 cookies when cookie is valid + if len(dict_from_cookiejar(self.session.cookies)) == 4: return True login_params = { @@ -77,12 +80,21 @@ def login(self): } # Must be done twice, or it isnt really logged in - response = self.get_url(self.urls['login'], post_data=login_params, timeout=30) + # first time gets __cfduid, if we already have __cfduid this might get the cookie response = self.get_url(self.urls['login'], post_data=login_params, timeout=30) if not response: logger.log(u"Unable to connect to provider", logger.WARNING) return False + # if the first post only got the __cfduid then sleep 5 seconds for cloudflare anti-bot + # and then get the actual cookie + if len(dict_from_cookiejar(self.session.cookies)) < 4: + time.sleep(5) + response = self.get_url(self.urls['login'], post_data=login_params, timeout=30) + if not response: + logger.log(u"Unable to connect to provider", logger.WARNING) + return False + if re.search('Error: Username or password incorrect!', response): logger.log(u"Invalid username or password. Check your settings", logger.WARNING) return False