Skip to content

Commit 5e152cf

Browse files
thezoggyPatrick Vos
authored and
Patrick Vos
committed
Update notifiers pass 3
* Instead of calling each notifier update_library routine individually, we now just call all of them similar to the notifications * Safeguard notifiers from affecting the post-processing routine, catch and log exceptions. * Cleaned up notifier ui page wording so they follow similar pattern. * Converted updateXBMC to use show id rather than show name (works the same way as refreshShow/updateShow/etc) * Better exception handling for pyTivo and NMJ * Cleaned up logging entries, trying to standardize on what level we report and verbiage (not using contractions, prune out duplicate/excessive entries) * Added notification support for Synology (notifies Synology DSM) with migration of old setting * Dropped getURL helper reference since importing helper is more trouble than its worth, will just rewrite each notifier using Requests when we move to python 2.6+ * Add copyright NMA_Notifier
1 parent d43f491 commit 5e152cf

21 files changed

+318
-200
lines changed

data/interfaces/default/config_notifications.tmpl

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717

1818

1919
<br />
20-
<h2>Home Theater</h2>
20+
<h2>Home Theater / NAS</h2>
2121
<br />
2222

2323

@@ -366,17 +366,18 @@
366366

367367
<div class="component-group clearfix">
368368
<div class="component-group-desc">
369-
<img class="notifier-icon" src="$sbRoot/images/notifiers/synoindex.png" alt="" title="Synology Indexer" />
370-
<h3><a href="http://synology.com/" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">Synology Indexer</a></h3>
369+
<img class="notifier-icon" src="$sbRoot/images/notifiers/synoindex.png" alt="" title="Synology" />
370+
<h3><a href="http://synology.com/" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">Synology</a></h3>
371+
<p>The Synology DiskStation NAS.</p>
371372
<p>Synology Indexer is the daemon running on the Synology NAS to build its media database.</p>
373+
<p>Synology Notifier is the notification system of Synology DSM.</p>
372374
</div>
373-
374375
<fieldset class="component-group-list">
375376
<div class="field-pair">
376377
<input type="checkbox" class="enabler" name="use_synoindex" id="use_synoindex" #if $sickbeard.USE_SYNOINDEX then "checked=\"checked\"" else ""# />
377378
<label class="clearfix" for="use_synoindex">
378379
<span class="component-title">Enable</span>
379-
<span class="component-desc">Should Sick Beard send notifications to the synoindex daemon?<br /><br />
380+
<span class="component-desc">Should Sick Beard send Synology commands?<br /><br />
380381
</span>
381382
</label>
382383
<label class="nocheck clearfix" for="use_synoindex">
@@ -386,8 +387,31 @@
386387
</div>
387388

388389
<div id="content_use_synoindex">
390+
<div class="field-pair">
391+
<input type="checkbox" name="synoindex_notify_onsnatch" id="synoindex_notify_onsnatch" #if $sickbeard.SYNOINDEX_NOTIFY_ONSNATCH then "checked=\"checked\"" else ""# />
392+
<label class="clearfix" for="synoindex_notify_onsnatch">
393+
<span class="component-title">Notify on Snatch</span>
394+
<span class="component-desc">Send notification when we start a download?</span>
395+
</label>
396+
</div>
397+
<div class="field-pair">
398+
<input type="checkbox" name="synoindex_notify_ondownload" id="synoindex_notify_ondownload" #if $sickbeard.SYNOINDEX_NOTIFY_ONDOWNLOAD then "checked=\"checked\"" else ""# />
399+
<label class="clearfix" for="synoindex_notify_ondownload">
400+
<span class="component-title">Notify on Download</span>
401+
<span class="component-desc">Send notification when we finish a download?</span>
402+
</label>
403+
</div>
404+
<div class="field-pair">
405+
<input type="checkbox" name="synoindex_update_library" id="synoindex_update_library" #if $sickbeard.SYNOINDEX_UPDATE_LIBRARY then "checked=\"checked\"" else ""# />
406+
<label class="clearfix" for="synoindex_update_library">
407+
<span class="component-title">Update Library</span>
408+
<span class="component-desc">Update Synology library when we finish a download?</span>
409+
</label>
410+
</div>
411+
<div class="testNotification" id="testSynoNotify-result">Click below to test.</div>
412+
<input type="button" class="btn" value="Test Notice (SynoDSMnotify)" id="testSynoNotify" />
389413
<input type="submit" class="btn config_submitter" value="Save Changes" />
390-
</div><!-- /content_use_pytivo //-->
414+
</div><!-- /content_use_synoindex //-->
391415

392416
</fieldset>
393417
</div><!-- /synoindex component-group //-->
@@ -397,14 +421,14 @@
397421
<div class="component-group-desc">
398422
<img class="notifier-icon" src="$sbRoot/images/notifiers/pytivo.png" alt="" title="pyTivo" />
399423
<h3><a href="http://pytivo.sourceforge.net/wiki/index.php/PyTivo" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">pyTivo</a></h3>
400-
<p>pyTivo is both an HMO and GoBack server. This notifier will load the completed downloads to your Tivo.</p>
424+
<p>pyTivo is both an HMO and GoBack server. This notifier will load the completed downloads to your Tivo.</p>
401425
</div>
402426
<fieldset class="component-group-list">
403427
<div class="field-pair">
404428
<input type="checkbox" class="enabler" name="use_pytivo" id="use_pytivo" #if $sickbeard.USE_PYTIVO then "checked=\"checked\"" else ""# />
405429
<label class="clearfix" for="use_pytivo">
406430
<span class="component-title">Enable</span>
407-
<span class="component-desc">Should Sick Beard send notifications to pyTivo?<br /><br /></span>
431+
<span class="component-desc">Should Sick Beard update commands to pyTivo?<br /><br /></span>
408432
</label>
409433
<label class="nocheck clearfix" for="use_pytivo">
410434
<span class="component-title">&nbsp;</span>
@@ -637,7 +661,7 @@
637661
<input type="checkbox" class="enabler" name="use_pushover" id="use_pushover" #if $sickbeard.USE_PUSHOVER then "checked=\"checked\"" else ""# />
638662
<label class="clearfix" for="use_pushover">
639663
<span class="component-title">Enable</span>
640-
<span class="component-desc">Should Sick Beard send notifications through Pushover?</span>
664+
<span class="component-desc">Should Sick Beard send Pushover notifications?</span>
641665
</label>
642666
</div>
643667

@@ -678,14 +702,14 @@
678702
<div class="component-group-desc">
679703
<img class="notifier-icon" src="$sbRoot/images/notifiers/boxcar.png" alt="" title="Boxcar" />
680704
<h3><a href="http://boxcar.io/" rel="noreferrer" onclick="window.open('${sickbeard.ANON_REDIRECT}' + this.href, '_blank'); return false;">Boxcar</a></h3>
681-
<p>Read your messages where and when you want them! A subscription will be sent if needed.</p>
705+
<p>Universal push notification for iOS. Read your messages where and when you want them! A subscription will be sent if needed.</p>
682706
</div>
683707
<fieldset class="component-group-list">
684708
<div class="field-pair">
685709
<input type="checkbox" class="enabler" name="use_boxcar" id="use_boxcar" #if $sickbeard.USE_BOXCAR then "checked=\"checked\"" else ""# />
686710
<label class="clearfix" for="use_boxcar">
687711
<span class="component-title">Enable</span>
688-
<span class="component-desc">Should Sick Beard send notifications through Boxcar?</span>
712+
<span class="component-desc">Should Sick Beard send Boxcar notifications?</span>
689713
</label>
690714
</div>
691715

@@ -792,7 +816,7 @@
792816
</div><br />
793817

794818
<br />
795-
<h2>Online</h2>
819+
<h2>Social</h2>
796820
<br />
797821

798822

data/js/configNotifications.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,4 +257,15 @@ $(document).ready(function () {
257257
$("#testNMA").attr("disabled", false);
258258
});
259259
});
260+
261+
$("#testSynoNotify").click(function () {
262+
$(this).attr("disabled", true);
263+
$("#testSynoNotify-result").html(loading);
264+
$.get(sbRoot + "/home/testSynoNotify")
265+
.done(function (data) {
266+
$("#testSynoNotify-result").html(data);
267+
$("#testSynoNotify").attr("disabled", false);
268+
});
269+
});
270+
260271
});

sickbeard/__init__.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
CONFIG_FILE = None
5959

6060
# this is the version of the config we EXPECT to find
61-
CONFIG_VERSION = 5
61+
CONFIG_VERSION = 6
6262

6363
PROG_DIR = '.'
6464
MY_FULLNAME = None
@@ -267,6 +267,9 @@
267267
NMJ_MOUNT = None
268268

269269
USE_SYNOINDEX = False
270+
SYNOINDEX_NOTIFY_ONSNATCH = False
271+
SYNOINDEX_NOTIFY_ONDOWNLOAD = False
272+
SYNOINDEX_UPDATE_LIBRARY = False
270273

271274
USE_NMJv2 = False
272275
NMJv2_HOST = None
@@ -341,7 +344,8 @@ def initialize(consoleLogging=True):
341344
EXTRA_SCRIPTS, USE_TWITTER, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \
342345
USE_BOXCAR, BOXCAR_USERNAME, BOXCAR_PASSWORD, BOXCAR_NOTIFY_ONDOWNLOAD, BOXCAR_NOTIFY_ONSNATCH, \
343346
USE_PUSHOVER, PUSHOVER_USERKEY, PUSHOVER_NOTIFY_ONDOWNLOAD, PUSHOVER_NOTIFY_ONSNATCH, \
344-
USE_LIBNOTIFY, LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, USE_NMJ, NMJ_HOST, NMJ_DATABASE, NMJ_MOUNT, USE_NMJv2, NMJv2_HOST, NMJv2_DATABASE, NMJv2_DBLOC, USE_SYNOINDEX, \
347+
USE_LIBNOTIFY, LIBNOTIFY_NOTIFY_ONSNATCH, LIBNOTIFY_NOTIFY_ONDOWNLOAD, USE_NMJ, NMJ_HOST, NMJ_DATABASE, NMJ_MOUNT, USE_NMJv2, NMJv2_HOST, NMJv2_DATABASE, NMJv2_DBLOC, \
348+
USE_SYNOINDEX, SYNOINDEX_NOTIFY_ONSNATCH, SYNOINDEX_NOTIFY_ONDOWNLOAD, SYNOINDEX_UPDATE_LIBRARY, \
345349
USE_LISTVIEW, METADATA_XBMC, METADATA_XBMC_12PLUS, METADATA_MEDIABROWSER, METADATA_MEDE8ER, METADATA_PS3, metadata_provider_dict, \
346350
GIT_PATH, MOVE_ASSOCIATED_FILES, \
347351
COMING_EPS_LAYOUT, COMING_EPS_SORT, COMING_EPS_DISPLAY_PAUSED, METADATA_WDTV, METADATA_TIVO, IGNORE_WORDS, CREATE_MISSING_SHOW_DIRS, \
@@ -602,6 +606,9 @@ def initialize(consoleLogging=True):
602606

603607
CheckSection(CFG, 'Synology')
604608
USE_SYNOINDEX = bool(check_setting_int(CFG, 'Synology', 'use_synoindex', 0))
609+
SYNOINDEX_NOTIFY_ONSNATCH = bool(check_setting_int(CFG, 'Synology', 'synoindex_notify_onsnatch', 0))
610+
SYNOINDEX_NOTIFY_ONDOWNLOAD = bool(check_setting_int(CFG, 'Synology', 'synoindex_notify_ondownload', 0))
611+
SYNOINDEX_UPDATE_LIBRARY = bool(check_setting_int(CFG, 'Synology', 'synoindex_update_library', 0))
605612

606613
CheckSection(CFG, 'Trakt')
607614
USE_TRAKT = bool(check_setting_int(CFG, 'Trakt', 'use_trakt', 0))
@@ -1114,6 +1121,9 @@ def save_config():
11141121

11151122
new_config['Synology'] = {}
11161123
new_config['Synology']['use_synoindex'] = int(USE_SYNOINDEX)
1124+
new_config['Synology']['synoindex_notify_onsnatch'] = int(SYNOINDEX_NOTIFY_ONSNATCH)
1125+
new_config['Synology']['synoindex_notify_ondownload'] = int(SYNOINDEX_NOTIFY_ONDOWNLOAD)
1126+
new_config['Synology']['synoindex_update_library'] = int(SYNOINDEX_UPDATE_LIBRARY)
11171127

11181128
new_config['NMJv2'] = {}
11191129
new_config['NMJv2']['use_nmjv2'] = int(USE_NMJv2)

sickbeard/config.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -645,3 +645,10 @@ def _migrate_metadata(metadata, metadata_name, use_banner):
645645
sickbeard.METADATA_WDTV = _migrate_metadata(metadata_wdtv, 'WDTV', use_banner)
646646
sickbeard.METADATA_TIVO = _migrate_metadata(metadata_tivo, 'TIVO', use_banner)
647647
sickbeard.METADATA_MEDE8ER = _migrate_metadata(metadata_mede8er, 'Mede8er', use_banner)
648+
649+
# Migration v6: Synology notifier update
650+
def _migrate_v6(self):
651+
""" Updates Synology notifier to reflect that their now is an update library option instead misusing the enable option """
652+
653+
# clone use_synoindex to update_library since this now has notification options
654+
sickbeard.SYNOINDEX_UPDATE_LIBRARY = bool(check_setting_int(self.config_obj, 'Synology', 'use_synoindex', 0))

sickbeard/notifiers/__init__.py

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,15 @@
3636
import trakt
3737

3838
from sickbeard.common import *
39+
from sickbeard import logger
40+
from sickbeard.exceptions import ex
3941

40-
# home theater
42+
# home theater/nas
4143
xbmc_notifier = xbmc.XBMCNotifier()
4244
plex_notifier = plex.PLEXNotifier()
4345
nmj_notifier = nmj.NMJNotifier()
44-
synoindex_notifier = synoindex.synoIndexNotifier()
4546
nmjv2_notifier = nmjv2.NMJv2Notifier()
47+
synoindex_notifier = synoindex.synoIndexNotifier()
4648
pytivo_notifier = pytivo.pyTivoNotifier()
4749
# devices
4850
growl_notifier = growl.GrowlNotifier()
@@ -51,12 +53,12 @@
5153
pushover_notifier = pushover.PushoverNotifier()
5254
boxcar_notifier = boxcar.BoxcarNotifier()
5355
nma_notifier = nma.NMA_Notifier()
54-
# online
56+
# social
5557
twitter_notifier = tweet.TwitterNotifier()
5658
trakt_notifier = trakt.TraktNotifier()
5759

5860
notifiers = [
59-
libnotify_notifier, # Libnotify notifier goes first because it doesn't involve blocking on network activity.
61+
libnotify_notifier, # Libnotify notifier goes first because it doesn't involve blocking on network activity.
6062
xbmc_notifier,
6163
plex_notifier,
6264
nmj_notifier,
@@ -75,14 +77,23 @@
7577

7678
def notify_download(ep_name):
7779
for n in notifiers:
78-
n.notify_download(ep_name)
80+
try:
81+
n.notify_download(ep_name)
82+
except Exception, e:
83+
logger.log(n.__class__.__name__ + ": " + ex(e), logger.ERROR)
7984

8085

8186
def notify_snatch(ep_name):
8287
for n in notifiers:
83-
n.notify_snatch(ep_name)
88+
try:
89+
n.notify_snatch(ep_name)
90+
except Exception, e:
91+
logger.log(n.__class__.__name__ + ": " + ex(e), logger.ERROR)
8492

8593

8694
def update_library(ep_obj):
8795
for n in notifiers:
88-
n.update_library(ep_obj)
96+
try:
97+
n.update_library(ep_obj=ep_obj)
98+
except Exception, e:
99+
logger.log(n.__class__.__name__ + ": " + ex(e), logger.ERROR)

sickbeard/notifiers/boxcar.py

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -64,18 +64,17 @@ def _sendBoxcar(self, msg, title, email, subscribe=False):
6464

6565
# send the request to boxcar
6666
try:
67-
# TODO: Use our getURL from helper?
6867
req = urllib2.Request(curUrl)
6968
handle = urllib2.urlopen(req, data)
7069
handle.close()
7170

7271
except urllib2.URLError, e:
7372
# if we get an error back that doesn't have an error code then who knows what's really happening
7473
if not hasattr(e, 'code'):
75-
logger.log(u"BOXCAR: Boxcar notification failed." + ex(e), logger.ERROR)
74+
logger.log(u"BOXCAR: Notification failed." + ex(e), logger.ERROR)
7675
return False
7776
else:
78-
logger.log(u"BOXCAR: Boxcar notification failed. Error code: " + str(e.code), logger.WARNING)
77+
logger.log(u"BOXCAR: Notification failed. Error code: " + str(e.code), logger.ERROR)
7978

8079
# HTTP status 404 if the provided email address isn't a Boxcar user.
8180
if e.code == 404:
@@ -103,10 +102,10 @@ def _sendBoxcar(self, msg, title, email, subscribe=False):
103102

104103
# If you receive an HTTP status code of 400, it is because you failed to send the proper parameters
105104
elif e.code == 400:
106-
logger.log(u"BOXCAR: Wrong data send to boxcar.", logger.ERROR)
105+
logger.log(u"BOXCAR: Wrong data sent to boxcar.", logger.ERROR)
107106
return False
108107

109-
logger.log(u"BOXCAR: Boxcar notification successful.", logger.DEBUG)
108+
logger.log(u"BOXCAR: Notification successful.", logger.MESSAGE)
110109
return True
111110

112111
def _notify(self, title, message, username=None, force=False):
@@ -129,8 +128,7 @@ def _notify(self, title, message, username=None, force=False):
129128

130129
logger.log(u"BOXCAR: Sending notification for " + message, logger.DEBUG)
131130

132-
self._sendBoxcar(message, title, username)
133-
return True
131+
return self._sendBoxcar(message, title, username)
134132

135133
##############################################################################
136134
# Public functions
@@ -144,10 +142,10 @@ def notify_download(self, ep_name):
144142
if sickbeard.BOXCAR_NOTIFY_ONDOWNLOAD:
145143
self._notify(notifyStrings[NOTIFY_DOWNLOAD], ep_name)
146144

147-
def test_notify(self, email, title="Test"):
148-
return self._sendBoxcar("This is a test notification from SickBeard", title, email)
145+
def test_notify(self, boxcar_username):
146+
return self._notify("This is a test notification from Sick Beard", "Test", boxcar_username, force=True)
149147

150-
def update_library(self, showName=None):
148+
def update_library(self, ep_obj=None):
151149
pass
152150

153151
notifier = BoxcarNotifier

sickbeard/notifiers/growl.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,11 @@ def _notify(self, title="Sick Beard Notification", message=None, name=None, host
115115
print pc
116116
opts['host'] = pc[0]
117117
opts['port'] = pc[1]
118-
logger.log(u"GROWL: Sending message '" + message + "' to " + opts['host'] + ":" + str(opts['port']))
118+
logger.log(u"GROWL: Sending message '" + message + "' to " + opts['host'] + ":" + str(opts['port']), logger.DEBUG)
119119
try:
120120
return self._send_growl(opts, message)
121121
except Exception, e:
122-
logger.log(u"GROWL: Unable to send growl to " + opts['host'] + ":" + str(opts['port']) + " - " + ex(e))
122+
logger.log(u"GROWL: Unable to send growl to " + opts['host'] + ":" + str(opts['port']) + " - " + ex(e), logger.WARNING)
123123
return False
124124

125125
def _sendRegistration(self, host=None, password=None, name="Sick Beard Notification"):
@@ -161,7 +161,7 @@ def _sendRegistration(self, host=None, password=None, name="Sick Beard Notificat
161161
try:
162162
return self._send(opts['host'], opts['port'], register.encode(), opts['debug'])
163163
except Exception, e:
164-
logger.log(u"GROWL: Unable to send growl to " + opts['host'] + ":" + str(opts['port']) + " - " + ex(e))
164+
logger.log(u"GROWL: Unable to send growl to " + opts['host'] + ":" + str(opts['port']) + " - " + ex(e), logger.WARNING)
165165
return False
166166

167167
##############################################################################
@@ -183,7 +183,7 @@ def test_notify(self, host, password):
183183
else:
184184
return result
185185

186-
def update_library(self, showName=None):
186+
def update_library(self, ep_obj=None):
187187
pass
188188

189189
notifier = GrowlNotifier

sickbeard/notifiers/libnotify.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,15 +67,15 @@ def init_pynotify(self):
6767
try:
6868
import pynotify
6969
except ImportError:
70-
logger.log(u"LIBNOTIFY: Unable to import pynotify. libnotify notifications won't work.")
70+
logger.log(u"LIBNOTIFY: Unable to import pynotify. libnotify notifications won't work.", logger.ERROR)
7171
return False
7272
try:
7373
import gobject
7474
except ImportError:
75-
logger.log(u"LIBNOTIFY: Unable to import gobject. We can't catch a GError in display.")
75+
logger.log(u"LIBNOTIFY: Unable to import gobject. We can't catch a GError in display.", logger.ERROR)
7676
return False
7777
if not pynotify.init('Sick Beard'):
78-
logger.log(u"LIBNOTIFY: Initialization of pynotify failed. libnotify notifications won't work.")
78+
logger.log(u"LIBNOTIFY: Initialization of pynotify failed. libnotify notifications won't work.", logger.ERROR)
7979
return False
8080
self.pynotify = pynotify
8181
self.gobject = gobject
@@ -119,7 +119,7 @@ def notify_download(self, ep_name):
119119
def test_notify(self):
120120
return self._notify("Test notification", "This is a test notification from Sick Beard", force=True)
121121

122-
def update_library(self, showName=None):
122+
def update_library(self, ep_obj=None):
123123
pass
124124

125125
notifier = LibnotifyNotifier

0 commit comments

Comments
 (0)