Test #3 for blank pages.

Syncs show library with trakt.tv show library on startup.
Adds/Removes shows individually to/from trakt.tv library.
Added use_recommended feature to trakt.tv notifier config page.
This commit is contained in:
echel0n 2014-06-28 20:28:00 -07:00
parent 77a659c17f
commit ca60203e9e
7 changed files with 105 additions and 53 deletions

View File

@ -1184,6 +1184,13 @@
<span class="component-desc">Get your key at: <a href="http://trakt.tv/settings/api" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">http://trakt.tv/settings/api</a></span>
</label>
</div>
<div class="field-pair">
<input type="checkbox" class="enabler" name="trakt_use_recommended" id="trakt_use_recommended" #if $sickbeard.TRAKT_USE_RECOMMENDED then "checked=\"checked\"" else ""# />
<label class="clearfix" for="trakt_use_recommended">
<span class="component-title">Use Recommended Shows:</span>
<span class="component-desc">Adds ability to add recommended shows from trakt.tv</span>
</label>
</div>
<div class="field-pair">
<input type="checkbox" class="enabler" name="trakt_use_watchlist" id="trakt_use_watchlist" #if $sickbeard.TRAKT_USE_WATCHLIST then "checked=\"checked\"" else ""# />
<label class="clearfix" for="trakt_use_watchlist">

View File

@ -29,6 +29,7 @@
<br/><br/>
#if $sickbeard.TRAKT_USE_RECOMMENDED:
<a href="$sbRoot/home/addShows/recommendedShows/" id="btnNewShow" class="btn btn-large">
<div class="button"><img src="$sbRoot/images/add-new32.png" height="32" width="32" alt="Add Recommended Shows"/></div>
<div class="buttontext">
@ -36,6 +37,7 @@
<p>For shows that you haven't downloaded yet, this option recommends shows to add based on your Trakt.tv watch list, creates a directory for its episodes, and adds it to SickRage. *** Trakt.tv must be enabled ***</p>
</div>
</a>
#end if
<br/><br/>

View File

@ -35,7 +35,7 @@ from providers import ezrss, tvtorrents, btn, newznab, womble, thepiratebay, tor
from sickbeard.config import CheckSection, check_setting_int, check_setting_str, check_setting_float, ConfigMigrator, \
naming_ep_type
from sickbeard import searchBacklog, showUpdater, versionChecker, properFinder, autoPostProcesser, \
subtitles, traktWatchListChecker
subtitles, traktChecker
from sickbeard import helpers, db, exceptions, show_queue, search_queue, scheduler, show_name_helpers
from sickbeard import logger
from sickbeard import naming
@ -85,7 +85,7 @@ searchQueueScheduler = None
properFinderScheduler = None
autoPostProcesserScheduler = None
subtitlesFinderScheduler = None
traktWatchListCheckerScheduler = None
traktCheckerScheduler = None
showList = None
loadingShowList = None
@ -354,6 +354,7 @@ TRAKT_REMOVE_WATCHLIST = False
TRAKT_USE_WATCHLIST = False
TRAKT_METHOD_ADD = 0
TRAKT_START_PAUSED = False
TRAKT_USE_RECOMMENDED = False
USE_PYTIVO = False
PYTIVO_NOTIFY_ONSNATCH = False
@ -444,7 +445,7 @@ def initialize(consoleLogging=True):
TORRENT_USERNAME, TORRENT_PASSWORD, TORRENT_HOST, TORRENT_PATH, TORRENT_SEED_TIME, TORRENT_PAUSED, TORRENT_HIGH_BANDWIDTH, TORRENT_LABEL, TORRENT_VERIFY_CERT, \
USE_XBMC, XBMC_ALWAYS_ON, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, \
XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, BACKLOG_FREQUENCY, \
USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktWatchListCheckerScheduler, \
USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API, TRAKT_REMOVE_WATCHLIST, TRAKT_USE_WATCHLIST, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, TRAKT_USE_RECOMMENDED, \
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, SORT_ARTICLE, showList, loadingShowList, \
@ -792,6 +793,7 @@ def initialize(consoleLogging=True):
TRAKT_USE_WATCHLIST = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_watchlist', 0))
TRAKT_METHOD_ADD = check_setting_str(CFG, 'Trakt', 'trakt_method_add', "0")
TRAKT_START_PAUSED = bool(check_setting_int(CFG, 'Trakt', 'trakt_start_paused', 0))
TRAKT_USE_RECOMMENDED = bool(check_setting_int(CFG, 'Trakt', 'trakt_use_recommended', 0))
CheckSection(CFG, 'pyTivo')
USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0))
@ -1006,9 +1008,9 @@ def initialize(consoleLogging=True):
threadName="POSTPROCESSER",
silent=not PROCESS_AUTOMATICALLY)
traktWatchListCheckerScheduler = scheduler.Scheduler(traktWatchListChecker.TraktChecker(),
traktCheckerScheduler = scheduler.Scheduler(traktChecker.TraktChecker(),
cycleTime=datetime.timedelta(hours=1),
threadName="TRAKTWATCHLIST",
threadName="TRAKTCHECKER",
silent=not USE_TRAKT)
subtitlesFinderScheduler = scheduler.Scheduler(subtitles.SubtitlesFinder(),
@ -1122,7 +1124,7 @@ def start():
global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, USE_SUBTITLES,traktWatchListCheckerScheduler, \
subtitlesFinderScheduler, USE_SUBTITLES,traktCheckerScheduler, \
dailySearchScheduler, started
with INIT_LOCK:
@ -1163,8 +1165,8 @@ def start():
if USE_SUBTITLES:
subtitlesFinderScheduler.thread.start()
# start the trakt watchlist
traktWatchListCheckerScheduler.thread.start()
# start the trakt checker
traktCheckerScheduler.thread.start()
started = True
@ -1173,7 +1175,7 @@ def halt():
global __INITIALIZED__, maintenanceScheduler, backlogSearchScheduler, \
showUpdateScheduler, versionCheckScheduler, showQueueScheduler, \
properFinderScheduler, autoPostProcesserScheduler, searchQueueScheduler, \
subtitlesFinderScheduler, traktWatchListCheckerScheduler, \
subtitlesFinderScheduler, traktCheckerScheduler, \
dailySearchScheduler, started
with INIT_LOCK:
@ -1240,10 +1242,10 @@ def halt():
except:
pass
traktWatchListCheckerScheduler.abort = True
logger.log(u"Waiting for the TRAKTWATCHLIST thread to exit")
traktCheckerScheduler.abort = True
logger.log(u"Waiting for the TRAKTCHECKER thread to exit")
try:
traktWatchListCheckerScheduler.thread.join(10)
traktCheckerScheduler.thread.join(10)
except:
pass
@ -1665,6 +1667,7 @@ def save_config():
new_config['Trakt']['trakt_use_watchlist'] = int(TRAKT_USE_WATCHLIST)
new_config['Trakt']['trakt_method_add'] = TRAKT_METHOD_ADD
new_config['Trakt']['trakt_start_paused'] = int(TRAKT_START_PAUSED)
new_config['Trakt']['trakt_use_recommended'] = int(TRAKT_USE_RECOMMENDED)
new_config['pyTivo'] = {}
new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO)

View File

@ -60,26 +60,6 @@ class TraktNotifier:
if sickbeard.TRAKT_REMOVE_WATCHLIST:
TraktCall("show/episode/unwatchlist/%API%", self._api(), self._username(), self._password(), data)
def update_show_library(self, show_obj):
"""
Sends a request to trakt indicating that the given show and all its episodes is part of our library.
show_obj: The TVShow object to add to trakt
"""
if sickbeard.USE_TRAKT:
# URL parameters
data = {
'tvdb_id': show_obj.indexerid,
'title': show_obj.name,
'year': show_obj.startyear,
}
if data is not None:
TraktCall("show/library/%API%", self._api(), self._username(), self._password(), data)
def test_notify(self, api, username, password):
"""
Sends a test notification to trakt with the given authentication info and returns a boolean

View File

@ -385,8 +385,12 @@ class QueueItemAdd(ShowQueueItem):
self.show.flushEpisodes()
# if there are specific episodes that need to be added by trakt
sickbeard.traktWatchListCheckerScheduler.action.manageNewShow(self.show)
if sickbeard.USE_TRAKT:
# if there are specific episodes that need to be added by trakt
sickbeard.traktCheckerScheduler.action.manageNewShow(self.show)
# add show to trakt.tv library
sickbeard.traktCheckerScheduler.action.addShowToTraktLibrary(self.show)
# Load XEM data to DB for show
sickbeard.scene_numbering.xem_refresh(self.show.indexerid, self.show.indexer, force=True)

View File

@ -34,6 +34,7 @@ class TraktChecker():
self.todoBacklog = []
def run(self, force=False):
# add shows from trakt.tv watchlist
if sickbeard.TRAKT_USE_WATCHLIST:
self.todoWanted = [] #its about to all get re-added
if len(sickbeard.ROOT_DIRS.split('|')) < 2:
@ -42,6 +43,60 @@ class TraktChecker():
self.updateShows()
self.updateEpisodes()
# sync trakt.tv library with sickrage library
if sickbeard.TRAKT_USE_RECOMMENDED:
self.syncLibrary()
def findShow(self, indexerid):
library = TraktCall("user/library/shows/all.json/%API%/" + sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_API,
sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD)
results = filter(lambda x: int(x['tvdb_id']) == int(indexerid), library)
if len(results) == 0:
return None
else:
return results[0]
def syncLibrary(self):
logger.log(u"Syncing library to trakt.tv show library", logger.DEBUG)
for myShow in sickbeard.showList:
self.addShowToTraktLibrary(myShow)
def removeShowFromTraktLibrary(self, show_obj):
if not self.findShow(show_obj.indexerid):
return
# URL parameters
data = {
'tvdb_id': show_obj.indexerid,
'title': show_obj.name,
'year': show_obj.startyear,
}
if data is not None:
logger.log(u"Removing " + show_obj.name + " from trakt.tv library", logger.DEBUG)
TraktCall("show/unlibrary/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, data)
def addShowToTraktLibrary(self, show_obj):
"""
Sends a request to trakt indicating that the given show and all its episodes is part of our library.
show_obj: The TVShow object to add to trakt
"""
if self.findShow(show_obj.indexerid):
return
# URL parameters
data = {
'tvdb_id': show_obj.indexerid,
'title': show_obj.name,
'year': show_obj.startyear,
}
if data is not None:
logger.log(u"Adding " + show_obj.name + " to trakt.tv library", logger.DEBUG)
TraktCall("show/library/%API%", sickbeard.TRAKT_API, sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD, data)
def updateShows(self):
logger.log(u"Starting trakt show watchlist check", logger.DEBUG)

View File

@ -210,7 +210,7 @@ class MainHandler(RequestHandler):
def redirect(self, url, permanent=False, status=None):
self._transforms = []
return super(MainHandler, self).redirect(sickbeard.WEB_ROOT + url, permanent, status)
return super(MainHandler, self).redirect(sickbeard.WEB_ROOT + url, True, 303)
def get(self, *args, **kwargs):
response = self._dispatch()
@ -2177,7 +2177,7 @@ class ConfigNotifications(MainHandler):
use_nmjv2=None, nmjv2_host=None, nmjv2_dbloc=None, nmjv2_database=None,
use_trakt=None, trakt_username=None, trakt_password=None, trakt_api=None,
trakt_remove_watchlist=None, trakt_use_watchlist=None, trakt_method_add=None,
trakt_start_paused=None,
trakt_start_paused=None, trakt_use_recommended=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,
@ -2288,11 +2288,12 @@ class ConfigNotifications(MainHandler):
sickbeard.TRAKT_USE_WATCHLIST = config.checkbox_to_value(trakt_use_watchlist)
sickbeard.TRAKT_METHOD_ADD = trakt_method_add
sickbeard.TRAKT_START_PAUSED = config.checkbox_to_value(trakt_start_paused)
sickbeard.TRAKT_USE_RECOMMENDED = config.checkbox_to_value(trakt_use_recommended)
if sickbeard.USE_TRAKT:
sickbeard.traktWatchListCheckerScheduler.silent = False
sickbeard.traktCheckerScheduler.silent = False
else:
sickbeard.traktWatchListCheckerScheduler.silent = True
sickbeard.traktCheckerScheduler.silent = True
sickbeard.USE_EMAIL = config.checkbox_to_value(use_email)
sickbeard.EMAIL_NOTIFY_ONSNATCH = config.checkbox_to_value(email_notify_onsnatch)
@ -2735,22 +2736,18 @@ class NewHomeAddShows(MainHandler):
def getRecommendedShows(self, *args, **kwargs):
final_results = []
if sickbeard.USE_TRAKT:
for myShow in sickbeard.showList:
notifiers.trakt_notifier.update_show_library(myShow)
logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG)
recommendedlist = TraktCall("recommendations/shows.json/%API%/" + sickbeard.TRAKT_USERNAME,
sickbeard.TRAKT_API,
sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD)
if recommendedlist is None:
logger.log(u"Could not connect to trakt service, aborting recommended list update", logger.ERROR)
return
logger.log(u"Getting recommended shows from Trakt.tv", logger.DEBUG)
recommendedlist = TraktCall("recommendations/shows.json/%API%/" + sickbeard.TRAKT_USERNAME,
sickbeard.TRAKT_API,
sickbeard.TRAKT_USERNAME, sickbeard.TRAKT_PASSWORD)
if recommendedlist is None:
logger.log(u"Could not connect to trakt service, aborting recommended list update", logger.ERROR)
return
map(final_results.append, ([int(show['tvdb_id']), show['url'], show['title'], show['overview'],
datetime.date.fromtimestamp(show['first_aired']).strftime('%Y%m%d')] for show in
recommendedlist if
not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
map(final_results.append, ([int(show['tvdb_id']), show['url'], show['title'], show['overview'],
datetime.date.fromtimestamp(show['first_aired']).strftime('%Y%m%d')] for show in
recommendedlist if
not helpers.findCertainShow(sickbeard.showList, indexerid=int(show['tvdb_id']))))
return json.dumps({'results': final_results})
@ -3823,6 +3820,10 @@ class Home(MainHandler):
showObj) or sickbeard.showQueueScheduler.action.isBeingUpdated(showObj): # @UndefinedVariable
return _genericMessage("Error", "Shows can't be deleted while they're being added or updated.")
if sickbeard.USE_TRAKT:
# remove show from trakt.tv library
sickbeard.traktCheckerScheduler.action.removeShowFromTraktLibrary(showObj)
showObj.deleteShow()
ui.notifications.message('<b>%s</b> has been deleted' % showObj.name)