1
0
mirror of https://github.com/moparisthebest/SickRage synced 2024-08-13 16:53:54 -04:00

Merge pull request #1241 from LinuxBozo/trakt-api-2

Update to Trakt.tv API 2.0
This commit is contained in:
echel0n 2015-01-29 14:52:40 -08:00
commit c7c6fd42b1
9 changed files with 221 additions and 154 deletions

View File

@ -1391,13 +1391,12 @@
</label> </label>
</div> </div>
<div class="field-pair"> <div class="field-pair">
<label for="trakt_api"> <label for="trakt_disable_ssl_verify">
<span class="component-title">Trakt API key:</span> <span class="component-title">Disable SSL Verification:</span>
<input type="text" name="trakt_api" id="trakt_api" value="$sickbeard.TRAKT_API" class="form-control input-sm input250" /> <span class="component-desc">
</label> <input type="checkbox" class="enabler" name="trakt_disable_ssl_verify" id="trakt_disable_ssl_verify" #if $sickbeard.TRAKT_DISABLE_SSL_VERIFY then "checked=\"checked\"" else ""# />
<label> <p>Disable SSL certificate verification on systems with broken SSL implementations, like the QNAP NAS.</p>
<span class="component-title">&nbsp;</span> </span>
<span class="component-desc">get your key at: <a href="<%= anon_url('http://trakt.tv/settings/api') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;"><b>http://trakt.tv/settings/api</b></a></span>
</label> </label>
</div> </div>
<div class="field-pair"> <div class="field-pair">

View File

@ -75,24 +75,23 @@
</div> </div>
#else #else
#for $cur_show in $trending_shows: #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']
<div class="trakt_show" data-name="$cur_show['title']" data-rating="$cur_show['ratings']['percentage']" data-votes="$cur_show['ratings']['votes']"> <div class="trakt_show" data-name="$cur_show['show']['title']" data-rating="$cur_show['show']['rating']" data-votes="$cur_show['show']['votes']">
<div class="traktContainer"> <div class="traktContainer">
<div class="trakt-image"> <div class="trakt-image">
<a class="trakt-image" href="<%= anon_url(cur_show['url']) %>" target="_blank"><img alt="" class="trakt-image" src="${image}" /></a> <a class="trakt-image" href="<%= anon_url(show_url) %>" target="_blank"><img alt="" class="trakt-image" src="$cur_show['show']['images']['poster']['thumb']" /></a>
</div> </div>
<div class="show-title"> <div class="show-title">
<%= (cur_show['title'], '<span>&nbsp;</span>')[ '' == cur_show['title']] %> <%= (cur_show['show']['title'], '<span>&nbsp;</span>')[ '' == cur_show['show']['title']] %>
</div> </div>
<div class="clearfix"> <div class="clearfix">
<p>$cur_show['ratings']['percentage']% <img src="$sbRoot/images/heart.png"></p> <p><%= int(cur_show['show']['rating']*10) %>% <img src="$sbRoot/images/heart.png"></p>
<i>$cur_show['ratings']['votes'] votes</i> <i>$cur_show['show']['votes'] votes</i>
<div class="traktShowTitleIcons"> <div class="traktShowTitleIcons">
<a href="$sbRoot/home/addShows/addTraktShow?indexer_id=${cur_show['tvdb_id'] or cur_show['tvrage_id']}&amp;showName=${cur_show['title']}" class="btn btn-xs">Add Show</a> <a href="$sbRoot/home/addShows/addTraktShow?indexer_id=${cur_show['show']['ids']['tvdb'] or cur_show['show']['ids']['tvrage']}&amp;showName=${cur_show['show']['title']}" class="btn btn-xs">Add Show</a>
</div> </div>
</div> </div>
</div> </div>

View File

@ -297,16 +297,11 @@ $(document).ready(function(){
}); });
$('#testTrakt').click(function () { $('#testTrakt').click(function () {
var trakt_api = $.trim($('#trakt_api').val());
var trakt_username = $.trim($('#trakt_username').val()); var trakt_username = $.trim($('#trakt_username').val());
var trakt_password = $.trim($('#trakt_password').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.'); $('#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) { if (!trakt_username) {
$('#trakt_username').addClass('warning'); $('#trakt_username').addClass('warning');
} else { } else {
@ -319,10 +314,10 @@ $(document).ready(function(){
} }
return; return;
} }
$('#trakt_api,#trakt_username,#trakt_password').removeClass('warning'); $('#trakt_username,#trakt_password').removeClass('warning');
$(this).prop('disabled', true); $(this).prop('disabled', true);
$('#testTrakt-result').html(loading); $('#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) { .done(function (data) {
$('#testTrakt-result').html(data); $('#testTrakt-result').html(data);
$('#testTrakt').prop('disabled', false); $('#testTrakt').prop('disabled', false);

View File

@ -1,4 +1,5 @@
$(document).ready(function () { $(document).ready(function () {
$('#searchResults').html('<img id="searchingAnim" src="' + sbRoot + '/images/loading32' + themeSpinner + '.gif" height="32" width="32" /> loading recommended shows...');
function getRecommendedShows() { function getRecommendedShows() {
$.getJSON(sbRoot + '/home/addShows/getRecommendedShows', {}, function (data) { $.getJSON(sbRoot + '/home/addShows/getRecommendedShows', {}, function (data) {
var firstResult = true; var firstResult = true;

View File

@ -1,27 +1,67 @@
import requests import requests
import json
from sickbeard import logger
from requests.auth import HTTPBasicAuth
from exceptions import traktException, traktAuthException, traktServerBusy from exceptions import traktException, traktAuthException, traktServerBusy
class TraktAPI(): class TraktAPI():
def __init__(self, apikey, username=None, password=None, use_https=False, timeout=5): def __init__(self, apikey, username=None, password=None, disable_ssl_verify=False, timeout=30):
self.apikey = apikey
self.username = username self.username = username
self.password = password self.password = password
self.verify = not disable_ssl_verify
self.protocol = 'https://' if use_https else 'http://'
self.timeout = timeout 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): 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'): def traktRequest(self, path, data=None, method='GET'):
base_url = self.protocol + 'api.trakt.tv/%s' % url.replace('%APIKEY%', self.apikey).replace('%USER%', url = self.api_url + path
self.username) 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 # request the URL from trakt and parse the result as json
try: 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 # check for http errors and raise if any are present
resp.raise_for_status() resp.raise_for_status()
@ -29,9 +69,18 @@ class TraktAPI():
# convert response to json # convert response to json
resp = resp.json() resp = resp.json()
except (requests.HTTPError, requests.ConnectionError) as e: 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) raise traktAuthException(e)
elif e.response.status_code == 503: elif code == 503:
raise traktServerBusy(e) raise traktServerBusy(e)
else: else:
raise traktException(e) raise traktException(e)

View File

@ -393,7 +393,6 @@ SYNOLOGYNOTIFIER_NOTIFY_ONSUBTITLEDOWNLOAD = False
USE_TRAKT = False USE_TRAKT = False
TRAKT_USERNAME = None TRAKT_USERNAME = None
TRAKT_PASSWORD = None TRAKT_PASSWORD = None
TRAKT_API = ''
TRAKT_REMOVE_WATCHLIST = False TRAKT_REMOVE_WATCHLIST = False
TRAKT_REMOVE_SERIESLIST = False TRAKT_REMOVE_SERIESLIST = False
TRAKT_USE_WATCHLIST = False TRAKT_USE_WATCHLIST = False
@ -402,6 +401,7 @@ TRAKT_START_PAUSED = False
TRAKT_USE_RECOMMENDED = False TRAKT_USE_RECOMMENDED = False
TRAKT_SYNC = False TRAKT_SYNC = False
TRAKT_DEFAULT_INDEXER = None TRAKT_DEFAULT_INDEXER = None
TRAKT_DISABLE_SSL_VERIFY = False
USE_PYTIVO = False USE_PYTIVO = False
PYTIVO_NOTIFY_ONSNATCH = False PYTIVO_NOTIFY_ONSNATCH = False
@ -483,7 +483,7 @@ REQUIRE_WORDS = ""
CALENDAR_UNPROTECTED = False CALENDAR_UNPROTECTED = False
TMDB_API_KEY = 'edc5f123313769de83a71e157758030b' TMDB_API_KEY = 'edc5f123313769de83a71e157758030b'
TRAKT_API_KEY = 'abd806c54516240c76e4ebc9c5ccf394' TRAKT_API_KEY = 'd4161a7a106424551add171e5470112e4afdaf2438e6ef2fe0548edc75924868'
FANART_API_KEY = '9b3afaf26f6241bdb57d6cc6bd798da7' FANART_API_KEY = '9b3afaf26f6241bdb57d6cc6bd798da7'
__INITIALIZED__ = False __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, \ 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, \ 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, \ 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, \ 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, \ 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, \ 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)) USE_TRAKT = bool(check_setting_int(CFG, 'Trakt', 'use_trakt', 0))
TRAKT_USERNAME = check_setting_str(CFG, 'Trakt', 'trakt_username', '', censor_log=True) 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_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_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_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)) 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_USE_RECOMMENDED = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_recommended', 0))
TRAKT_SYNC = bool(check_setting_int(CFG, 'Trakt', 'trakt_sync', 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_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') CheckSection(CFG, 'pyTivo')
USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0)) 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']['use_trakt'] = int(USE_TRAKT)
new_config['Trakt']['trakt_username'] = TRAKT_USERNAME new_config['Trakt']['trakt_username'] = TRAKT_USERNAME
new_config['Trakt']['trakt_password'] = helpers.encrypt(TRAKT_PASSWORD, ENCRYPTION_VERSION) 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_watchlist'] = int(TRAKT_REMOVE_WATCHLIST)
new_config['Trakt']['trakt_remove_serieslist'] = int(TRAKT_REMOVE_SERIESLIST) new_config['Trakt']['trakt_remove_serieslist'] = int(TRAKT_REMOVE_SERIESLIST)
new_config['Trakt']['trakt_use_watchlist'] = int(TRAKT_USE_WATCHLIST) 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_use_recommended'] = int(TRAKT_USE_RECOMMENDED)
new_config['Trakt']['trakt_sync'] = int(TRAKT_SYNC) new_config['Trakt']['trakt_sync'] = int(TRAKT_SYNC)
new_config['Trakt']['trakt_default_indexer'] = int(TRAKT_DEFAULT_INDEXER) 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'] = {}
new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO) new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO)

View File

@ -47,69 +47,65 @@ class TraktNotifier:
""" """
trakt_id = sickbeard.indexerApi(ep_obj.show.indexer).config['trakt_id'] 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: if sickbeard.USE_TRAKT:
try: try:
# URL parameters # URL parameters
data = { data = {
'title': ep_obj.show.name, 'shows': [
'year': ep_obj.show.startyear, {
'episodes': [{ 'title': ep_obj.show.name,
'season': ep_obj.season, 'year': ep_obj.show.startyear,
'episode': ep_obj.episode 'ids': {},
}] 'seasons': [
{
'number': ep_obj.season,
'episodes': [
{
'number': ep_obj.episode
}
]
}
]
}
]
} }
if trakt_id == 'tvdb_id': 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 # update library
trakt_api.traktRequest("show/episode/library/%APIKEY%", data, method='POST') trakt_api.traktRequest("sync/collection", data, method='POST')
# remove from watchlist # remove from watchlist
if sickbeard.TRAKT_REMOVE_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: if sickbeard.TRAKT_REMOVE_SERIESLIST:
data = { data = {
'shows': [ 'shows': [
{ {
'title': ep_obj.show.name, 'title': ep_obj.show.name,
'year': ep_obj.show.startyear 'year': ep_obj.show.startyear,
'ids': {}
} }
] ]
} }
if trakt_id == 'tvdb_id': 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) 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 Sends a test notification to trakt with the given authentication info and returns a boolean
representing success. representing success.
@ -120,15 +116,12 @@ class TraktNotifier:
Returns: True if the request succeeded, False otherwise Returns: True if the request succeeded, False otherwise
""" """
trakt_api = TraktAPI(api, username, password)
try: try:
if trakt_api.validateAccount(): trakt_api = TraktAPI(sickbeard.TRAKT_API_KEY, username, password, disable_ssl)
return "Test notice sent successfully to Trakt" trakt_api.validateAccount()
return "Test notice sent successfully to Trakt"
except (traktException, traktAuthException, traktServerBusy) as e: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) 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 notifier = TraktNotifier

View File

@ -19,6 +19,7 @@
import os import os
import traceback import traceback
import datetime import datetime
import json
import sickbeard import sickbeard
from sickbeard import encodingKludge as ek from sickbeard import encodingKludge as ek
@ -36,7 +37,7 @@ class TraktChecker():
def __init__(self): def __init__(self):
self.todoWanted = [] 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): def run(self, force=False):
try: try:
@ -59,7 +60,7 @@ class TraktChecker():
traktShow = None traktShow = None
try: 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: if not library:
logger.log(u"Could not connect to trakt service, aborting library check", logger.ERROR) 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) logger.log(u"No shows found in your library, aborting library update", logger.DEBUG)
return 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) 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): def removeShowFromTraktLibrary(self, show_obj):
if self.findShow(show_obj.indexer, show_obj.indexerid): if self.findShow(show_obj.indexer, show_obj.indexerid):
# URL parameters trakt_id = sickbeard.indexerApi(show_obj.indexer).config['trakt_id']
data = {'tvdb_id': helpers.mapIndexersToShow(show_obj)[1], 'title': show_obj.name,
'year': show_obj.startyear}
# 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) logger.log(u"Removing " + show_obj.name + " from trakt.tv library", logger.DEBUG)
try: 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING)
pass pass
@ -105,16 +118,27 @@ class TraktChecker():
data = {} data = {}
if not self.findShow(show_obj.indexer, show_obj.indexerid): if not self.findShow(show_obj.indexer, show_obj.indexerid):
trakt_id = sickbeard.indexerApi(show_obj.indexer).config['trakt_id']
# URL parameters # URL parameters
data['tvdb_id'] = helpers.mapIndexersToShow(show_obj)[1] data = {
data['title'] = show_obj.name 'shows': [
data['year'] = show_obj.startyear {
'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): if len(data):
logger.log(u"Adding " + show_obj.name + " to trakt.tv library", logger.DEBUG) logger.log(u"Adding " + show_obj.name + " to trakt.tv library", logger.DEBUG)
try: 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING)
return return
@ -123,7 +147,7 @@ class TraktChecker():
logger.log(u"Starting trakt show watchlist check", logger.DEBUG) logger.log(u"Starting trakt show watchlist check", logger.DEBUG)
try: 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING)
return return
@ -135,14 +159,14 @@ class TraktChecker():
for show in watchlist: for show in watchlist:
indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER) indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER)
if indexer == 2: if indexer == 2:
indexer_id = int(show["tvrage_id"]) indexer_id = int(show["show"]["ids"]["tvrage"])
else: else:
indexer_id = int(show["tvdb_id"]) indexer_id = int(show["show"]["ids"]["tvdb"])
if int(sickbeard.TRAKT_METHOD_ADD) != 2: 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: 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: if int(sickbeard.TRAKT_METHOD_ADD) == 1:
newShow = helpers.findCertainShow(sickbeard.showList, indexer_id) newShow = helpers.findCertainShow(sickbeard.showList, indexer_id)
@ -158,7 +182,7 @@ class TraktChecker():
logger.log(u"Starting trakt episode watchlist check", logger.DEBUG) logger.log(u"Starting trakt episode watchlist check", logger.DEBUG)
try: 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING)
return return
@ -170,22 +194,22 @@ class TraktChecker():
for show in watchlist: for show in watchlist:
indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER) indexer = int(sickbeard.TRAKT_DEFAULT_INDEXER)
if indexer == 2: if indexer == 2:
indexer_id = int(show["tvrage_id"]) indexer_id = int(show["show"]["ids"]["tvrage"])
else: 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) newShow = helpers.findCertainShow(sickbeard.showList, indexer_id)
try: try:
if newShow and newShow.indexer == indexer: if newShow and newShow.indexer == indexer:
for episode in show["episodes"]: for episode in show["episode"]:
if newShow is not None: if newShow is not None:
self.setEpisodeToWanted(newShow, episode["season"], episode["number"]) self.setEpisodeToWanted(newShow, episode["season"], episode["number"])
else: else:
self.todoWanted.append((indexer_id, episode["season"], episode["number"])) self.todoWanted.append((indexer_id, episode["season"], episode["number"]))
except TypeError: 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): def addDefaultShow(self, indexer, indexer_id, name, status):
""" """

View File

@ -928,9 +928,13 @@ class Home(WebRoot):
"dbloc": dbloc} "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') # 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): def loadShowNotifyLists(self):
@ -2218,19 +2222,20 @@ class HomeAddShows(Home):
logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG) 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: try:
recommendedlist = trakt_api.traktRequest("recommendations/shows.json/%APIKEY%", method='POST') recommendedlist = trakt_api.traktRequest("recommendations/shows?extended=full,images")
if recommendedlist: if recommendedlist:
indexers = ['tvdb_id', 'tvrage_id'] indexers = ['tvdb', 'tvrage']
map(final_results.append, ( map(final_results.append, (
[int(show[indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]]), show['url'], show['title'], [int(show['show']['ids'][indexers[sickbeard.TRAKT_DEFAULT_INDEXER - 1]]),
show['overview'], 'http://www.trakt.tv/shows/%s' % show['show']['ids']['slug'], show['show']['title'],
datetime.date.fromtimestamp(int(show['first_aired']) / 1000.0).strftime('%Y%m%d')] 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, [ 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: except (traktException, traktAuthException, traktServerBusy) as e:
logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING) logger.log(u"Could not connect to Trakt service: %s" % ex(e), logger.WARNING)
@ -2273,14 +2278,16 @@ class HomeAddShows(Home):
t.trending_shows = [] 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: 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: for show in shows:
try: try:
tvdb_id = int(show['show']['ids']['tvdb'])
tvrage_id = int(show['show']['ids']['tvrage'] or 0)
if not helpers.findCertainShow(sickbeard.showList, if not helpers.findCertainShow(sickbeard.showList,
[int(show['tvdb_id']), int(show['tvrage_id'])]): [tvdb_id, tvrage_id]):
t.trending_shows += [show] t.trending_shows += [show]
except exceptions.MultipleShowObjectsException: except exceptions.MultipleShowObjectsException:
continue continue
@ -4391,10 +4398,10 @@ class ConfigNotifications(Config):
libnotify_notify_onsubtitledownload=None, libnotify_notify_onsubtitledownload=None,
use_nmj=None, nmj_host=None, nmj_database=None, nmj_mount=None, use_synoindex=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_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_remove_watchlist=None, trakt_use_watchlist=None, trakt_method_add=None,
trakt_start_paused=None, trakt_use_recommended=None, trakt_sync=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, use_synologynotifier=None, synologynotifier_notify_onsnatch=None,
synologynotifier_notify_ondownload=None, synologynotifier_notify_onsubtitledownload=None, synologynotifier_notify_ondownload=None, synologynotifier_notify_onsubtitledownload=None,
use_pytivo=None, pytivo_notify_onsnatch=None, pytivo_notify_ondownload=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.USE_TRAKT = config.checkbox_to_value(use_trakt)
sickbeard.TRAKT_USERNAME = trakt_username sickbeard.TRAKT_USERNAME = trakt_username
sickbeard.TRAKT_PASSWORD = trakt_password sickbeard.TRAKT_PASSWORD = trakt_password
sickbeard.TRAKT_API = trakt_api
sickbeard.TRAKT_REMOVE_WATCHLIST = config.checkbox_to_value(trakt_remove_watchlist) sickbeard.TRAKT_REMOVE_WATCHLIST = config.checkbox_to_value(trakt_remove_watchlist)
sickbeard.TRAKT_REMOVE_SERIESLIST = config.checkbox_to_value(trakt_remove_serieslist) sickbeard.TRAKT_REMOVE_SERIESLIST = config.checkbox_to_value(trakt_remove_serieslist)
sickbeard.TRAKT_USE_WATCHLIST = config.checkbox_to_value(trakt_use_watchlist) 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_USE_RECOMMENDED = config.checkbox_to_value(trakt_use_recommended)
sickbeard.TRAKT_SYNC = config.checkbox_to_value(trakt_sync) sickbeard.TRAKT_SYNC = config.checkbox_to_value(trakt_sync)
sickbeard.TRAKT_DEFAULT_INDEXER = int(trakt_default_indexer) 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: if sickbeard.USE_TRAKT:
sickbeard.traktCheckerScheduler.silent = False sickbeard.traktCheckerScheduler.silent = False