diff --git a/gui/slick/interfaces/default/config_notifications.tmpl b/gui/slick/interfaces/default/config_notifications.tmpl index f1919d9d..1c64516c 100644 --- a/gui/slick/interfaces/default/config_notifications.tmpl +++ b/gui/slick/interfaces/default/config_notifications.tmpl @@ -12,9 +12,9 @@ -#if $varExists('header') +#if $varExists('header')

$header

-#else +#else

$title

#end if @@ -30,7 +30,7 @@
- +

KODI

@@ -110,7 +110,7 @@

only send library updates to the first active host ?

-
+
- +
@@ -232,7 +232,7 @@ +
+ -
+
- +
@@ -430,7 +430,7 @@ @@ -446,8 +446,8 @@
- - + +
@@ -563,7 +563,7 @@
- +
@@ -576,7 +576,7 @@ @@ -587,7 +587,7 @@ @@ -1203,7 +1203,7 @@ @@ -1214,7 +1214,7 @@ @@ -1266,7 +1266,7 @@
- +
@@ -1391,13 +1391,12 @@
- -
@@ -1444,7 +1443,7 @@   method in which to download episodes for new show's. -
+
-
-
+
+
#else #for $cur_show in $trending_shows: - #set $image = re.sub(r'(?im)(.*)(\..*?)$', r'\1-300\2', $cur_show['images']['poster'], 0) + #set $show_url = 'http://www.trakt.tv/shows/%s' % $cur_show['show']['ids']['slug'] -
+
- +
- <%= (cur_show['title'], ' ')[ '' == cur_show['title']] %> + <%= (cur_show['show']['title'], ' ')[ '' == cur_show['show']['title']] %>
-

$cur_show['ratings']['percentage']%

- $cur_show['ratings']['votes'] votes - +

<%= int(cur_show['show']['rating']*10) %>%

+ $cur_show['show']['votes'] votes
diff --git a/gui/slick/js/configNotifications.js b/gui/slick/js/configNotifications.js index d62ceed4..2851bc53 100644 --- a/gui/slick/js/configNotifications.js +++ b/gui/slick/js/configNotifications.js @@ -36,7 +36,7 @@ $(document).ready(function(){ $('#testProwl').prop('disabled', false); }); }); - + $('#testKODI').click(function () { var kodi_host = $.trim($('#kodi_host').val()); var kodi_username = $.trim($('#kodi_username').val()); @@ -91,7 +91,7 @@ $(document).ready(function(){ $('#testBoxcar').prop('disabled', false); }); }); - + $('#testBoxcar2').click(function () { var boxcar2_accesstoken = $.trim($('#boxcar2_accesstoken').val()); if (!boxcar2_accesstoken) { @@ -141,7 +141,7 @@ $(document).ready(function(){ $.get(sbRoot + '/home/testLibnotify', function (data) { $('#testLibnotify-result').html(data); }); }); - + $('#twitterStep1').click(function() { $('#testTwitter-result').html(loading); $.get(sbRoot + '/home/twitterStep1', function (data) {window.open(data); }) @@ -174,7 +174,7 @@ $(document).ready(function(){ } $('#testNMJ-result').html(loading); var nmj_host = $('#nmj_host').val(); - + $.get(sbRoot + '/home/settingsNMJ', {'host': nmj_host}, function (data) { if (data === null) { @@ -236,7 +236,7 @@ $(document).ready(function(){ } var nmjv2_dbinstance=$('#NMJv2db_instance').val(); - $.get(sbRoot + '/home/settingsNMJv2', {'host': nmjv2_host,'dbloc': nmjv2_dbloc,'instance': nmjv2_dbinstance}, + $.get(sbRoot + '/home/settingsNMJv2', {'host': nmjv2_host,'dbloc': nmjv2_dbloc,'instance': nmjv2_dbinstance}, function (data){ if (data == null) { $('#nmjv2_database').removeAttr('readonly'); @@ -244,7 +244,7 @@ $(document).ready(function(){ var JSONData = $.parseJSON(data); $('#testNMJv2-result').html(JSONData.message); $('#nmjv2_database').val(JSONData.database); - + if (JSONData.database) $('#nmjv2_database').attr('readonly', true); else @@ -268,7 +268,7 @@ $(document).ready(function(){ $('#testNMJv2').prop('disabled', false); }); }); - + $('#testFreeMobile').click(function () { var freemobile_id = $.trim($('#freemobile_id').val()); var freemobile_apikey = $.trim($('#freemobile_apikey').val()); @@ -295,18 +295,13 @@ $(document).ready(function(){ $('#testFreeMobile').prop('disabled', false); }); }); - + $('#testTrakt').click(function () { - var trakt_api = $.trim($('#trakt_api').val()); var trakt_username = $.trim($('#trakt_username').val()); var trakt_password = $.trim($('#trakt_password').val()); - if (!trakt_api || !trakt_username || !trakt_password) { + var trakt_disable_ssl_verify = $('#trakt_disable_ssl_verify').is(':checked'); + if (!trakt_username || !trakt_password) { $('#testTrakt-result').html('Please fill out the necessary fields above.'); - if (!trakt_api) { - $('#trakt_api').addClass('warning'); - } else { - $('#trakt_api').removeClass('warning'); - } if (!trakt_username) { $('#trakt_username').addClass('warning'); } else { @@ -319,10 +314,10 @@ $(document).ready(function(){ } return; } - $('#trakt_api,#trakt_username,#trakt_password').removeClass('warning'); + $('#trakt_username,#trakt_password').removeClass('warning'); $(this).prop('disabled', true); $('#testTrakt-result').html(loading); - $.get(sbRoot + '/home/testTrakt', {'api': trakt_api, 'username': trakt_username, 'password': trakt_password}) + $.get(sbRoot + '/home/testTrakt', {'username': trakt_username, 'password': trakt_password, 'disable_ssl': trakt_disable_ssl_verify}) .done(function (data) { $('#testTrakt-result').html(data); $('#testTrakt').prop('disabled', false); @@ -422,7 +417,7 @@ $(document).ready(function(){ if(msg){ $('#testPushbullet-result').html(loading); } - + var pushbullet_api = $("#pushbullet_api").val(); if(!pushbullet_api) { @@ -460,7 +455,7 @@ $(document).ready(function(){ $('#getPushbulletDevices').click(function(){ get_pushbullet_devices("Device list updated. Please choose a device to push to."); }); - + // we have to call this function on dom ready to create the devices select get_pushbullet_devices(); diff --git a/gui/slick/js/recommendedShows.js b/gui/slick/js/recommendedShows.js index caec10d9..9f7165b3 100644 --- a/gui/slick/js/recommendedShows.js +++ b/gui/slick/js/recommendedShows.js @@ -1,4 +1,5 @@ $(document).ready(function () { + $('#searchResults').html(' loading recommended shows...'); function getRecommendedShows() { $.getJSON(sbRoot + '/home/addShows/getRecommendedShows', {}, function (data) { var firstResult = true; diff --git a/lib/trakt/trakt.py b/lib/trakt/trakt.py index c802cd40..90533afe 100644 --- a/lib/trakt/trakt.py +++ b/lib/trakt/trakt.py @@ -1,27 +1,67 @@ import requests +import json +from sickbeard import logger -from requests.auth import HTTPBasicAuth from exceptions import traktException, traktAuthException, traktServerBusy class TraktAPI(): - def __init__(self, apikey, username=None, password=None, use_https=False, timeout=5): - self.apikey = apikey + def __init__(self, apikey, username=None, password=None, disable_ssl_verify=False, timeout=30): self.username = username self.password = password - - self.protocol = 'https://' if use_https else 'http://' + self.verify = not disable_ssl_verify self.timeout = timeout + self.api_url = 'https://api.trakt.tv/' + self.headers = { + 'Content-Type': 'application/json', + 'trakt-api-version': '2', + 'trakt-api-key': apikey, + } def validateAccount(self): - return self.traktRequest("account/test/%APIKEY%", method='POST') + if hasattr(self, 'token'): + del(self.token) + data = { + 'login': self.username, + 'password': self.password + } + try: + resp = requests.request('POST', self.api_url+"auth/login", headers=self.headers, + data=json.dumps(data), timeout=self.timeout, verify=self.verify) + resp.raise_for_status() + resp = resp.json() + except (requests.HTTPError, requests.ConnectionError) as e: + code = getattr(e.response, 'status_code', None) + if not code: + # This is pretty much a fatal error if there is no status_code + # It means there basically was no response at all + raise traktException(e) + elif code == 502: + # Retry the request, cloudflare had a proxying issue + logger.log(u"Retrying trakt api request: auth/login", logger.WARNING) + return self.validateAccount() + elif code == 401: + raise traktAuthException(e) + elif code == 503: + raise traktServerBusy(e) + else: + raise traktException(e) + if 'token' in resp: + self.token = resp['token'] + return True + return False - def traktRequest(self, url, data=None, method='GET'): - base_url = self.protocol + 'api.trakt.tv/%s' % url.replace('%APIKEY%', self.apikey).replace('%USER%', - self.username) + def traktRequest(self, path, data=None, method='GET'): + url = self.api_url + path + headers = self.headers + if not getattr(self, 'token', None): + self.validateAccount() + headers['trakt-user-login'] = self.username + headers['trakt-user-token'] = self.token # request the URL from trakt and parse the result as json try: - resp = requests.request(method, base_url, auth=HTTPBasicAuth(self.username, self.password), data=data if data else []) + resp = requests.request(method, url, headers=headers, timeout=self.timeout, + data=json.dumps(data) if data else [], verify=self.verify) # check for http errors and raise if any are present resp.raise_for_status() @@ -29,9 +69,18 @@ class TraktAPI(): # convert response to json resp = resp.json() except (requests.HTTPError, requests.ConnectionError) as e: - if e.response.status_code == 401: + code = getattr(e.response, 'status_code', None) + if not code: + # This is pretty much a fatal error if there is no status_code + # It means there basically was no response at all + raise traktException(e) + elif code == 502: + # Retry the request, cloudflare had a proxying issue + logger.log(u"Retrying trakt api request: %s" % path, logger.WARNING) + return self.traktRequest(path, data, method) + elif code == 401: raise traktAuthException(e) - elif e.response.status_code == 503: + elif code == 503: raise traktServerBusy(e) else: raise traktException(e) diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index d367c76c..8ab13859 100755 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -393,7 +393,6 @@ SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = False USE_TRAKT = False TRAKT_USERNAME = None TRAKT_PASSWORD = None -TRAKT_API = '' TRAKT_REMOVE_WATCHLIST = False TRAKT_REMOVE_SERIESLIST = False TRAKT_USE_WATCHLIST = False @@ -402,6 +401,7 @@ TRAKT_START_PAUSED = False TRAKT_USE_RECOMMENDED = False TRAKT_SYNC = False TRAKT_DEFAULT_INDEXER = None +TRAKT_DISABLE_SSL_VERIFY = False USE_PYTIVO = False PYTIVO_NOTIFY_ONSNATCH = False @@ -483,7 +483,7 @@ REQUIRE_WORDS = "" CALENDAR_UNPROTECTED = False TMDB_API_KEY = 'edc5f123313769de83a71e157758030b' -TRAKT_API_KEY = 'abd806c54516240c76e4ebc9c5ccf394' +TRAKT_API_KEY = 'd4161a7a106424551add171e5470112e4afdaf2438e6ef2fe0548edc75924868' FANART_API_KEY = '9b3afaf26f6241bdb57d6cc6bd798da7' __INITIALIZED__ = False @@ -504,7 +504,7 @@ def initialize(consoleLogging=True): TORRENT_USERNAME, TORRENT_PASSWORD, TORRENT_HOST, TORRENT_PATH, TORRENT_SEED_TIME, TORRENT_PAUSED, TORRENT_HIGH_BANDWIDTH, TORRENT_LABEL, TORRENT_LABEL_ANIME, TORRENT_VERIFY_CERT, TORRENT_RPCURL, \ USE_KODI, KODI_ALWAYS_ON, KODI_NOTIFY_ONSNATCH, KODI_NOTIFY_ONDOWNLOAD, KODI_NOTIFY_ONSUBTITLEDOWNLOAD, KODI_UPDATE_FULL, KODI_UPDATE_ONLYFIRST, \ KODI_UPDATE_LIBRARY, KODI_HOST, KODI_USERNAME, KODI_PASSWORD, BACKLOG_FREQUENCY, \ - USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, \ + USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, TRAKT_DISABLE_SSL_VERIFY, \ USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, \ PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \ showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, SORT_ARTICLE, showList, loadingShowList, \ @@ -913,7 +913,6 @@ def initialize(consoleLogging=True): USE_TRAKT = bool(check_setting_int(CFG, 'Trakt', 'use_trakt', 0)) TRAKT_USERNAME = check_setting_str(CFG, 'Trakt', 'trakt_username', '', censor_log=True) TRAKT_PASSWORD = check_setting_str(CFG, 'Trakt', 'trakt_password', '', censor_log=True) - TRAKT_API = check_setting_str(CFG, 'Trakt', 'trakt_api', '', censor_log=True) TRAKT_REMOVE_WATCHLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_remove_watchlist', 0)) TRAKT_REMOVE_SERIESLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_remove_serieslist', 0)) TRAKT_USE_WATCHLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_watchlist', 0)) @@ -922,6 +921,7 @@ def initialize(consoleLogging=True): TRAKT_USE_RECOMMENDED = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_recommended', 0)) TRAKT_SYNC = bool(check_setting_int(CFG, 'Trakt', 'trakt_sync', 0)) TRAKT_DEFAULT_INDEXER = check_setting_int(CFG, 'Trakt', 'trakt_default_indexer', 1) + TRAKT_DISABLE_SSL_VERIFY = bool(check_setting_int(CFG, 'Trakt', 'trakt_disable_ssl_verify', 0)) CheckSection(CFG, 'pyTivo') USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0)) @@ -1786,7 +1786,6 @@ def save_config(): new_config['Trakt']['use_trakt'] = int(USE_TRAKT) new_config['Trakt']['trakt_username'] = TRAKT_USERNAME new_config['Trakt']['trakt_password'] = helpers.encrypt(TRAKT_PASSWORD, ENCRYPTION_VERSION) - new_config['Trakt']['trakt_api'] = TRAKT_API new_config['Trakt']['trakt_remove_watchlist'] = int(TRAKT_REMOVE_WATCHLIST) new_config['Trakt']['trakt_remove_serieslist'] = int(TRAKT_REMOVE_SERIESLIST) new_config['Trakt']['trakt_use_watchlist'] = int(TRAKT_USE_WATCHLIST) @@ -1795,6 +1794,7 @@ def save_config(): new_config['Trakt']['trakt_use_recommended'] = int(TRAKT_USE_RECOMMENDED) new_config['Trakt']['trakt_sync'] = int(TRAKT_SYNC) new_config['Trakt']['trakt_default_indexer'] = int(TRAKT_DEFAULT_INDEXER) + new_config['Trakt']['trakt_disable_ssl_verify'] = int(TRAKT_DISABLE_SSL_VERIFY) new_config['pyTivo'] = {} new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO) diff --git a/sickbeard/notifiers/trakt.py b/sickbeard/notifiers/trakt.py index 39f958ca..2d0e8526 100644 --- a/sickbeard/notifiers/trakt.py +++ b/sickbeard/notifiers/trakt.py @@ -42,93 +42,86 @@ class TraktNotifier: def update_library(self, ep_obj): """ Sends a request to trakt indicating that the given episode is part of our library. - + ep_obj: The TVEpisode object to add to trakt """ trakt_id = sickbeard.indexerApi(ep_obj.show.indexer).config['trakt_id'] - trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD) + trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, sickbeard.TRAKT_DISABLE_SSL_VERIFY) if sickbeard.USE_TRAKT: try: # URL parameters data = { - 'title': ep_obj.show.name, - 'year': ep_obj.show.startyear, - 'episodes': [{ - 'season': ep_obj.season, - 'episode': ep_obj.episode - }] + 'shows': [ + { + 'title': ep_obj.show.name, + 'year': ep_obj.show.startyear, + 'ids': {}, + 'seasons': [ + { + 'number': ep_obj.season, + 'episodes': [ + { + 'number': ep_obj.episode + } + ] + } + ] + } + ] } if trakt_id == 'tvdb_id': - data[trakt_id] = ep_obj.show.indexerid + data['shows'][0]['ids']['tvdb'] = ep_obj.show.indexerid + else: + data['shows'][0]['ids']['tvrage'] = ep_obj.show.indexerid # update library - trakt_api.traktRequest("show/episode/library/%APIKEY%", data, method='POST') + trakt_api.traktRequest("sync/collection", data, method='POST') # remove from watchlist if sickbeard.TRAKT_REMOVE_WATCHLIST: - trakt_api.traktRequest("show/episode/unwatchlist/%APIKEY%", data, method='POST') + trakt_api.traktRequest("sync/watchlist/remove", data, method='POST') if sickbeard.TRAKT_REMOVE_SERIESLIST: data = { 'shows': [ { 'title': ep_obj.show.name, - 'year': ep_obj.show.startyear + 'year': ep_obj.show.startyear, + 'ids': {} } ] } if trakt_id == 'tvdb_id': - data['shows'][0][trakt_id] = ep_obj.show.indexerid + data['shows'][0]['ids']['tvdb'] = ep_obj.show.indexerid + else: + data['shows'][0]['ids']['tvrage'] = ep_obj.show.indexerid - trakt_api.traktRequest("show/unwatchlist/%APIKEY%", data, method='POST') + trakt_api.traktRequest("sync/watchlist/remove", data, method='POST') - # Remove all episodes from episode watchlist - # Start by getting all episodes in the watchlist - watchlist = trakt_api.traktRequest("user/watchlist/episodes.json/%APIKEY%/%USER%") - - # Convert watchlist to only contain current show - if watchlist: - for show in watchlist: - if show[trakt_id] == ep_obj.show.indexerid: - data_show = { - 'title': show['title'], - trakt_id: show[trakt_id], - 'episodes': [] - } - - # Add series and episode (number) to the array - for episodes in show['episodes']: - ep = {'season': episodes['season'], 'episode': episodes['number']} - data_show['episodes'].append(ep) - - trakt_api.traktRequest("show/episode/unwatchlist/%APIKEY%", data_show, method='POST') except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) - def test_notify(self, api, username, password): + def test_notify(self, username, password, disable_ssl): """ Sends a test notification to trakt with the given authentication info and returns a boolean representing success. - + api: The api string to use username: The username to use password: The password to use - + Returns: True if the request succeeded, False otherwise """ - - trakt_api = TraktAPI(api, username, password) - try: - if trakt_api.validateAccount(): - return "Test notice sent successfully to Trakt" + trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, username, password, disable_ssl) + trakt_api.validateAccount() + return "Test notice sent successfully to Trakt" except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) - - return "Test notice failed to Trakt: %s" % ex(e) + return "Test notice failed to Trakt: %s" % ex(e) notifier = TraktNotifier diff --git a/sickbeard/traktChecker.py b/sickbeard/traktChecker.py index 2c14b069..e6cc8238 100644 --- a/sickbeard/traktChecker.py +++ b/sickbeard/traktChecker.py @@ -19,6 +19,7 @@ import os import traceback import datetime +import json import sickbeard from sickbeard import encodingKludge as ek @@ -36,7 +37,7 @@ class TraktChecker(): def __init__(self): self.todoWanted = [] - self.trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD) + self.trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, sickbeard.TRAKT_DISABLE_SSL_VERIFY) def run(self, force=False): try: @@ -59,7 +60,7 @@ class TraktChecker(): traktShow = None try: - library = self.trakt_api.traktRequest("user/library/shows/all.json/%APIKEY%/%USER%") + library = self.trakt_api.traktRequest("sync/collection/shows") or [] if not library: logger.log(u"Could not connect to trakt service, aborting library check", logger.ERROR) @@ -69,7 +70,7 @@ class TraktChecker(): logger.log(u"No shows found in your library, aborting library update", logger.DEBUG) return - traktShow = filter(lambda x: int(indexerid) in [int(x['tvdb_id']) or 0, int(x['tvrage_id'])] or 0, library) + traktShow = filter(lambda x: int(indexerid) in [int(x['show']['ids']['tvdb'] or 0), int(x['show']['ids']['tvrage'] or 0)], library) except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) @@ -83,14 +84,26 @@ class TraktChecker(): def removeShowFromTraktLibrary(self, show_obj): if self.findShow(show_obj.indexer, show_obj.indexerid): - # URL parameters - data = {'tvdb_id': helpers.mapIndexersToShow(show_obj)[1], 'title': show_obj.name, - 'year': show_obj.startyear} + trakt_id = sickbeard.indexerApi(show_obj.indexer).config['trakt_id'] + # URL parameters + data = { + 'shows': [ + { + 'title': show_obj.name, + 'year': show_obj.startyear, + 'ids': {} + } + ] + } + if trakt_id == 'tvdb_id': + data['shows'][0]['ids']['tvdb'] = show_obj.indexerid + else: + data['shows'][0]['ids']['tvrage'] = show_obj.indexerid logger.log(u"Removing " + show_obj.name + " from trakt.tv library", logger.DEBUG) try: - self.trakt_api.traktRequest("show/unlibrary/%APIKEY%", data, method='POST') + self.trakt_api.traktRequest("sync/collection/remove", data, method='POST') except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) pass @@ -105,16 +118,27 @@ class TraktChecker(): data = {} if not self.findShow(show_obj.indexer, show_obj.indexerid): + trakt_id = sickbeard.indexerApi(show_obj.indexer).config['trakt_id'] # URL parameters - data['tvdb_id'] = helpers.mapIndexersToShow(show_obj)[1] - data['title'] = show_obj.name - data['year'] = show_obj.startyear + data = { + 'shows': [ + { + 'title': show_obj.name, + 'year': show_obj.startyear, + 'ids': {} + } + ] + } + if trakt_id == 'tvdb_id': + data['shows'][0]['ids']['tvdb'] = show_obj.indexerid + else: + data['shows'][0]['ids']['tvrage'] = show_obj.indexerid if len(data): logger.log(u"Adding " + show_obj.name + " to trakt.tv library", logger.DEBUG) try: - self.trakt_api.traktRequest("show/library/%APIKEY%", data, method='POST') + self.trakt_api.traktRequest("sync/collection", data, method='POST') except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) return @@ -123,7 +147,7 @@ class TraktChecker(): logger.log(u"Starting trakt show watchlist check", logger.DEBUG) try: - watchlist = self.trakt_api.traktRequest("user/watchlist/shows.json/%APIKEY%/%USER%") + watchlist = self.trakt_api.traktRequest("sync/watchlist/shows") except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) return @@ -135,14 +159,14 @@ class TraktChecker(): for show in watchlist: indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER) if indexer == 2: - indexer_id = int(show["tvrage_id"]) + indexer_id = int(show["show"]["ids"]["tvrage"]) else: - indexer_id = int(show["tvdb_id"]) + indexer_id = int(show["show"]["ids"]["tvdb"]) if int(sickbeard.TRAKT_METHOD_ADD) != 2: - self.addDefaultShow(indexer, indexer_id, show["title"], SKIPPED) + self.addDefaultShow(indexer, indexer_id, show["show"]["title"], SKIPPED) else: - self.addDefaultShow(indexer, indexer_id, show["title"], WANTED) + self.addDefaultShow(indexer, indexer_id, show["show"]["title"], WANTED) if int(sickbeard.TRAKT_METHOD_ADD) == 1: newShow = helpers.findCertainShow(sickbeard.showList, indexer_id) @@ -158,7 +182,7 @@ class TraktChecker(): logger.log(u"Starting trakt episode watchlist check", logger.DEBUG) try: - watchlist = self.trakt_api.traktRequest("user/watchlist/episodes.json/%APIKEY%/%USER%") + watchlist = self.trakt_api.traktRequest("sync/watchlist/episodes") except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) return @@ -170,22 +194,22 @@ class TraktChecker(): for show in watchlist: indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER) if indexer == 2: - indexer_id = int(show["tvrage_id"]) + indexer_id = int(show["show"]["ids"]["tvrage"]) else: - indexer_id = int(show["tvdb_id"]) + indexer_id = int(show["show"]["ids"]["tvdb"]) - self.addDefaultShow(indexer, indexer_id, show["title"], SKIPPED) + self.addDefaultShow(indexer, indexer_id, show["show"]["title"], SKIPPED) newShow = helpers.findCertainShow(sickbeard.showList, indexer_id) try: if newShow and newShow.indexer == indexer: - for episode in show["episodes"]: + for episode in show["episode"]: if newShow is not None: self.setEpisodeToWanted(newShow, episode["season"], episode["number"]) else: self.todoWanted.append((indexer_id, episode["season"], episode["number"])) except TypeError: - logger.log(u"Could not parse the output from trakt for " + show["title"], logger.DEBUG) + logger.log(u"Could not parse the output from trakt for " + show["show"]["title"], logger.DEBUG) def addDefaultShow(self, indexer, indexer_id, name, status): """ diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 68cf53f5..e84ca539 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -928,9 +928,13 @@ class Home(WebRoot): "dbloc": dbloc} - def testTrakt(self, api=None, username=None, password=None): + def testTrakt(self, username=None, password=None, disable_ssl=None): # self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') - return notifiers.trakt_notifier.test_notify(api, username, password) + if disable_ssl == 'true': + disable_ssl = True + else: + disable_ssl = False + return notifiers.trakt_notifier.test_notify(username, password, disable_ssl) def loadShowNotifyLists(self): @@ -2218,19 +2222,20 @@ class HomeAddShows(Home): logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG) - trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD) + trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, sickbeard.TRAKT_DISABLE_SSL_VERIFY) try: - recommendedlist = trakt_api.traktRequest("recommendations/shows.json/%APIKEY%", method='POST') + recommendedlist = trakt_api.traktRequest("recommendations/shows?extended=full,images") if recommendedlist: - indexers = ['tvdb_id', 'tvrage_id'] + indexers = ['tvdb', 'tvrage'] map(final_results.append, ( - [int(show[indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]]), show['url'], show['title'], - show['overview'], - datetime.date.fromtimestamp(int(show['first_aired']) / 1000.0).strftime('%Y%m%d')] + [int(show['show']['ids'][indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]]), + 'http://www.trakt.tv/shows/%s' % show['show']['ids']['slug'], show['show']['title'], + show['show']['overview'], + datetime.date.fromtimestamp(int(show['show']['first_aired']) / 1000.0).strftime('%Y%m%d')] for show in recommendedlist if not helpers.findCertainShow(sickbeard.showList, [ - int(show[indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]])]))) + int(show['show']['ids'][indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]])]))) except (traktException, traktAuthException, traktServerBusy) as e: logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) @@ -2273,14 +2278,16 @@ class HomeAddShows(Home): t.trending_shows = [] - trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD) + trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, sickbeard.TRAKT_DISABLE_SSL_VERIFY) try: - shows = trakt_api.traktRequest("shows/trending.json/%APIKEY%") or [] + shows = trakt_api.traktRequest("shows/trending?limit=50&extended=full,images") or [] for show in shows: try: + tvdb_id = int(show['show']['ids']['tvdb']) + tvrage_id = int(show['show']['ids']['tvrage'] or 0) if not helpers.findCertainShow(sickbeard.showList, - [int(show['tvdb_id']), int(show['tvrage_id'])]): + [tvdb_id, tvrage_id]): t.trending_shows += [show] except exceptions.MultipleShowObjectsException: continue @@ -4391,10 +4398,10 @@ class ConfigNotifications(Config): libnotify_notify_onsubtitledownload=None, use_nmj=None, nmj_host=None, nmj_database=None, nmj_mount=None, use_synoindex=None, use_nmjv2=None, nmjv2_host=None, nmjv2_dbloc=None, nmjv2_database=None, - use_trakt=None, trakt_username=None, trakt_password=None, trakt_api=None, + use_trakt=None, trakt_username=None, trakt_password=None, trakt_remove_watchlist=None, trakt_use_watchlist=None, trakt_method_add=None, trakt_start_paused=None, trakt_use_recommended=None, trakt_sync=None, - trakt_default_indexer=None, trakt_remove_serieslist=None, + trakt_default_indexer=None, trakt_remove_serieslist=None, trakt_disable_ssl_verify=None, use_synologynotifier=None, synologynotifier_notify_onsnatch=None, synologynotifier_notify_ondownload=None, synologynotifier_notify_onsubtitledownload=None, use_pytivo=None, pytivo_notify_onsnatch=None, pytivo_notify_ondownload=None, @@ -4507,7 +4514,6 @@ class ConfigNotifications(Config): sickbeard.USE_TRAKT = config.checkbox_to_value(use_trakt) sickbeard.TRAKT_USERNAME = trakt_username sickbeard.TRAKT_PASSWORD = trakt_password - sickbeard.TRAKT_API = trakt_api sickbeard.TRAKT_REMOVE_WATCHLIST = config.checkbox_to_value(trakt_remove_watchlist) sickbeard.TRAKT_REMOVE_SERIESLIST = config.checkbox_to_value(trakt_remove_serieslist) sickbeard.TRAKT_USE_WATCHLIST = config.checkbox_to_value(trakt_use_watchlist) @@ -4516,6 +4522,7 @@ class ConfigNotifications(Config): sickbeard.TRAKT_USE_RECOMMENDED = config.checkbox_to_value(trakt_use_recommended) sickbeard.TRAKT_SYNC = config.checkbox_to_value(trakt_sync) sickbeard.TRAKT_DEFAULT_INDEXER = int(trakt_default_indexer) + sickbeard.TRAKT_DISABLE_SSL_VERIFY = config.checkbox_to_value(trakt_disable_ssl_verify) if sickbeard.USE_TRAKT: sickbeard.traktCheckerScheduler.silent = False