From c26e867859c7cbe4400522ac36d3c0af7ff00e57 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Tue, 1 Apr 2014 00:23:15 +0200 Subject: [PATCH] Added initial version of Growl notification, including image --- headphones/__init__.py | 18 ++++++++- headphones/notifiers.py | 78 ++++++++++++++++++++++++++++++++++++- headphones/postprocessor.py | 6 +++ headphones/sab.py | 4 ++ headphones/transmission.py | 4 ++ lib/gntp/LICENSE | 20 ++++++++++ 6 files changed, 128 insertions(+), 2 deletions(-) create mode 100644 lib/gntp/LICENSE diff --git a/headphones/__init__.py b/headphones/__init__.py index 8a4637bc..0c5a3af6 100644 --- a/headphones/__init__.py +++ b/headphones/__init__.py @@ -219,6 +219,10 @@ ENCODERQUALITY = None ENCODERVBRCBR = None ENCODERLOSSLESS = False DELETE_LOSSLESS_FILES = False +GROWL_ENABLED = True +GROWL_HOST = None +GROWL_PASSWORD = None +GROWL_ONSNATCH = True PROWL_ENABLED = True PROWL_PRIORITY = 1 PROWL_KEYS = None @@ -338,7 +342,7 @@ def initialize(): NZB_DOWNLOADER, TORRENT_DOWNLOADER, PREFERRED_WORDS, REQUIRED_WORDS, IGNORED_WORDS, LASTFM_USERNAME, \ INTERFACE, FOLDER_PERMISSIONS, FILE_PERMISSIONS, ENCODERFOLDER, ENCODER_PATH, ENCODER, XLDPROFILE, BITRATE, SAMPLINGFREQUENCY, \ MUSIC_ENCODER, ADVANCEDENCODER, ENCODEROUTPUTFORMAT, ENCODERQUALITY, ENCODERVBRCBR, ENCODERLOSSLESS, DELETE_LOSSLESS_FILES, \ - PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_KEYS, PUSHOVER_ONSNATCH, MIRRORLIST, \ + GROWL_ENABLED, GROWL_HOST, GROWL_PASSWORD, GROWL_ONSNATCH, PROWL_ENABLED, PROWL_PRIORITY, PROWL_KEYS, PROWL_ONSNATCH, PUSHOVER_ENABLED, PUSHOVER_PRIORITY, PUSHOVER_KEYS, PUSHOVER_ONSNATCH, MIRRORLIST, \ TWITTER_ENABLED, TWITTER_ONSNATCH, TWITTER_USERNAME, TWITTER_PASSWORD, TWITTER_PREFIX, \ PUSHBULLET_ENABLED, PUSHBULLET_APIKEY, PUSHBULLET_DEVICEID, PUSHBULLET_ONSNATCH, \ MIRROR, CUSTOMHOST, CUSTOMPORT, CUSTOMSLEEP, HPUSER, HPPASS, XBMC_ENABLED, XBMC_HOST, XBMC_USERNAME, XBMC_PASSWORD, XBMC_UPDATE, \ @@ -365,6 +369,7 @@ def initialize(): CheckSection('Waffles') CheckSection('Rutracker') CheckSection('What.cd') + CheckSection('Growl') CheckSection('Prowl') CheckSection('Pushover') CheckSection('PushBullet') @@ -536,6 +541,11 @@ def initialize(): ENCODERLOSSLESS = bool(check_setting_int(CFG, 'General', 'encoderlossless', 1)) DELETE_LOSSLESS_FILES = bool(check_setting_int(CFG, 'General', 'delete_lossless_files', 1)) + GROWL_ENABLED = bool(check_setting_int(CFG, 'Growl', 'growl_enabled', 0)) + GROWL_HOST = check_setting_str(CFG, 'Growl', 'growl_host', '') + GROWL_PASSWORD = check_setting_str(CFG, 'Growl', 'growl_password', '') + GROWL_ONSNATCH = bool(check_setting_int(CFG, 'Growl', 'growl_onsnatch', 0)) + PROWL_ENABLED = bool(check_setting_int(CFG, 'Prowl', 'prowl_enabled', 0)) PROWL_KEYS = check_setting_str(CFG, 'Prowl', 'prowl_keys', '') PROWL_ONSNATCH = bool(check_setting_int(CFG, 'Prowl', 'prowl_onsnatch', 0)) @@ -928,6 +938,12 @@ def config_write(): new_config['General']['ignored_words'] = IGNORED_WORDS new_config['General']['required_words'] = REQUIRED_WORDS + new_config['Growl'] = {} + new_config['Growl']['growl_enabled'] = int(GROWL_ENABLED) + new_config['Growl']['growl_host'] = GROWL_HOST + new_config['Growl']['growl_password'] = GROWL_PASSWORD + new_config['Growl']['growl_onsnatch'] = int(GROWL_ONSNATCH) + new_config['Prowl'] = {} new_config['Prowl']['prowl_enabled'] = int(PROWL_ENABLED) new_config['Prowl']['prowl_keys'] = PROWL_KEYS diff --git a/headphones/notifiers.py b/headphones/notifiers.py index 3da78a6e..52cb9703 100644 --- a/headphones/notifiers.py +++ b/headphones/notifiers.py @@ -34,6 +34,83 @@ except: import lib.oauth2 as oauth import lib.pythontwitter as twitter +import lib.gntp.notifier as gntp_notifier + +class GROWL: + + def __init__(self): + self.enabled = headphones.GROWL_ENABLED + self.host = headphones.GROWL_HOST + self.password = headphones.GROWL_PASSWORD + + def conf(self, options): + return cherrypy.config['config'].get('Growl', options) + + def notify(self, message, event): + if not self.enabled: + return + + # Split host and port + if self.host == "": + host, port = "localhost", 23053 + if ":" in self.host: + host, port = self.host.split(':', 1) + port = int(port) + else: + host, port = self.host, 23053 + + # If password is empty, assume none + if self.password == "": + password = None + else: + password = self.password + + # Register notification + growl = gntp_notifier.GrowlNotifier( + applicationName='Headphones', + notifications=['New Event'], + defaultNotifications=['New Event'], + hostname=host, + port=port, + password=password + ) + + try: + growl.register() + except gntp_notifier.errors.NetworkError: + logger.info(u'Growl notification failed: network error') + return + except gntp_notifier.errors.AuthError: + logger.info(u'Growl notification failed: authentication error') + return + + # Send it, including an image + image_file = os.path.join(str(headphones.PROG_DIR), 'data/images/headphoneslogo.png') + image = open(image_file, 'rb').read() + + try: + growl.notify( + noteType='New Event', + title=event, + description=message, + icon=image + ) + except gntp_notifier.errors.NetworkError: + logger.info(u'Growl notification failed: network error') + return + + logger.info(u"Growl notifications sent.") + + def updateLibrary(self): + #For uniformity reasons not removed + return + + def test(self, host, password): + self.enabled = True + self.host = host + self.password = password + + self.notify('ZOMG Lazors Pewpewpew!', 'Test Message') class PROWL: @@ -44,7 +121,6 @@ class PROWL: self.enabled = headphones.PROWL_ENABLED self.keys = headphones.PROWL_KEYS self.priority = headphones.PROWL_PRIORITY - pass def conf(self, options): return cherrypy.config['config'].get('Prowl', options) diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 1333936f..bf8cfcae 100644 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -407,6 +407,12 @@ def doPostProcessing(albumid, albumpath, release, tracks, downloaded_track_list, logger.info(u'Post-processing for %s - %s complete' % (release['ArtistName'], release['AlbumTitle'])) + if headphones.GROWL_ENABLED: + pushmessage = release['ArtistName'] + ' - ' + release['AlbumTitle'] + logger.info(u"Growl request") + growl = notifiers.GROWL() + growl.notify(pushmessage,"Download and Postprocessing completed") + if headphones.PROWL_ENABLED: pushmessage = release['ArtistName'] + ' - ' + release['AlbumTitle'] logger.info(u"Prowl request") diff --git a/headphones/sab.py b/headphones/sab.py index 45b494a6..2bcbe2d2 100644 --- a/headphones/sab.py +++ b/headphones/sab.py @@ -119,6 +119,10 @@ def sendNZB(nzb): if sabText == "ok": logger.info(u"NZB sent to SAB successfully") + if headphones.GROWL_ENABLED and headphones.GROWL_ONSNATCH: + logger.info(u"Sending Growl notification") + growl = notifiers.GROWL() + growl.notify(nzb.name,"Download started") if headphones.PROWL_ENABLED and headphones.PROWL_ONSNATCH: logger.info(u"Sending Prowl notification") prowl = notifiers.PROWL() diff --git a/headphones/transmission.py b/headphones/transmission.py index 92073683..cc2d0e51 100644 --- a/headphones/transmission.py +++ b/headphones/transmission.py @@ -49,6 +49,10 @@ def addTorrent(link): retid = False logger.info(u"Torrent sent to Transmission successfully") + if headphones.GROWL_ENABLED and headphones.GROWL_ONSNATCH: + logger.info(u"Sending Growl notification") + growl = notifiers.GROWL() + growl.notify(name,"Download started") if headphones.PROWL_ENABLED and headphones.PROWL_ONSNATCH: logger.info(u"Sending Prowl notification") prowl = notifiers.PROWL() diff --git a/lib/gntp/LICENSE b/lib/gntp/LICENSE new file mode 100644 index 00000000..c274a5a2 --- /dev/null +++ b/lib/gntp/LICENSE @@ -0,0 +1,20 @@ +Copyright (c) 2013 Paul Traylor + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE +LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION +WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.