Skip to content

Commit

Permalink
New feature: Allow use of Pushover priorities. (#5567)
Browse files Browse the repository at this point in the history
* New feature: Allow use of Pushover priorities.
Also, set default Pushover alert sound to whatever is configured on the receiving device, and fixed bug where unsuccessful notification were not being detected.

* run `yarn dev`

* Fix code style

* yarn dev again
  • Loading branch information
andofrjando authored and p0psicles committed Nov 4, 2018
1 parent 674196f commit f3be47a
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 96 deletions.
4 changes: 3 additions & 1 deletion medusa/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,8 @@ def initialize(self, console_logging=True):
app.PUSHOVER_USERKEY = check_setting_str(app.CFG, 'Pushover', 'pushover_userkey', '', censor_log='normal')
app.PUSHOVER_APIKEY = check_setting_str(app.CFG, 'Pushover', 'pushover_apikey', '', censor_log='low')
app.PUSHOVER_DEVICE = check_setting_list(app.CFG, 'Pushover', 'pushover_device', '')
app.PUSHOVER_SOUND = check_setting_str(app.CFG, 'Pushover', 'pushover_sound', 'pushover')
app.PUSHOVER_SOUND = check_setting_str(app.CFG, 'Pushover', 'pushover_sound', 'default')
app.PUSHOVER_PRIORITY = check_setting_str(app.CFG, 'Pushover', 'pushover_priority', '0')

app.USE_LIBNOTIFY = bool(check_setting_int(app.CFG, 'Libnotify', 'use_libnotify', 0))
app.LIBNOTIFY_NOTIFY_ONSNATCH = bool(check_setting_int(app.CFG, 'Libnotify', 'libnotify_notify_onsnatch', 0))
Expand Down Expand Up @@ -1780,6 +1781,7 @@ def save_config():
new_config['Pushover']['pushover_apikey'] = app.PUSHOVER_APIKEY
new_config['Pushover']['pushover_device'] = app.PUSHOVER_DEVICE
new_config['Pushover']['pushover_sound'] = app.PUSHOVER_SOUND
new_config['Pushover']['pushover_priority'] = app.PUSHOVER_PRIORITY

new_config['Libnotify'] = {}
new_config['Libnotify']['use_libnotify'] = int(app.USE_LIBNOTIFY)
Expand Down
1 change: 1 addition & 0 deletions medusa/app.py
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,7 @@ def __init__(self):
self.PUSHOVER_APIKEY = None
self.PUSHOVER_DEVICE = []
self.PUSHOVER_SOUND = None
self.PUSHOVER_PRIORITY = 0

self.USE_LIBNOTIFY = False
self.LIBNOTIFY_NOTIFY_ONSNATCH = False
Expand Down
150 changes: 76 additions & 74 deletions medusa/notifiers/pushover.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@
NOTIFY_SUBTITLE_DOWNLOAD,
notifyStrings,
)
from medusa.helper.exceptions import ex
from medusa.logger.adapters.style import BraceAdapter

from requests.compat import urlencode

from six.moves.http_client import HTTPSConnection
from six.moves.urllib.error import HTTPError

log = BraceAdapter(logging.getLogger(__name__))
log.logger.addHandler(logging.NullHandler())
Expand All @@ -39,7 +37,7 @@ def __init__(self):
def test_notify(self, userKey=None, apiKey=None):
return self._notifyPushover('This is a test notification from Medusa', 'Test', userKey=userKey, apiKey=apiKey, force=True)

def _sendPushover(self, msg, title, sound=None, userKey=None, apiKey=None):
def _sendPushover(self, msg, title, sound=None, userKey=None, apiKey=None, priority=None):
"""
Sends a pushover notification to the address provided
Expand All @@ -48,6 +46,7 @@ def _sendPushover(self, msg, title, sound=None, userKey=None, apiKey=None):
sound: The notification sound to use
userKey: The pushover user id to send the message to (or to subscribe with)
apiKey: The pushover api key to use
priority: The pushover priority to use
returns: True if the message succeeded, False otherwise
"""

Expand All @@ -60,83 +59,85 @@ def _sendPushover(self, msg, title, sound=None, userKey=None, apiKey=None):
if sound is None:
sound = app.PUSHOVER_SOUND

log.debug(u'Pushover API KEY in use: {0}', apiKey)
if priority is None:
priority = app.PUSHOVER_PRIORITY

# build up the URL and parameters
msg = msg.strip()

# send the request to pushover
try:
if app.PUSHOVER_SOUND != 'default':
args = {
'token': apiKey,
'user': userKey,
'title': title.encode('utf-8'),
'message': msg.encode('utf-8'),
'timestamp': int(time.time()),
'retry': 60,
'expire': 3600,
'sound': sound,
}
else:
# sound is default, so don't send it
args = {
'token': apiKey,
'user': userKey,
'title': title.encode('utf-8'),
'message': msg.encode('utf-8'),
'timestamp': int(time.time()),
'retry': 60,
'expire': 3600,
}

if app.PUSHOVER_DEVICE:
args['device'] = ','.join(app.PUSHOVER_DEVICE)

conn = HTTPSConnection('api.pushover.net:443')
conn.request('POST', '/1/messages.json',
urlencode(args), {'Content-type': 'application/x-www-form-urlencoded'})

except HTTPError as e:
# if we get an error back that doesn't have an error code then who knows what's really happening
if not hasattr(e, 'code'):
log.error(u'Pushover notification failed. {}', ex(e))
return False
if sound != 'default':
args = {
'token': apiKey,
'user': userKey,
'title': title.encode('utf-8'),
'message': msg.encode('utf-8'),
'timestamp': int(time.time()),
'retry': 60,
'expire': 3600,
'sound': sound,
'priority': priority,
}
else:
# sound is default, so don't send it
args = {
'token': apiKey,
'user': userKey,
'title': title.encode('utf-8'),
'message': msg.encode('utf-8'),
'timestamp': int(time.time()),
'retry': 60,
'expire': 3600,
'priority': priority,
}

if app.PUSHOVER_DEVICE:
args['device'] = ','.join(app.PUSHOVER_DEVICE)

log.debug(u'PUSHOVER: Sending notice with details: title="{0}" message="{1}", priority={2}, sound={3}',
args['title'], args['message'], priority, sound)

conn = HTTPSConnection('api.pushover.net:443')
conn.request('POST', '/1/messages.json',
urlencode(args), {'Content-type': 'application/x-www-form-urlencoded'})
conn_resp = conn.getresponse()

if conn_resp.status == 200:
log.info(u'Pushover notification successful.')
return True

# HTTP status 404 if the provided email address isn't a Pushover user.
elif conn_resp.status == 404:
log.warning(u'Username is wrong/not a pushover email. Pushover will send an email to it')
return False

# For HTTP status code 401's, it is because you are passing in either an invalid token, or the user has not added your service.
elif conn_resp.status == 401:
# HTTP status 401 if the user doesn't have the service added
subscribeNote = self._sendPushover(msg, title, sound=sound, userKey=userKey, apiKey=apiKey)
if subscribeNote:
log.debug(u'Subscription sent')
return True
else:
log.error(u'Pushover notification failed. Error code: {0}', e.code)

# HTTP status 404 if the provided email address isn't a Pushover user.
if e.code == 404:
log.warning(u'Username is wrong/not a pushover email. Pushover will send an email to it')
return False

# For HTTP status code 401's, it is because you are passing in either an invalid token, or the user has not added your service.
elif e.code == 401:

# HTTP status 401 if the user doesn't have the service added
subscribeNote = self._sendPushover(msg, title, sound=sound, userKey=userKey, apiKey=apiKey)
if subscribeNote:
log.debug(u'Subscription sent')
return True
else:
log.error(u'Subscription could not be sent')
return False

# If you receive an HTTP status code of 400, it is because you failed to send the proper parameters
elif e.code == 400:
log.error(u'Wrong data sent to pushover')
return False

# If you receive a HTTP status code of 429, it is because the message limit has been reached (free limit is 7,500)
elif e.code == 429:
log.error(u'Pushover API message limit reached - try a different API key')
return False

log.info(u'Pushover notification successful.')
return True
log.error(u'Subscription could not be sent')

# If you receive an HTTP status code of 400, it is because you failed to send the proper parameters
elif conn_resp.status == 400:
log.error(u'Wrong keys sent to pushover')
return False

# If you receive a HTTP status code of 429, it is because the message limit has been reached (free limit is 7,500)
elif conn_resp.status == 429:
log.error(u'Pushover API message limit reached - try a different API key')
return False

# Something else has gone wrong... who knows what's really happening
else:
log.error(u'Pushover notification failed. HTTP response code: {0}', conn_resp.status)
return False

def notify_snatch(self, ep_name, is_proper):
title=notifyStrings[(NOTIFY_SNATCH, NOTIFY_SNATCH_PROPER)[is_proper]]
title = notifyStrings[(NOTIFY_SNATCH, NOTIFY_SNATCH_PROPER)[is_proper]]
if app.PUSHOVER_NOTIFY_ONSNATCH:
self._notifyPushover(title, ep_name)

Expand All @@ -160,7 +161,7 @@ def notify_login(self, ipaddress=''):
title = notifyStrings[NOTIFY_LOGIN]
self._notifyPushover(title, update_text.format(ipaddress))

def _notifyPushover(self, title, message, sound=None, userKey=None, apiKey=None, force=False):
def _notifyPushover(self, title, message, sound=None, userKey=None, apiKey=None, priority=None, force=False):
"""
Sends a pushover notification based on the provided info or Medusa config
Expand All @@ -169,6 +170,7 @@ def _notifyPushover(self, title, message, sound=None, userKey=None, apiKey=None,
sound: The notification sound to use
userKey: The userKey to send the notification to
apiKey: The apiKey to use to send the notification
priority: The pushover priority to use
force: Enforce sending, for instance for testing
"""

Expand All @@ -178,4 +180,4 @@ def _notifyPushover(self, title, message, sound=None, userKey=None, apiKey=None,

log.debug(u'Sending notification for {0}', message)

return self._sendPushover(message, title, sound=sound, userKey=userKey, apiKey=apiKey)
return self._sendPushover(message, title, sound=sound, userKey=userKey, apiKey=apiKey, priority=priority)
2 changes: 2 additions & 0 deletions medusa/server/api/v2/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ class ConfigHandler(BaseRequestHandler):
'notifiers.pushover.userKey': StringField(app, 'PUSHOVER_USERKEY'),
'notifiers.pushover.device': ListField(app, 'PUSHOVER_DEVICE'),
'notifiers.pushover.sound': StringField(app, 'PUSHOVER_SOUND'),
'notifiers.pushover.priority': IntegerField(app, 'PUSHOVER_PRIORITY'),
'notifiers.pushover.notifyOnSnatch': BooleanField(app, 'PUSHOVER_NOTIFY_ONSNATCH'),
'notifiers.pushover.notifyOnDownload': BooleanField(app, 'PUSHOVER_NOTIFY_ONDOWNLOAD'),
'notifiers.pushover.notifyOnSubtitleDownload': BooleanField(app, 'PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD'),
Expand Down Expand Up @@ -848,6 +849,7 @@ def data_notifiers():
section_data['pushover']['userKey'] = app.PUSHOVER_USERKEY
section_data['pushover']['device'] = app.PUSHOVER_DEVICE
section_data['pushover']['sound'] = app.PUSHOVER_SOUND
section_data['pushover']['priority'] = app.PUSHOVER_PRIORITY
section_data['pushover']['notifyOnSnatch'] = bool(app.PUSHOVER_NOTIFY_ONSNATCH)
section_data['pushover']['notifyOnDownload'] = bool(app.PUSHOVER_NOTIFY_ONDOWNLOAD)
section_data['pushover']['notifyOnSubtitleDownload'] = bool(app.PUSHOVER_NOTIFY_ONSUBTITLEDOWNLOAD)
Expand Down
7 changes: 4 additions & 3 deletions medusa/server/web/config/notifications.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ def saveNotifications(self, use_kodi=None, kodi_always_on=None, kodi_notify_onsn
use_boxcar2=None, boxcar2_notify_onsnatch=None, boxcar2_notify_ondownload=None,
boxcar2_notify_onsubtitledownload=None, boxcar2_accesstoken=None,
use_pushover=None, pushover_notify_onsnatch=None, pushover_notify_ondownload=None,
pushover_notify_onsubtitledownload=None, pushover_userkey=None, pushover_apikey=None, pushover_device=None, pushover_sound=None,
use_libnotify=None, libnotify_notify_onsnatch=None, libnotify_notify_ondownload=None,
libnotify_notify_onsubtitledownload=None,
pushover_notify_onsubtitledownload=None, pushover_userkey=None, pushover_apikey=None, pushover_device=None,
pushover_sound=None, pushover_priority=None, use_libnotify=None, libnotify_notify_onsnatch=None,
libnotify_notify_ondownload=None, libnotify_notify_onsubtitledownload=None,
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_pin=None,
Expand Down Expand Up @@ -173,6 +173,7 @@ def saveNotifications(self, use_kodi=None, kodi_always_on=None, kodi_notify_onsn
app.PUSHOVER_APIKEY = pushover_apikey
app.PUSHOVER_DEVICE = [_.strip() for _ in pushover_device.split(',')]
app.PUSHOVER_SOUND = pushover_sound
app.PUSHOVER_PRIORITY = pushover_priority

app.USE_LIBNOTIFY = config.checkbox_to_value(use_libnotify)
app.LIBNOTIFY_NOTIFY_ONSNATCH = config.checkbox_to_value(libnotify_notify_onsnatch)
Expand Down
31 changes: 25 additions & 6 deletions themes-default/slim/views/config_notifications.mako
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,15 @@ window.app = new Vue({
{ text: 'High', value: 1 },
{ text: 'Emergency', value: 2 }
],
pushoverPriorityOptions: [
{ text: 'Lowest', value: -2 },
{ text: 'Low', value: -1 },
{ text: 'Normal', value: 0 },
{ text: 'High', value: 1 },
{ text: 'Emergency', value: 2 }
],
pushoverSoundOptions: [
{ text: 'Default', value: 'default' },
{ text: 'Pushover', value: 'pushover' },
{ text: 'Bike', value: 'bike' },
{ text: 'Bugle', value: 'bugle' },
Expand All @@ -48,8 +56,7 @@ window.app = new Vue({
{ text: 'Persistent (long)', value: 'persistant' },
{ text: 'Pushover Echo (long)', value: 'echo' },
{ text: 'Up Down (long)', value: 'updown' },
{ text: 'None (silent)', value: 'none' },
{ text: 'Device specific', value: 'default' }
{ text: 'None (silent)', value: 'none' }
],
pushbulletDeviceOptions: [
{ text: 'All devices', value: '' }
Expand Down Expand Up @@ -163,6 +170,7 @@ window.app = new Vue({
userKey: null,
device: [],
sound: null,
priority: null,
notifyOnSnatch: null,
notifyOnDownload: null,
notifyOnSubtitleDownload: null
Expand Down Expand Up @@ -1396,18 +1404,20 @@ window.app = new Vue({
<config-toggle-slider v-model="notifiers.pushover.notifyOnDownload" label="Notify on download" id="pushover_notify_ondownload" :explanations="['send a notification when a download finishes?']" @change="save()" ></config-toggle-slider>
<config-toggle-slider v-model="notifiers.pushover.notifyOnSubtitleDownload" label="Notify on subtitle download" id="pushover_notify_onsubtitledownload" :explanations="['send a notification when subtitles are downloaded?']" @change="save()" ></config-toggle-slider>
<config-textbox v-model="notifiers.pushover.userKey" label="Pushover Key" id="pushover_userkey" :explanations="['user key of your Pushover account']" @change="save()" ></config-textbox>
<config-textbox v-model="notifiers.pushover.userKey" label="Pushover User Key" id="pushover_userkey" :explanations="['User Key of your Pushover account']" @change="save()" ></config-textbox>
<config-textbox v-model="notifiers.pushover.apiKey" label="Pushover API Key" id="pushover_apikey" @change="save()" >
<span><app-link href="https://pushover.net/apps/build/"><b>Click here</b></app-link> to create a Pushover API key</span>
<config-textbox v-model="notifiers.pushover.apiKey" label="Pushover API key" id="pushover_apikey" @change="save()" >
<span><app-link href="https://pushover.net/apps/build/"><b>Click here</b></app-link> to create a Pushover API key</span>
</config-textbox>
<config-template label-for="pushover_device" label="Pushover Devices">
<select-list name="pushover_device" id="pushover_device" :list-items="notifiers.pushover.device" @change="notifiers.pushover.device = $event.map(x => x.value)"></select-list>
<p>List of pushover devices you want to send notifications to</p>
</config-template>
<config-template label-for="pushover_spound" label="Pushover notification sound">
<config-template label-for="pushover_sound" label="Pushover notification sound">
<select id="pushover_sound" name="pushover_sound" v-model="notifiers.pushover.sound" class="form-control">
<option v-for="option in pushoverSoundOptions" v-bind:value="option.value">
{{ option.text }}
Expand All @@ -1416,6 +1426,15 @@ window.app = new Vue({
<span>Choose notification sound to use</span>
</config-template>
<config-template label-for="pushover_priority" label="Pushover notification priority">
<select id="pushover_priority" name="pushover_priority" v-model="notifiers.pushover.priority" class="form-control">
<option v-for="option in pushoverPriorityOptions" v-bind:value="option.value">
{{ option.text }}
</option>
</select>
<span>priority of Pushover messages from Medusa</span>
</config-template>
<div class="testNotification" id="testPushover-result">Click below to test.</div>
<input class="btn-medusa" type="button" value="Test Pushover" id="testPushover" @click="testPushover"/>
<input type="submit" class="config_submitter btn-medusa" value="Save Changes"/>
Expand Down
Loading

0 comments on commit f3be47a

Please sign in to comment.