diff --git a/.travis.yml b/.travis.yml index 9e41afd1d0fedac9d35c5910cf73850290d98adc..209f9697863360e8fd63c833d954abc14c45063a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,3 +21,7 @@ after_failure: notifications: irc: "irc.freenode.net#sickrage-updates" + + email: + on_success: change + on_failure: change diff --git a/gui/slick/images/notifiers/emby.png b/gui/slick/images/notifiers/emby.png new file mode 100644 index 0000000000000000000000000000000000000000..de19014fe177de9a28429f6ea415bfd71878e77e Binary files /dev/null and b/gui/slick/images/notifiers/emby.png differ diff --git a/gui/slick/images/providers/piratenzb.png b/gui/slick/images/providers/piratenzb.png new file mode 100644 index 0000000000000000000000000000000000000000..ce66c0290f0574d6fdc1d85dd835b8630cab51fa Binary files /dev/null and b/gui/slick/images/providers/piratenzb.png differ diff --git a/gui/slick/images/providers/piratenzb_com.png b/gui/slick/images/providers/piratenzb_com.png new file mode 100644 index 0000000000000000000000000000000000000000..ce66c0290f0574d6fdc1d85dd835b8630cab51fa Binary files /dev/null and b/gui/slick/images/providers/piratenzb_com.png differ diff --git a/gui/slick/interfaces/default/config_notifications.tmpl b/gui/slick/interfaces/default/config_notifications.tmpl index 1afaa4322342472ecd8329ce66f5b561b1492dcf..e17c379432ab8c0cd1659975914df72e8cbaaa38 100644 --- a/gui/slick/interfaces/default/config_notifications.tmpl +++ b/gui/slick/interfaces/default/config_notifications.tmpl @@ -332,6 +332,48 @@ </div><!-- /plex client component-group --> + <div class="component-group"> + <div class="component-group-desc"> + <img class="notifier-icon" src="$sbRoot/images/notifiers/emby.png" alt="" title="Emby" /> + <h3><a href="<%= anon_url('http://emby.media/') %>" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">Emby</a></h3> + <p>A home media server built using other popular open source technologies.</p> + </div> + <fieldset class="component-group-list"> + <div class="field-pair"> + <label for="use_emby"> + <span class="component-title">Enable</span> + <span class="component-desc"> + <input type="checkbox" class="enabler" name="use_emby" id="use_emby" #if $sickbeard.USE_EMBY then "checked=\"checked\"" else ""# /> + <p>should SickRage send update commands to Emby?<p> + </span> + </label> + </div> + <div id="content_use_emby"> + <div class="field-pair"> + <label for="emby_host"> + <span class="component-title">Emby IP:Port</span> + <input type="text" name="emby_host" id="emby_host" value="$sickbeard.EMBY_HOST" class="form-control input-sm input250" /> + </label> + <label> + <span class="component-title"> </span> + <span class="component-desc">host running Emby (eg. 192.168.1.100:8096)</span> + </label> + </div> + <div class="field-pair"> + <label for="emby_apikey"> + <span class="component-title">Emby API Key</span> + <input type="text" name="emby_apikey" id="emby_apikey" value="$sickbeard.EMBY_APIKEY" class="form-control input-sm input250" /> + </label> + </div> + <div class="testNotification" id="testEMBY-result">Click below to test.</div> + <input class="btn" type="button" value="Test Emby" id="testEMBY" /> + <input type="submit" class="config_submitter btn" value="Save Changes" /> + </div> + <!-- /content_use_emby //--> + </fieldset> + </div><!-- /emby component-group //--> + + <div class="component-group"> <div class="component-group-desc"> <img class="notifier-icon" src="$sbRoot/images/notifiers/nmj.png" alt="" title="Networked Media Jukebox" /> diff --git a/gui/slick/interfaces/default/inc_top.tmpl b/gui/slick/interfaces/default/inc_top.tmpl index 0499190e550fdae16ff1311c8cdf744ed675f981..04c87647cee950ddd82f420850c106424c1a2e0f 100644 --- a/gui/slick/interfaces/default/inc_top.tmpl +++ b/gui/slick/interfaces/default/inc_top.tmpl @@ -126,6 +126,8 @@ \$("#SubMenu a:contains('Notification')").addClass('btn').html('<span class="ui-icon ui-icon-note pull-left"></span> Notifications'); \$("#SubMenu a:contains('Update show in KODI')").addClass('btn').html('<span class="submenu-icon-kodi pull-left"></span> Update show in KODI'); \$("#SubMenu a[href$='/home/updateKODI/']").addClass('btn').html('<span class="submenu-icon-kodi pull-left"></span> Update KODI'); + \$("#SubMenu a:contains('Update show in Emby')").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Update show in Emby'); + \$("#SubMenu a[href$='/home/updateEMBY/']").addClass('btn').html('<span class="ui-icon ui-icon-refresh pull-left"></span> Update Emby'); \$("#SubMenu a:contains('Pause')").addClass('btn').html('<span class="ui-icon ui-icon-pause pull-left"></span> Pause'); \$("#SubMenu a:contains('Resume')").addClass('btn').html('<span class="ui-icon ui-icon-play pull-left"></span> Resume'); @@ -193,6 +195,9 @@ #if $sickbeard.USE_KODI and $sickbeard.KODI_HOST != "": <li><a href="$sbRoot/home/updateKODI/"><i class="menu-icon-kodi"></i> Update KODI</a></li> #end if + #if $sickbeard.USE_EMBY and $sickbeard.EMBY_HOST != "" and $sickbeard.EMBY_APIKEY != "": + <li><a href="$sbRoot/home/updateEMBY/"><i class="menu-icon-backlog-view"></i> Update Emby</a></li> + #end if #if $sickbeard.USE_TORRENTS and $sickbeard.TORRENT_METHOD != 'blackhole' \ and ($sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'https' \ or not $sickbeard.ENABLE_HTTPS and $sickbeard.TORRENT_HOST[:5] == 'http:'): diff --git a/gui/slick/js/configNotifications.js b/gui/slick/js/configNotifications.js index 801d73df3b243de22516a2cb4abd18ac8253a459..338a452281eff62ccd6acf81063d0030ae906fdf 100644 --- a/gui/slick/js/configNotifications.js +++ b/gui/slick/js/configNotifications.js @@ -95,6 +95,33 @@ $(document).ready(function(){ }); }); + $('#testEMBY').click(function () { + var emby_host = $('#emby_host').val(); + var emby_apikey = $('#emby_apikey').val(); + if (!emby_host || !emby_apikey) { + $('#testEMBY-result').html('Please fill out the necessary fields above.'); + if (!emby_host) { + $('#emby_host').addClass('warning'); + } else { + $('#emby_host').removeClass('warning'); + } + if (!emby_apikey) { + $('#emby_apikey').addClass('warning'); + } else { + $('#emby_apikey').removeClass('warning'); + } + return; + } + $('#emby_host,#emby_apikey').removeClass('warning'); + $(this).prop('disabled', true); + $('#testEMBY-result').html(loading); + $.get(sbRoot + '/home/testEMBY', {'host': emby_host, 'emby_apikey': emby_apikey}) + .done(function (data) { + $('#testEMBY-result').html(data); + $('#testEMBY').prop('disabled', false); + }); + }); + $('#testBoxcar').click(function() { var boxcar_username = $.trim($('#boxcar_username').val()); if (!boxcar_username) { diff --git a/runscripts/init.fedora b/runscripts/init.fedora index 4fd9ede44439d5d2e3330b19918fed929d005451..792f9d5c8ade1c338148126d31edb3d489c2f507 100755 --- a/runscripts/init.fedora +++ b/runscripts/init.fedora @@ -28,6 +28,7 @@ homedir=${SR_HOME-/opt/sickrage} datadir=${SR_DATA-/opt/sickrage} pidfile=${SR_PIDFILE-/var/run/sickrage/sickrage.pid} nice=${SR_NICE-} +python_bin=${PYTHON_BIN-/usr/bin/python} ## pidpath=`dirname ${pidfile}` @@ -47,7 +48,7 @@ fi start() { # Start daemon. echo -n $"Starting $prog: " - daemon --user=${username} --pidfile=${pidfile} ${nice} python ${homedir}/SickBeard.py ${options} + daemon --user=${username} --pidfile=${pidfile} ${nice} ${python_bin} ${homedir}/SickBeard.py ${options} RETVAL=$? echo [ $RETVAL -eq 0 ] && touch $lockfile @@ -56,7 +57,7 @@ start() { stop() { echo -n $"Shutting down $prog: " - killproc -p ${pidfile} python + killproc -p ${pidfile} ${python_bin} RETVAL=$? echo [ $RETVAL -eq 0 ] && rm -f $lockfile diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index 44ad391965872e250262de64dbc239198d6ee837..eaa058492a1194949976e679250dc02c7a3feecb 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -341,6 +341,10 @@ USE_PLEX_CLIENT = False PLEX_CLIENT_USERNAME = None PLEX_CLIENT_PASSWORD = None +USE_EMBY = False +EMBY_HOST = None +EMBY_APIKEY = None + USE_GROWL = False GROWL_NOTIFY_ONSNATCH = False GROWL_NOTIFY_ONDOWNLOAD = False @@ -559,6 +563,7 @@ def initialize(consoleLogging=True): USE_TRAKT, TRAKT_USERNAME, TRAKT_ACCESS_TOKEN, TRAKT_REFRESH_TOKEN, TRAKT_REMOVE_WATCHLIST, TRAKT_SYNC_WATCHLIST, TRAKT_REMOVE_SHOW_FROM_SICKRAGE, TRAKT_METHOD_ADD, TRAKT_START_PAUSED, traktCheckerScheduler, traktRollingScheduler, TRAKT_USE_RECOMMENDED, TRAKT_SYNC, TRAKT_SYNC_REMOVE, TRAKT_DEFAULT_INDEXER, TRAKT_REMOVE_SERIESLIST, TRAKT_TIMEOUT, TRAKT_BLACKLIST_NAME, TRAKT_USE_ROLLING_DOWNLOAD, TRAKT_ROLLING_NUM_EP, TRAKT_ROLLING_ADD_PAUSED, TRAKT_ROLLING_FREQUENCY, \ USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, USE_PLEX_CLIENT, PLEX_CLIENT_USERNAME, PLEX_CLIENT_PASSWORD, \ PLEX_SERVER_HOST, PLEX_SERVER_TOKEN, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, DEFAULT_BACKLOG_FREQUENCY, MIN_BACKLOG_FREQUENCY, BACKLOG_STARTUP, SKIP_REMOVED_FILES, \ + USE_EMBY, EMBY_HOST, EMBY_APIKEY, \ showUpdateScheduler, __INITIALIZED__, INDEXER_DEFAULT_LANGUAGE, EP_DEFAULT_DELETED_STATUS, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, UPDATE_SHOWS_ON_SNATCH, TRASH_REMOVE_SHOW, TRASH_ROTATE_LOGS, SORT_ARTICLE, showList, loadingShowList, \ NEWZNAB_DATA, NZBS, NZBS_UID, NZBS_HASH, INDEXER_DEFAULT, INDEXER_TIMEOUT, USENET_RETENTION, TORRENT_DIR, \ QUALITY_DEFAULT, FLATTEN_FOLDERS_DEFAULT, SUBTITLES_DEFAULT, STATUS_DEFAULT, STATUS_DEFAULT_AFTER, DAILYSEARCH_STARTUP, \ @@ -603,6 +608,7 @@ def initialize(consoleLogging=True): CheckSection(CFG, 'NZBget') CheckSection(CFG, 'KODI') CheckSection(CFG, 'PLEX') + CheckSection(CFG, 'Emby') CheckSection(CFG, 'Growl') CheckSection(CFG, 'Prowl') CheckSection(CFG, 'Twitter') @@ -949,7 +955,11 @@ def initialize(consoleLogging=True): USE_PLEX_CLIENT = bool(check_setting_int(CFG, 'Plex', 'use_plex_client', 0)) PLEX_CLIENT_USERNAME = check_setting_str(CFG, 'Plex', 'plex_client_username', '', censor_log=True) PLEX_CLIENT_PASSWORD = check_setting_str(CFG, 'Plex', 'plex_client_password', '', censor_log=True) - + + USE_EMBY = bool(check_setting_int(CFG, 'Emby', 'use_emby', 0)) + EMBY_HOST = check_setting_str(CFG, 'Emby', 'emby_host', '') + EMBY_APIKEY = check_setting_str(CFG, 'Emby', 'emby_apikey', '') + USE_GROWL = bool(check_setting_int(CFG, 'Growl', 'use_growl', 0)) GROWL_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Growl', 'growl_notify_onsnatch', 0)) GROWL_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Growl', 'growl_notify_ondownload', 0)) @@ -1916,6 +1926,11 @@ def save_config(): new_config['Plex']['plex_username'] = PLEX_USERNAME new_config['Plex']['plex_password'] = helpers.encrypt(PLEX_PASSWORD, ENCRYPTION_VERSION) + new_config['Emby'] = {} + new_config['Emby']['use_emby'] = int(USE_EMBY) + new_config['Emby']['emby_host'] = EMBY_HOST + new_config['Emby']['emby_apikey'] = EMBY_APIKEY + new_config['Growl'] = {} new_config['Growl']['use_growl'] = int(USE_GROWL) new_config['Growl']['growl_notify_onsnatch'] = int(GROWL_NOTIFY_ONSNATCH) diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py index 77ae5dae97fb658a86f19bfff246bf2d4f47dd1b..6df210bcc70d570fe64c219577eaeb1224fd65a1 100644 --- a/sickbeard/notifiers/__init__.py +++ b/sickbeard/notifiers/__init__.py @@ -20,6 +20,7 @@ import sickbeard import kodi import plex +import emby import nmj import nmjv2 import synoindex @@ -46,6 +47,7 @@ from sickbeard.common import * # home theater / nas kodi_notifier = kodi.KODINotifier() plex_notifier = plex.PLEXNotifier() +emby_notifier = emby.EMBYNotifier() nmj_notifier = nmj.NMJNotifier() nmjv2_notifier = nmjv2.NMJv2Notifier() synoindex_notifier = synoindex.synoIndexNotifier() diff --git a/sickbeard/notifiers/emby.py b/sickbeard/notifiers/emby.py new file mode 100644 index 0000000000000000000000000000000000000000..441d7fc2e1533c1de003f1e501c8bd671cda4464 --- /dev/null +++ b/sickbeard/notifiers/emby.py @@ -0,0 +1,121 @@ +# Author: Nic Wolfe <nic@wolfeden.ca> +# URL: http://code.google.com/p/sickbeard/ +# +# 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 <http://www.gnu.org/licenses/>. + +import urllib +import urllib2 + +import sickbeard + +from sickbeard import logger +from sickbeard import common +from sickbeard.exceptions import ex + + +try: + import json +except ImportError: + import simplejson as json + +class EMBYNotifier: + + def _notify_emby(self, message, host=None, emby_apikey=None): + """Handles notifying Emby host via HTTP API + + Returns: + Returns True for no issue or False if there was an error + + """ + + # fill in omitted parameters + if not host: + host = sickbeard.EMBY_HOST + if not emby_apikey: + username = sickbeard.EMBY_APIKEY + + url = 'http://%s/emby/Notifications/Admin' % (host) + values = {'Name': 'SickRage', 'Description': message, 'ImageUrl': 'https://raw.githubusercontent.com/SiCKRAGETV/SickRage/master/gui/slick/images/sickrage-shark-mascot.png'} + data = json.dumps(values) + try: + req = urllib2.Request(url, data) + req.add_header('X-MediaBrowser-Token', emby_apikey) + req.add_header('Content-Type', 'application/json') + + response = urllib2.urlopen(req) + result = response.read() + response.close() + + logger.log(u'EMBY: HTTP response: ' + result.replace('\n', ''), logger.DEBUG) + return True + + except (urllib2.URLError, IOError), e: + logger.log(u'EMBY: Warning: Couldn\'t contact Emby at ' + url + ' ' + ex(e), logger.WARNING) + return False + + +############################################################################## +# Public functions +############################################################################## + + def test_notify(self, host, emby_apikey): + return self._notify_emby('This is a test notification from SickRage', host, emby_apikey) + + def update_library(self, show=None): + """Handles updating the Emby Media Server host via HTTP API + + Returns: + Returns True for no issue or False if there was an error + + """ + + if sickbeard.USE_EMBY: + + if not sickbeard.EMBY_HOST: + logger.log(u'EMBY: No host specified, check your settings', logger.DEBUG) + return False + + if show: + if show.indexer == 1: + provider = 'tvdb' + elif show.indexer == 2: + provider = 'tvrage' + else: + logger.log(u'EMBY: Provider unknown', logger.WARNING) + return False + query = '?%sid=%s' % (provider, show.indexerid) + else: + query = '' + + url = 'http://%s/emby/Library/Series/Updated%s' % (sickbeard.EMBY_HOST, query) + values = {} + data = urllib.urlencode(values) + try: + req = urllib2.Request(url, data) + req.add_header('X-MediaBrowser-Token', sickbeard.EMBY_APIKEY) + + response = urllib2.urlopen(req) + result = response.read() + response.close() + + logger.log(u'EMBY: HTTP response: ' + result.replace('\n', ''), logger.DEBUG) + return True + + except (urllib2.URLError, IOError), e: + logger.log(u'EMBY: Warning: Couldn\'t contact Emby at ' + url + ' ' + ex(e), logger.WARNING) + return False + +notifier = EMBYNotifier diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index c66022ea08aacdade63c001d2ae49be50e8ab4cf..36e16e6254fca8996ff12c89a5e6785dad386492 100644 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -1091,6 +1091,9 @@ class PostProcessor(object): # do the library update for Plex notifiers.plex_notifier.update_library(ep_obj) + # do the library update for EMBY + notifiers.emby_notifier.update_library(ep_obj.show) + # do the library update for NMJ # nmj_notifier kicks off its library update when the notify_download is issued (inside notifiers) diff --git a/sickbeard/providers/freshontv.py b/sickbeard/providers/freshontv.py index c8a0610da4fd7f6b15c8b38849a7edabcaeaab37..36c4f1f009ef6357822aca759d99f57842483d4f 100644 --- a/sickbeard/providers/freshontv.py +++ b/sickbeard/providers/freshontv.py @@ -122,7 +122,7 @@ class FreshOnTVProvider(generic.TorrentProvider): } return True except: - logger.log(u'Unable to obtain cookie for FreshOnTV', logger.ERROR) + logger.log(u'Unable to obtain cookie for FreshOnTV', logger.WARNING) return False else: diff --git a/sickbeard/providers/torrentday.py b/sickbeard/providers/torrentday.py index 76e65166b0209df3b3afc06b3708f9fd1aa7b515..b3df3040c6d8460064d847e6db69e5a61b8f1ca2 100644 --- a/sickbeard/providers/torrentday.py +++ b/sickbeard/providers/torrentday.py @@ -122,7 +122,7 @@ class TorrentDayProvider(generic.TorrentProvider): except: pass - logger.log(u'Unable to obtain cookie for TorrentDay', logger.ERROR) + logger.log(u'Unable to obtain cookie for TorrentDay', logger.WARNING) return False diff --git a/sickbeard/scene_exceptions.py b/sickbeard/scene_exceptions.py index 88ca2a4030911e0a9a972afb7b3aa574ac18421c..a6e49242782e9e00996bd05bb16fca4e995662e3 100644 --- a/sickbeard/scene_exceptions.py +++ b/sickbeard/scene_exceptions.py @@ -294,7 +294,7 @@ def _xem_exceptions_fetcher(): for indexer in sickbeard.indexerApi().indexers: logger.log(u"Checking for XEM scene exception updates for " + sickbeard.indexerApi(indexer).name) - url = "http://thexem.de/map/allNames?origin=%s&seasonNumbers=1" % sickbeard.indexerApi(indexer).config[ + url = "http://thexem.de/map/allNames?origin=%s&seasonNumbers=1&language=us" % sickbeard.indexerApi(indexer).config[ 'xem_origin'] parsedJSON = helpers.getURL(url, session=xem_session, timeout = 90, json=True) diff --git a/sickbeard/search.py b/sickbeard/search.py index 4f4452ef4f7d9356fba844cad6d8b2ae1e6883fa..d98324c7f1f5dc31e9c394b5be45cbb9fdcdbb6c 100644 --- a/sickbeard/search.py +++ b/sickbeard/search.py @@ -453,8 +453,8 @@ def searchProviders(show, episodes, manualSearch=False, downCurQuality=False): searchCount = 0 search_mode = curProvider.search_mode - # Always search for episode when manually searching when in sponly and fallback false - if search_mode == 'sponly' and manualSearch == True and curProvider.search_fallback == False: + # Always search for episode when manually searching when in sponly + if search_mode == 'sponly' and manualSearch == True: search_mode = 'eponly' while(True): @@ -474,8 +474,6 @@ def searchProviders(show, episodes, manualSearch=False, downCurQuality=False): logger.log(u"Error while searching " + curProvider.name + ", skipping: " + ex(e), logger.ERROR) logger.log(traceback.format_exc(), logger.DEBUG) break - finally: - threading.currentThread().name = origThreadName didSearch = True @@ -492,10 +490,10 @@ def searchProviders(show, episodes, manualSearch=False, downCurQuality=False): break if search_mode == 'sponly': - logger.log(u"FALLBACK EPISODE SEARCH INITIATED ...", logger.DEBUG) + logger.log(u"Fallback episode search initiated", logger.DEBUG) search_mode = 'eponly' else: - logger.log(u"FALLBACK SEASON PACK SEARCH INITIATED ...", logger.DEBUG) + logger.log(u"Fallback season pack search initiate", logger.DEBUG) search_mode = 'sponly' # skip to next provider if we have no results to process diff --git a/sickbeard/tv.py b/sickbeard/tv.py index 32b1e6b3fa8e9d865c7851934521c3739eb30c59..69acce31874f3e6b5857917a41c4f27475682feb 100644 --- a/sickbeard/tv.py +++ b/sickbeard/tv.py @@ -557,7 +557,7 @@ class TVShow(object): except sickbeard.indexer_error: logger.log(u"" + sickbeard.indexerApi( self.indexer).name + " timed out, unable to update episodes from " + sickbeard.indexerApi( - self.indexer).name, logger.ERROR) + self.indexer).name, logger.WARNING) return None logger.log( diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 9ce1076fd44e54b1d2717f54d3e3d06621589212..72cca7266b54c9695f114f7fc3210d00837dbc39 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -718,6 +718,7 @@ class Home(WebRoot): {'title': 'Manual Post-Processing', 'path': 'home/postprocess/'}, {'title': 'Update KODI', 'path': 'home/updateKODI/', 'requires': self.haveKODI}, {'title': 'Update Plex', 'path': 'home/updatePLEX/', 'requires': self.havePLEX}, + {'title': 'Update Emby', 'path': 'home/updateEMBY/', 'requires': self.haveEMBY}, {'title': 'Manage Torrents', 'path': 'manage/manageTorrents/', 'requires': self.haveTORRENT}, ] @@ -793,6 +794,9 @@ class Home(WebRoot): def havePLEX(self): return sickbeard.USE_PLEX and sickbeard.PLEX_UPDATE_LIBRARY + def haveEMBY(self): + return sickbeard.USE_EMBY + def haveTORRENT(self): if sickbeard.USE_TORRENTS and sickbeard.TORRENT_METHOD != 'blackhole' \ and (sickbeard.ENABLE_HTTPS and sickbeard.TORRENT_HOST[:5] == 'https' @@ -983,6 +987,17 @@ class Home(WebRoot): return notifiers.libnotify.diagnose() + def testEMBY(self, host=None, emby_apikey=None): + # self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') + + host = config.clean_host(host) + result = notifiers.emby_notifier.test_notify(urllib.unquote_plus(host), emby_apikey) + if result: + return "Test notice sent successfully to " + urllib.unquote_plus(host) + else: + return "Test notice failed to " + urllib.unquote_plus(host) + + def testNMJ(self, host=None, database=None, mount=None): # self.set_header('Cache-Control', 'max-age=0,no-cache,no-store') @@ -1270,6 +1285,8 @@ class Home(WebRoot): {'title': 'Force Full Update', 'path': 'home/updateShow?show=%d&force=1' % showObj.indexerid}) t.submenu.append({'title': 'Update show in KODI', 'path': 'home/updateKODI?show=%d' % showObj.indexerid, 'requires': self.haveKODI}) + t.submenu.append({'title': 'Update show in Emby', + 'path': 'home/updateEMBY?show=%d' % showObj.indexerid, 'requires': self.haveEMBY}) t.submenu.append({'title': 'Preview Rename', 'path': 'home/testRename?show=%d' % showObj.indexerid}) if sickbeard.USE_SUBTITLES and not sickbeard.showQueueScheduler.action.isBeingSubtitled( showObj) and showObj.subtitles: @@ -1707,6 +1724,24 @@ class Home(WebRoot): ui.notifications.error("Unable to contact Plex Media Server host: " + sickbeard.PLEX_SERVER_HOST) return self.redirect('/home/') + def updateEMBY(self, show=None): + showName=None + showObj=None + + if show: + showObj = sickbeard.helpers.findCertainShow(sickbeard.showList, int(show)) + + if notifiers.emby_notifier.update_library(showObj): + ui.notifications.message( + "Library update command sent to Emby host: " + sickbeard.EMBY_HOST) + else: + ui.notifications.error("Unable to contact Emby host: " + sickbeard.EMBY_HOST) + + if showObj: + return self.redirect('/home/displayShow?show=' + str(showObj.indexerid)) + else: + return self.redirect('/home/') + def setStatus(self, show=None, eps=None, status=None, direct=False): if not all([show, eps, status]): @@ -4741,6 +4776,7 @@ class ConfigNotifications(Config): plex_notify_onsubtitledownload=None, plex_update_library=None, plex_server_host=None, plex_server_token=None, plex_host=None, plex_username=None, plex_password=None, use_plex_client=None, plex_client_username=None, plex_client_password=None, + use_emby=None, emby_host=None, emby_apikey=None, use_growl=None, growl_notify_onsnatch=None, growl_notify_ondownload=None, growl_notify_onsubtitledownload=None, growl_host=None, growl_password=None, use_freemobile=None, freemobile_notify_onsnatch=None, freemobile_notify_ondownload=None, @@ -4808,7 +4844,11 @@ class ConfigNotifications(Config): sickbeard.USE_PLEX_CLIENT = config.checkbox_to_value(use_plex) sickbeard.PLEX_CLIENT_USERNAME = plex_username sickbeard.PLEX_CLIENT_PASSWORD = plex_password - + + sickbeard.USE_EMBY = config.checkbox_to_value(use_emby) + sickbeard.EMBY_HOST = config.clean_host(emby_host) + sickbeard.EMBY_APIKEY = emby_apikey + sickbeard.USE_GROWL = config.checkbox_to_value(use_growl) sickbeard.GROWL_NOTIFY_ONSNATCH = config.checkbox_to_value(growl_notify_onsnatch) sickbeard.GROWL_NOTIFY_ONDOWNLOAD = config.checkbox_to_value(growl_notify_ondownload)