diff --git a/data/images/notifiers/betaseries.png b/data/images/notifiers/betaseries.png new file mode 100644 index 0000000000000000000000000000000000000000..2a803b6453cf5bfbda8b7f539333b2cb394fa7fa Binary files /dev/null and b/data/images/notifiers/betaseries.png differ diff --git a/data/interfaces/default/config_notifications.tmpl b/data/interfaces/default/config_notifications.tmpl index 75f00a7aa0aa73f29ffc1fcbed6b1bfe1369864f..ca0de96f0176ca0f913f0d5407e19917e26b6e4e 100755 --- a/data/interfaces/default/config_notifications.tmpl +++ b/data/interfaces/default/config_notifications.tmpl @@ -1078,7 +1078,7 @@ </div> <div class="field-pair"> <label class="nocheck clearfix"> - <span class="component-title">Pushbullet Devices</span> + <span class="component-title">Pushbullet Devices and Channels</span> <select name="pushbullet_device_list" id="pushbullet_device_list"></select> <input type="hidden" id="pushbullet_device" value="$sickbeard.PUSHBULLET_DEVICE"> <input type="button" class="btn" value="Update device list" id="getPushbulletDevices" /> @@ -1261,6 +1261,50 @@ </fieldset> </div><!-- /trakt component-group //--> + <div class="component-group clearfix"> + <div class="component-group-desc"> + <img class="notifier-icon" src="$sbRoot/images/notifiers/betaseries.png" alt="" title="BetaSeries" /> + <h3><a href="http://betaseries.com/" rel="noreferrer" onclick="window.open(this.href, '_blank'); return false;">{ betaseries.com }</a></h3> + <p>French equivalent of trakt.tv.</p> + </div> + <fieldset class="component-group-list"> + <div class="field-pair"> + <input type="checkbox" class="enabler" name="use_betaseries" id="use_betaseries" #if $sickbeard.USE_BETASERIES then "checked=\"checked\"" else ""# /> + <label class="clearfix" for="use_betaseries"> + <span class="component-title">Enable</span> + <span class="component-desc">Should Sick Beard send BetaSeries notifications?</span> + </label> + </div> + + <div id="content_use_betaseries"> + <div class="field-pair"> + <label class="nocheck clearfix"> + <span class="component-title">BetaSeries Username</span> + <input type="text" name="betaseries_username" id="betaseries_username" value="$sickbeard.BETASERIES_USERNAME" size="35" /> + </label> + <label class="nocheck clearfix"> + <span class="component-title"> </span> + <span class="component-desc">Username of your BetaSeries account.</span> + </label> + </div> + <div class="field-pair"> + <label class="nocheck clearfix"> + <span class="component-title">BetaSeries Password</span> + <input type="password" name="betaseries_password" id="betaseries_password" value="$sickbeard.BETASERIES_PASSWORD" size="35" /> + </label> + <label class="nocheck clearfix"> + <span class="component-title"> </span> + <span class="component-desc">Password of your BetaSeries account.</span> + </label> + </div> + <div class="testNotification" id="testBetaSeries-result">Click below to test.</div> + <input type="button" class="btn" value="Test BetaSeries" id="testBetaSeries" /> + <input type="submit" class="btn config_submitter" value="Save Changes" /> + </div><!-- /content_use_betaseries //--> + + </fieldset> + </div><!-- /betaseries component-group //--> + <div class="component-group clearfix"> <div class="component-group-desc"> <img class="notifier-icon" src="$sbRoot/images/notifiers/mail.png" alt="" title="Mail" /> diff --git a/data/js/configNotifications.js b/data/js/configNotifications.js index 2e207b088798d61a0dbc2ef8cf28878ca8abbe08..1e1f93c8f9141407bcfa79dfce9fa9558a7a4e24 100644 --- a/data/js/configNotifications.js +++ b/data/js/configNotifications.js @@ -246,18 +246,37 @@ $(document).ready(function () { $("#pushbullet_api").focus(); return false; } - + $("#pushbullet_device_list").html(''); var current_pushbullet_device = $("#pushbullet_device").val(); $.get(sbRoot + "/home/getPushbulletDevices", {'api': pushbullet_api}, function (data) { var devices = jQuery.parseJSON(data).devices; - $("#pushbullet_device_list").html(''); + for (var i = 0; i < devices.length; i++) { if(devices[i].active == true && devices[i].pushable == true){ - if(current_pushbullet_device == devices[i].iden) { - $("#pushbullet_device_list").append('<option value="'+devices[i].iden+'" selected>' + devices[i].nickname + '</option>') + if(current_pushbullet_device == 'device:'+devices[i].iden) { + $("#pushbullet_device_list").append('<option value="device:'+devices[i].iden+'" selected>' + devices[i].nickname + '</option>') } else { - $("#pushbullet_device_list").append('<option value="'+devices[i].iden+'">' + devices[i].nickname + '</option>') + $("#pushbullet_device_list").append('<option value="device:'+devices[i].iden+'">' + devices[i].nickname + '</option>') + } + } + } + if(msg) { + $('#testPushbullet-result').html(msg); + } + } + ); + + $.get(sbRoot + "/home/getPushbulletChannels", {'api': pushbullet_api}, + function (data) { + var channels = jQuery.parseJSON(data).channels; + + for (var i = 0; i < channels.length; i++) { + if(channels[i].active == true){ + if(current_pushbullet_device == 'channel:'+channels[i].tag) { + $("#pushbullet_device_list").append('<option value="channel:'+channels[i].tag+'" selected>' + channels[i].name + '</option>') + } else { + $("#pushbullet_device_list").append('<option value="channel:'+channels[i].tag+'">' + channels[i].name + '</option>') } } } @@ -279,6 +298,15 @@ $(document).ready(function () { // we have to call this function on dom ready to create the devices select get_pushbullet_devices(); + + $('#testBetaSeries').click(function () { + $('#testBetaSeries-result').html(loading); + var betaseries_username = $("#betaseries_username").val(); + var betaseries_password = $("#betaseries_password").val(); + + $.get(sbRoot + "/home/testBetaSeries", {'username': betaseries_username, 'password': betaseries_password}, + function (data) { $('#testBetaSeries-result').html(data); }); + }); $('#email_show').change(function () { var key = parseInt($('#email_show').val(), 10); diff --git a/sickbeard/__init__.py b/sickbeard/__init__.py index ca77bffdbfc6fb1dc8bcde24d0db9b3091bf6d6e..1fc8340e59c614e02f4cf716b36201c8e62efb88 100644 --- a/sickbeard/__init__.py +++ b/sickbeard/__init__.py @@ -378,6 +378,13 @@ TRAKT_USE_WATCHLIST = False TRAKT_METHOD_ADD = 0 TRAKT_START_PAUSED = False +USE_BETASERIES = False +BETASERIES_USERNAME = None +BETASERIES_PASSWORD = None +# This key is registered for Sick Beard. +# For your application, please get one at http://www.betaseries.com/api/ +BETASERIES_API = '94318dc0bb30' + USE_PYTIVO = False PYTIVO_NOTIFY_ONSNATCH = False PYTIVO_NOTIFY_ONDOWNLOAD = False @@ -475,6 +482,7 @@ def initialize(consoleLogging=True): USE_XBMC, XBMC_NOTIFY_ONSNATCH, XBMC_NOTIFY_ONDOWNLOAD, XBMC_NOTIFY_ONSUBTITLEDOWNLOAD, XBMC_UPDATE_FULL, XBMC_UPDATE_ONLYFIRST, \ XBMC_UPDATE_LIBRARY, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, \ USE_TRAKT, TRAKT_USERNAME, TRAKT_PASSWORD, TRAKT_API,TRAKT_REMOVE_WATCHLIST,TRAKT_USE_WATCHLIST,TRAKT_METHOD_ADD,TRAKT_START_PAUSED,traktWatchListCheckerSchedular, \ + USE_BETASERIES, BETASERIES_USERNAME, BETASERIES_PASSWORD, BETASERIES_API, \ USE_PLEX, PLEX_NOTIFY_ONSNATCH, PLEX_NOTIFY_ONDOWNLOAD, PLEX_NOTIFY_ONSUBTITLEDOWNLOAD, PLEX_UPDATE_LIBRARY, \ PLEX_SERVER_HOST, PLEX_HOST, PLEX_USERNAME, PLEX_PASSWORD, \ showUpdateScheduler, __INITIALIZED__, LAUNCH_BROWSER, UPDATE_SHOWS_ON_START, SORT_ARTICLE, FRENCH_COLUMN, showList, loadingShowList, \ @@ -978,7 +986,13 @@ 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)) - + + CheckSection(CFG, 'BetaSeries') + USE_BETASERIES = bool(check_setting_int(CFG, 'BetaSeries', 'use_betaseries', 0)) + BETASERIES_USERNAME = check_setting_str(CFG, 'BetaSeries', 'betaseries_username', '') + BETASERIES_PASSWORD = check_setting_str(CFG, 'BetaSeries', 'betaseries_password', '') + BETASERIES_API = check_setting_str(CFG, 'BetaSeries', 'betaseries_api', '') + CheckSection(CFG, 'pyTivo') USE_PYTIVO = bool(check_setting_int(CFG, 'pyTivo', 'use_pytivo', 0)) PYTIVO_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'pyTivo', 'pytivo_notify_onsnatch', 0)) @@ -1734,7 +1748,13 @@ 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['BetaSeries'] = {} + new_config['BetaSeries']['use_betaseries'] = int(USE_BETASERIES) + new_config['BetaSeries']['betaseries_username'] = BETASERIES_USERNAME + new_config['BetaSeries']['betaseries_password'] = BETASERIES_PASSWORD + new_config['BetaSeries']['betaseries_api'] = BETASERIES_API + new_config['pyTivo'] = {} new_config['pyTivo']['use_pytivo'] = int(USE_PYTIVO) new_config['pyTivo']['pytivo_notify_onsnatch'] = int(PYTIVO_NOTIFY_ONSNATCH) diff --git a/sickbeard/common.py b/sickbeard/common.py index c4c8c2894bcd8af03937e4bed971a37e7c4fb263..45c789275c7c8d0b5e954cb76c5c72414607736d 100644 --- a/sickbeard/common.py +++ b/sickbeard/common.py @@ -45,7 +45,7 @@ NOTIFY_SUBTITLE_DOWNLOAD = 3 notifyStrings = {} notifyStrings[NOTIFY_SNATCH] = "Download en cours" -notifyStrings[NOTIFY_DOWNLOAD] = "Download finis" +notifyStrings[NOTIFY_DOWNLOAD] = "Download fini" notifyStrings[NOTIFY_SUBTITLE_DOWNLOAD] = "Sous-titre" ### Episode statuses diff --git a/sickbeard/name_parser/regexes.py b/sickbeard/name_parser/regexes.py index 813eff9cc390c10b303ff6d99cd379f18034af68..d2c79ad1ed6b8dae1cb762479b29a62e2ea1f985 100644 --- a/sickbeard/name_parser/regexes.py +++ b/sickbeard/name_parser/regexes.py @@ -73,7 +73,7 @@ ep_regexes = [ ('standard_cpas_bien', # [www.Cpasbien.me] Dexter.S07E04.FRENCH.LD.HDTV.XviD-MiNDe ''' - \[[a-zA-Z0-9\.]{2,20}\][. _-]+ + \[[a-zA-Z0-9\.\s]{2,20}\][. _-]+ (?P<series_name>.+?)[. _-]+ # Show_Name and separator s(?P<season_num>\d+)[. _-]* # S01 and optional separator e(?P<ep_num>\d+) # E02 and separator diff --git a/sickbeard/notifiers/__init__.py b/sickbeard/notifiers/__init__.py index 8f9759f870fe6aaedf2080fbdb0409a99dd03da5..747918baad2bca563e3e1e0dc629dd88ed418772 100755 --- a/sickbeard/notifiers/__init__.py +++ b/sickbeard/notifiers/__init__.py @@ -39,6 +39,7 @@ import pushbullet import tweet import trakt +import betaseries from sickbeard.common import * @@ -63,6 +64,7 @@ pushbullet_notifier = pushbullet.PushbulletNotifier() # online twitter_notifier = tweet.TwitterNotifier() trakt_notifier = trakt.TraktNotifier() +betaseries_notifier = betaseries.BetaSeriesNotifier() mail_notifier = mail.MailNotifier() notifiers = [ @@ -84,6 +86,7 @@ notifiers = [ pushbullet_notifier, twitter_notifier, trakt_notifier, + betaseries_notifier, mail_notifier, ] diff --git a/sickbeard/notifiers/betaseries.py b/sickbeard/notifiers/betaseries.py new file mode 100644 index 0000000000000000000000000000000000000000..ec5e36562a1f2d8dee7df7e4993ff970882478f7 --- /dev/null +++ b/sickbeard/notifiers/betaseries.py @@ -0,0 +1,162 @@ +# Author: Gregoire Astruc <gregoire.astruc@gmail.com> +# URL: http://code.google.com/p/sickbeard/ +# +# This file is part of Sick Beard. +# +# Sick Beard 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. +# +# Sick Beard 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 Sick Beard. If not, see <http://www.gnu.org/licenses/>. +import urllib2, urllib + +from hashlib import md5 + +try: + import json +except ImportError: + from lib import simplejson as json + +import sickbeard + +from sickbeard import logger + +class BetaSeriesNotifier: + """ + A "notifier" for betaseries.com which keeps track of what has and hasn't been added to your library. + """ + + def notify_snatch(self, ep_name): + pass + + def notify_download(self, ep_name): + pass + + def update_library(self, ep_obj): + """ + Sends a request to betaseries indicating that the given episode is part of our library. + + ep_obj: The TVEpisode object to add to betaseries + """ + if not sickbeard.USE_BETASERIES: + return + + # TODO: Figure out if the show is present, and eventually add it. + + self._notifyBetaSeries('episodes/downloaded', {'thetvdb_id': ep_obj.tvdbid}) + + def test_notify(self, username, password): + """ + 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 + """ + return self._notifyBetaSeries("timeline/home", login=username, password=password) + + def _login(self): + return sickbeard.BETASERIES_USERNAME + + def _password(self): + return sickbeard.BETASERIES_PASSWORD + + def _api(self): + return sickbeard.BETASERIES_API + + def _use_me(self): + return sickbeard.USE_BETASERIES + + def _notifyBetaSeries(self, method, data = {}, login = None, password = None): + """ + A generic method for communicating with betaseries. Uses the method and data provided along + with the auth info to send the command. + + method: The URL to use at trakt, relative, no leading slash. + api: The API string to provide to trakt + login: The username to use when logging in + password: The unencrypted password to use when logging in + + Returns: A boolean representing success + """ + logger.log("betaseries_notifier: Call method {0}".format(method), logger.DEBUG) + + # if the login isn't given then use the config login + if not login: + login = self._login() + + # if the password isn't given then use the config password + if not password: + password = self._password() + + password = md5(password).hexdigest() + token = None + + try: + stream = urllib2.urlopen(self._requestBetaSeries('members/auth', {"login": login, "password": password})) + auth_resp = stream.read() + auth_resp = json.loads(auth_resp) + + token = auth_resp["token"] + except urllib2.URLError, e: + error = ''.join(e.readlines()) + logger.log("betaseries_notifier: Failed authenticating: {0} ({1})".format(e, error), logger.ERROR) + return False + except IOError, e: + logger.log("betaseries_notifier: Failed authenticating: {0}".format(e), logger.ERROR) + return False + + + # request the URL from betaseries and parse the result as json + try: + stream = urllib2.urlopen(self._requestBetaSeries(method, data, token)) + resp = stream.read() + + resp = json.loads(resp) + + if resp["errors"]: + raise Exception(resp["errors"]) + except urllib2.URLError, e: + error = ''.join(e.readlines()) + logger.log("betaseries_notifier: Failed method call on {0}: {1} ({2})".format(method, e, error), logger.ERROR) + + except IOError: + logger.log("betaseries_notifier: Failed calling method {0}".format(method), logger.ERROR) + return False + + if not resp["errors"]: + logger.log("betaseries_notifier: Succeeded calling {0}. Result: {1}".format(method, resp), logger.DEBUG) + return True + + #TODO: Destroy token. + + logger.log("betaseries_notifier: Failed calling method", logger.ERROR) + return False + + def _requestBetaSeries(self, method, data, token = None, version = "2.2"): + logger.log("betaseries_notifier: building request for {0} with payload {1}".format(method, data), logger.DEBUG) + request = urllib2.Request( + url="https://api.betaseries.com/{0}".format(method), + headers={ + "User-Agent": "Sickbeard/1.0", + "X-BetaSeries-Version": "2.2", + "X-BetaSeries-Key": self._api()}) + if data: + request.add_data(urllib.urlencode(data)) + + if token: + request.add_header("X-BetaSeries-Token", token) + + return request + +notifier = BetaSeriesNotifier diff --git a/sickbeard/notifiers/pushbullet.py b/sickbeard/notifiers/pushbullet.py index 64801afd861fa16f2a6774a3325cadf1fb99f4e3..a6c60a1f1daf859b60d856863b84d7876bd9650e 100644 --- a/sickbeard/notifiers/pushbullet.py +++ b/sickbeard/notifiers/pushbullet.py @@ -34,6 +34,9 @@ class PushbulletNotifier: def get_devices(self, pushbullet_api): return self._sendPushbullet(pushbullet_api, method="GET", force=True) + def get_channels(self, pushbullet_api): + return self._sendPushbullet(pushbullet_api, method="GET", force=True, event="getChannels") + def notify_snatch(self, ep_name): if sickbeard.PUSHBULLET_NOTIFY_ONSNATCH: self._sendPushbullet(pushbullet_api=None, event=common.notifyStrings[common.NOTIFY_SNATCH], message=ep_name, notificationType="note", method="POST") @@ -55,12 +58,15 @@ class PushbulletNotifier: pushbullet_api = sickbeard.PUSHBULLET_API if pushbullet_device == None: pushbullet_device = sickbeard.PUSHBULLET_DEVICE - + if method == 'POST': uri = '/v2/pushes' - else: + else: uri = '/v2/devices' + if event == 'getChannels': + uri = '/v2/channels' + logger.log(u"Pushbullet event: " + str(event), logger.DEBUG) logger.log(u"Pushbullet message: " + str(message), logger.DEBUG) logger.log(u"Pushbullet api: " + str(pushbullet_api), logger.DEBUG) @@ -80,11 +86,20 @@ class PushbulletNotifier: else: testMessage = False try: - data = { - 'title': event.encode('utf-8'), - 'body': message.encode('utf-8'), - 'device_iden': pushbullet_device, - 'type': notificationType} + device = pushbullet_device.split(':'); + if device[0] == 'device': + data = { + 'title': event.encode('utf-8'), + 'body': message.encode('utf-8'), + 'device_iden': device[1], + 'type': notificationType} + else: + data = { + 'title': event.encode('utf-8'), + 'body': message.encode('utf-8'), + 'channel_tag': device[1], + 'type': notificationType} + data = json.dumps(data) http_handler.request(method, uri, body=data, headers={'Content-Type': 'application/json', 'Authorization': 'Bearer %s' % pushbullet_api}) diff --git a/sickbeard/postProcessor.py b/sickbeard/postProcessor.py index a1dccfa93951aee19da1c459724ed00c174fc9ee..7dd5d79e76bb70e6ca168a679fc209ba78646e01 100755 --- a/sickbeard/postProcessor.py +++ b/sickbeard/postProcessor.py @@ -1050,6 +1050,9 @@ class PostProcessor(object): # do the library update for Trakt notifiers.trakt_notifier.update_library(ep_obj) + # do the library update for BetaSeries + notifiers.betaseries_notifier.update_library(ep_obj) + self._run_extra_scripts(ep_obj) return True diff --git a/sickbeard/providers/libertalia.py b/sickbeard/providers/libertalia.py index 173c9eb6f68c7af806e9196c33f8f7ba2a670327..3f6f14b513f2ac75de0de466430b679c8080fcf2 100644 --- a/sickbeard/providers/libertalia.py +++ b/sickbeard/providers/libertalia.py @@ -150,7 +150,17 @@ class LIBERTALIAProvider(generic.TorrentProvider): #bypass first row because title only columns = row.find('td', {"class" : "torrent_name"} ) logger.log(u"LIBERTALIA found rows ! " , logger.DEBUG) - link = columns.find("a", href=re.compile("torrents")) + isvfclass = row.find('td', {"class" : "sprite-vf"} ) + isvostfrclass = row.find('td', {"class" : "sprite-vostfr"} ) + link = columns.find("a", href=re.compile("torrents")) + if link: + if isvostfrclass and str(show.audio_lang)=='fr': + logger.log(u"LIBERTALIA found VOSTFR et demande *"+str(show.audio_lang)+"* je skip ! " + link.text , logger.DEBUG) + link = columns.find("a", href=re.compile("nepastrouver")) + if link: + if isvfclass and str(show.audio_lang)!='fr' : + logger.log(u"LIBERTALIA found VF et demande *"+str(show.audio_lang)+"* je skip ! " + link.text , logger.DEBUG) + link = columns.find("a", href=re.compile("nepastrouver")) if link: title = link.text recherched=searchUrl.split("&[PARAMSTR]=")[1] @@ -170,7 +180,9 @@ class LIBERTALIAProvider(generic.TorrentProvider): results.append( LIBERTALIASearchResult( self.opener, title, downloadURL, quality, 'fr' ) ) else: results.append( LIBERTALIASearchResult( self.opener, title, downloadURL, quality ) ) - + else: + logger.log(u"Pas de table trouvée ! je délogue", logger.DEBUG) + self.login_done = False return results def getResult(self, episodes): diff --git a/sickbeard/providers/t411.py b/sickbeard/providers/t411.py index b9e8494f5febc344be2303ad3a03851aa5f492d1..1f5e6f4d71ffe113a4df7a2889063a93c6bf0c69 100644 --- a/sickbeard/providers/t411.py +++ b/sickbeard/providers/t411.py @@ -39,7 +39,7 @@ class T411Provider(generic.TorrentProvider): self.opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self.cj)) self.opener.addheaders = [('Content-Type', 'application/x-www-form-urlencoded'),('User-Agent', 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.7) Gecko/20091221 Firefox/3.5.7 (.NET CLR 3.5.30729)')] - self.url = "http://www.t411.me" + self.url = "http://www.t411.io" self.login_done = False @@ -133,7 +133,7 @@ class T411Provider(generic.TorrentProvider): link = row.find("a", title=True) title = link['title'] id = row.find_all('td')[2].find_all('a')[0]['href'][1:].replace('torrents/nfo/?id=','') - downloadURL = ('http://www.t411.me/torrents/download/?id=%s' % id) + downloadURL = ('http://www.t411.io/torrents/download/?id=%s' % id) quality = Quality.nameQuality( title ) if quality==Quality.UNKNOWN and title: diff --git a/sickbeard/webserve.py b/sickbeard/webserve.py index 2a6a9e2982163a3cb70ee145fe3d6b4fd9ced908..c11bf938b14614a77ff0293e6be3bc0d034596a4 100644 --- a/sickbeard/webserve.py +++ b/sickbeard/webserve.py @@ -1535,12 +1535,13 @@ class ConfigNotifications: 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,trakt_remove_watchlist=None,trakt_use_watchlist=None,trakt_start_paused=None,trakt_method_add=None, + use_betaseries=None, betaseries_username=None, betaseries_password=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, pytivo_notify_onsubtitledownload=None, pytivo_update_library=None, pytivo_host=None, pytivo_share_name=None, pytivo_tivo_name=None, use_nma=None, nma_notify_onsnatch=None, nma_notify_ondownload=None, nma_notify_onsubtitledownload=None, nma_api=None, nma_priority=0, use_pushalot=None, pushalot_notify_onsnatch=None, pushalot_notify_ondownload=None, pushalot_notify_onsubtitledownload=None, pushalot_authorizationtoken=None, - use_pushbullet=None, pushbullet_notify_onsnatch=None, pushbullet_notify_ondownload=None, pushbullet_notify_onsubtitledownload=None, pushbullet_api=None, pushbullet_device=None, pushbullet_device_list=None, + use_pushbullet=None, pushbullet_notify_onsnatch=None, pushbullet_notify_ondownload=None, pushbullet_notify_onsubtitledownload=None, pushbullet_api=None, pushbullet_device=None, pushbullet_device_list=None, pushbullet_channel_list=None, use_mail=None, mail_username=None, mail_password=None, mail_server=None, mail_ssl=None, mail_from=None, mail_to=None, mail_notify_onsnatch=None ): @@ -1761,6 +1762,11 @@ class ConfigNotifications: else: trakt_start_paused = 0 + if use_betaseries == "on": + use_betaseries = 1 + else: + use_betaseries = 0 + if use_pytivo == "on": use_pytivo = 1 else: @@ -1971,6 +1977,10 @@ class ConfigNotifications: sickbeard.TRAKT_METHOD_ADD = trakt_method_add sickbeard.TRAKT_START_PAUSED = trakt_start_paused + sickbeard.USE_BETASERIES = use_betaseries + sickbeard.BETASERIES_USERNAME = betaseries_username + sickbeard.BETASERIES_PASSWORD = betaseries_password + sickbeard.USE_PYTIVO = use_pytivo sickbeard.PYTIVO_NOTIFY_ONSNATCH = pytivo_notify_onsnatch == "off" sickbeard.PYTIVO_NOTIFY_ONDOWNLOAD = pytivo_notify_ondownload == "off" @@ -2008,6 +2018,7 @@ class ConfigNotifications: sickbeard.PUSHBULLET_NOTIFY_ONSUBTITLEDOWNLOAD = pushbullet_notify_onsubtitledownload sickbeard.PUSHBULLET_API = pushbullet_api sickbeard.PUSHBULLET_DEVICE = pushbullet_device_list + sickbeard.PUSHBULLET_CHANNEL = pushbullet_channel_list sickbeard.save_config() @@ -2855,6 +2866,16 @@ class Home: else: return "Test notice failed to Trakt" + @cherrypy.expose + def testBetaSeries(self, username=None, password=None): + cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store" + + result = notifiers.betaseries_notifier.test_notify(username, password) + if result: + return "Test notice sent successfully to BetaSeries" + else: + return "Test notice failed to BetaSeries" + @cherrypy.expose def testMail(self, mail_from=None, mail_to=None, mail_server=None, mail_ssl=None, mail_user=None, mail_password=None): cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store" @@ -2908,6 +2929,18 @@ class Home: else: return "Error sending Pushbullet notification" + @cherrypy.expose + + #get channels + def getPushbulletChannels(self, api=None): + cherrypy.response.headers['Cache-Control'] = "max-age=0,no-cache,no-store" + + result = notifiers.pushbullet_notifier.get_channels(api) + if result: + return result + else: + return "Error sending Pushbullet notification" + @cherrypy.expose def shutdown(self, pid=None): @@ -3935,7 +3968,7 @@ class WebInterface: myDB = db.DBConnection() # Limit dates - past_date = (datetime.date.today() + datetime.timedelta(weeks=-52)).toordinal() + past_date = (datetime.date.today() + datetime.timedelta(weeks=-2)).toordinal() future_date = (datetime.date.today() + datetime.timedelta(weeks=52)).toordinal() # Get all the shows that are not paused and are currently on air (from kjoconnor Fork) @@ -3943,16 +3976,17 @@ class WebInterface: for show in calendar_shows: # Get all episodes of this show airing between today and next month episode_list = myDB.select("SELECT tvdbid, name, season, episode, description, airdate FROM tv_episodes WHERE airdate >= ? AND airdate < ? AND showid = ?", (past_date, future_date, int(show["tvdb_id"]))) + + # Get local timezone and load network timezones + local_zone = tz.tzlocal() + try: + network_zone = network_timezones.get_network_timezone(show['network'], network_timezones.load_network_dict(), local_zone) + except: + # Dummy network_zone for exceptions + network_zone = None for episode in episode_list: - # Get local timezone and load network timezones - local_zone = tz.tzlocal() - try: - network_zone = network_timezones.get_network_timezone(show['network'], network_timezones.load_network_dict(), local_zone) - except: - # Dummy network_zone for exceptions - network_zone = None # Get the air date and time air_date = datetime.datetime.fromordinal(int(episode['airdate']))