diff --git a/CHANGES.md b/CHANGES.md index 06c1b3e..85b4639 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,9 +1,11 @@ -### 0.18.15 (2019-02-xx xx:xx:00 UTC) +### 0.18.15 (2019-02-21 15:30:00 UTC) * Change improve Zooqle * Change log bad torrent data * Change search HorribleSubs without fansub groups * Remove provider Anizb +* Change improve handling Trakt API response errors with watchlists +* Fix TV info source locked id check ### 0.18.14 (2019-02-11 15:10:00 UTC) diff --git a/lib/libtrakt/exceptions.py b/lib/libtrakt/exceptions.py index 67126ee..75b05fd 100644 --- a/lib/libtrakt/exceptions.py +++ b/lib/libtrakt/exceptions.py @@ -11,4 +11,31 @@ class TraktServerBusy(TraktException): class TraktShowNotFound(TraktException): - pass \ No newline at end of file + pass + + +class TraktCloudFlareException(TraktException): + pass + + +class TraktMethodNotExisting(TraktException): + pass + + +class TraktTimeout(TraktException): + pass + + +class TraktValueError(TraktException): + pass + + +class TraktServerError(TraktException): + def __init__(self, *args, **kwargs): + self.error_code = kwargs.get('error_code') + kwargs = {} + if 0 < len(args): + args = tuple(['%s, Server Error: %s' % (args[0], self.error_code)]) + else: + args = tuple(['Server Error: %s' % self.error_code]) + super(TraktServerError, self).__init__(*args, **kwargs) diff --git a/lib/libtrakt/trakt.py b/lib/libtrakt/trakt.py index d9c11cc..43bc974 100644 --- a/lib/libtrakt/trakt.py +++ b/lib/libtrakt/trakt.py @@ -6,7 +6,7 @@ import time import datetime from sickbeard import logger -from .exceptions import TraktException, TraktAuthException # , TraktServerBusy +from .exceptions import * class TraktAccount: @@ -149,7 +149,10 @@ class TraktAPI: @staticmethod def delete_account(account): if account in sickbeard.TRAKT_ACCOUNTS: - TraktAPI().trakt_request('/oauth/revoke', send_oauth=account, method='POST') + try: + TraktAPI().trakt_request('/oauth/revoke', send_oauth=account, method='POST') + except TraktException: + logger.log('Failed to remove account from trakt.tv') sickbeard.TRAKT_ACCOUNTS.pop(account) sickbeard.save_config() return True @@ -255,16 +258,21 @@ class TraktAPI: if not code: if 'timed out' in e: logger.log(u'Timeout connecting to Trakt', logger.WARNING) + if count >= self.max_retrys: + raise TraktTimeout() return self.trakt_request(path, data, headers, url, count=count, sleep_retry=sleep_retry, send_oauth=send_oauth, method=method) # This is pretty much a fatal error if there is no status_code # It means there basically was no response at all else: logger.log(u'Could not connect to Trakt. Error: {0}'.format(e), logger.WARNING) + raise TraktException('Could not connect to Trakt. Error: {0}'.format(e)) elif 502 == code: # Retry the request, Cloudflare had a proxying issue logger.log(u'Retrying Trakt api request: %s' % path, logger.WARNING) + if count >= self.max_retrys: + raise TraktCloudFlareException() return self.trakt_request(path, data, headers, url, count=count, sleep_retry=sleep_retry, send_oauth=send_oauth, method=method) @@ -289,18 +297,22 @@ class TraktAPI: raise TraktAuthException() elif code in (500, 501, 503, 504, 520, 521, 522): + if count >= self.max_retrys: + logger.log(u'Trakt may have some issues and it\'s unavailable. Code: %s' % code, logger.WARNING) + raise TraktServerError(error_code=code) # http://docs.trakt.apiary.io/#introduction/status-codes logger.log(u'Trakt may have some issues and it\'s unavailable. Trying again', logger.WARNING) - self.trakt_request(path, data, headers, url, count=count, sleep_retry=sleep_retry, - send_oauth=send_oauth, method=method) + return self.trakt_request(path, data, headers, url, count=count, sleep_retry=sleep_retry, + send_oauth=send_oauth, method=method) elif 404 == code: logger.log(u'Trakt error (404) the resource does not exist: %s%s' % (url, path), logger.WARNING) + raise TraktMethodNotExisting('Trakt error (404) the resource does not exist: %s%s' % (url, path)) else: logger.log(u'Could not connect to Trakt. Code error: {0}'.format(code), logger.ERROR) - return {} + raise TraktException('Could not connect to Trakt. Code error: {0}'.format(code)) except ValueError as e: logger.log(u'Value Error: {0}'.format(e), logger.ERROR) - return {} + raise TraktValueError(u'Value Error: {0}'.format(e)) # check and confirm Trakt call did not fail if isinstance(resp, dict) and 'failure' == resp.get('status', None): diff --git a/sickbeard/databases/mainDB.py b/sickbeard/databases/mainDB.py index 0a0fc22..439fcda 100644 --- a/sickbeard/databases/mainDB.py +++ b/sickbeard/databases/mainDB.py @@ -40,6 +40,7 @@ class MainSanityCheck(db.DBSanityCheck): self.fix_unaired_episodes() self.fix_scene_exceptions() self.fix_orphan_not_found_show() + self.fix_fallback_mapping() def fix_duplicate_shows(self, column='indexer_id'): @@ -192,6 +193,16 @@ class MainSanityCheck(db.DBSanityCheck): if sql_result.rowcount: logger.log('Fixed orphaned not found shows') + def fix_fallback_mapping(self): + fallback_indexer = [i for i in sickbeard.indexerApi().fallback_indexers] + if fallback_indexer: + sql_result = self.connection.action( + 'DELETE FROM indexer_mapping WHERE mindexer IN (%s) OR indexer in (%s)' % + (','.join(['?'] * len(fallback_indexer)), ','.join(['?'] * len(fallback_indexer))), + fallback_indexer + fallback_indexer) + if sql_result.rowcount: + logger.log('Fixed fallback indexer mappings') + class InitialSchema(db.SchemaUpgrade): # ====================== diff --git a/sickbeard/indexers/indexer_api.py b/sickbeard/indexers/indexer_api.py index 8db5af1..3b1b87f 100644 --- a/sickbeard/indexers/indexer_api.py +++ b/sickbeard/indexers/indexer_api.py @@ -123,19 +123,26 @@ class indexerApi(object): @property def indexers(self): - return dict((int(x['id']), x['name']) for x in indexerConfig.values() if not x['mapped_only']) + return dict((int(x['id']), x['name']) for x in indexerConfig.values() if not x['mapped_only'] and True is not x.get('fallback')) @property def search_indexers(self): return dict((int(x['id']), x['name']) for x in indexerConfig.values() if not x['mapped_only'] and - x.get('active') and not x.get('defunct')) + x.get('active') and not x.get('defunct') and True is not x.get('fallback')) @property def all_indexers(self): """ - return all indexers including mapped only indexers + return all indexers including mapped only indexers excluding fallback indexers """ - return dict((int(x['id']), x['name']) for x in indexerConfig.values()) + return dict((int(x['id']), x['name']) for x in indexerConfig.values() if True is not x.get('fallback')) + + @property + def fallback_indexers(self): + """ + return all fallback indexers + """ + return dict((int(x['id']), x['name']) for x in indexerConfig.values() if True is x.get('fallback')) @property def xem_supported_indexers(self): diff --git a/sickbeard/indexers/indexer_config.py b/sickbeard/indexers/indexer_config.py index 17ace51..a0bce0c 100644 --- a/sickbeard/indexers/indexer_config.py +++ b/sickbeard/indexers/indexer_config.py @@ -43,6 +43,7 @@ indexerConfig = { dupekey='', mapped_only=True, icon='thetvdb16.png', + fallback=True, ), INDEXER_TVRAGE: dict( main_url='http://tvrage.com/', diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 3bb84aa..6dacc90 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -2137,7 +2137,7 @@ class Home(MainHandler): i = helpers.tryInt(t.group(1)) if 'mid-%s' % i in kwargs: l = helpers.tryInt(kwargs['mid-%s' % i], None) - if None is not id and id >= 0: + if None is not l and l >= 0: show_obj.ids.setdefault(i, {'id': 0, 'status': MapStatus.NONE, 'date': datetime.date.fromordinal(1)})['id'] = l show_obj.ids.setdefault(i, {'id': 0, 'status': MapStatus.NONE, 'date':