Update all notifiers to use requests library

This commit is contained in:
JonnyWong16 2017-07-06 22:42:34 -07:00
parent abf55df26d
commit 9701474662

View file

@ -16,11 +16,9 @@
import base64 import base64
import bleach import bleach
import json import json
import cherrypy
from email.mime.multipart import MIMEMultipart from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText from email.mime.text import MIMEText
import email.utils import email.utils
from httplib import HTTPSConnection
import os import os
import re import re
import requests import requests
@ -29,9 +27,7 @@ import smtplib
import subprocess import subprocess
import threading import threading
import time import time
import urllib
from urllib import urlencode from urllib import urlencode
import urllib2
from urlparse import urlparse from urlparse import urlparse
import uuid import uuid
@ -324,7 +320,7 @@ def get_agent_class(agent_id=None, config=None):
agent_id = int(agent_id) agent_id = int(agent_id)
if agent_id == 0: if agent_id == 0:
return GROWL(config=config) return GROWL(config=config,)
elif agent_id == 1: elif agent_id == 1:
return PROWL(config=config) return PROWL(config=config)
elif agent_id == 2: elif agent_id == 2:
@ -662,6 +658,7 @@ class PrettyMetadata(object):
class Notifier(object): class Notifier(object):
NAME = ''
_DEFAULT_CONFIG = {} _DEFAULT_CONFIG = {}
def __init__(self, config=None): def __init__(self, config=None):
@ -687,6 +684,16 @@ class Notifier(object):
def notify(self, subject='', body='', action='', **kwargs): def notify(self, subject='', body='', action='', **kwargs):
pass pass
def notify_success(self, req=None):
if req is not None:
if req.status_code >= 200 and req.status_code < 300:
logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True
else:
logger.error(u"PlexPy Notifiers :: {name} notification failed: "
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
return False
def return_config_options(self): def return_config_options(self):
config_options = [] config_options = []
return config_options return config_options
@ -696,11 +703,12 @@ class ANDROIDAPP(Notifier):
""" """
PlexPy Android app notifications PlexPy Android app notifications
""" """
NAME = 'PlexPy Android App'
_DEFAULT_CONFIG = {'device_id': '', _DEFAULT_CONFIG = {'device_id': '',
'priority': 3 'priority': 3
} }
ONESIGNAL_APP_ID = '3b4b666a-d557-4b92-acdf-e2c8c4b95357' _ONESIGNAL_APP_ID = '3b4b666a-d557-4b92-acdf-e2c8c4b95357'
def notify(self, subject='', body='', action='', notification_id=None, **kwargs): def notify(self, subject='', body='', action='', notification_id=None, **kwargs):
if not subject or not body: if not subject or not body:
@ -750,7 +758,7 @@ class ANDROIDAPP(Notifier):
#logger.debug("Nonce (base64): {}".format(base64.b64encode(nonce))) #logger.debug("Nonce (base64): {}".format(base64.b64encode(nonce)))
#logger.debug("Salt (base64): {}".format(base64.b64encode(salt))) #logger.debug("Salt (base64): {}".format(base64.b64encode(salt)))
payload = {'app_id': self.ONESIGNAL_APP_ID, payload = {'app_id': self._ONESIGNAL_APP_ID,
'include_player_ids': [self.config['device_id']], 'include_player_ids': [self.config['device_id']],
'contents': {'en': 'PlexPy Notification'}, 'contents': {'en': 'PlexPy Notification'},
'data': {'encrypted': True, 'data': {'encrypted': True,
@ -763,7 +771,7 @@ class ANDROIDAPP(Notifier):
"Android app notifications will be sent unecrypted. " "Android app notifications will be sent unecrypted. "
"Install the library to encrypt the notifications.") "Install the library to encrypt the notifications.")
payload = {'app_id': self.ONESIGNAL_APP_ID, payload = {'app_id': self._ONESIGNAL_APP_ID,
'include_player_ids': [self.config['device_id']], 'include_player_ids': [self.config['device_id']],
'contents': {'en': 'PlexPy Notification'}, 'contents': {'en': 'PlexPy Notification'},
'data': {'encrypted': False, 'data': {'encrypted': False,
@ -775,19 +783,10 @@ class ANDROIDAPP(Notifier):
headers = {'Content-Type': 'application/json'} headers = {'Content-Type': 'application/json'}
r = requests.post("https://onesignal.com/api/v1/notifications", headers=headers, json=payload) r = requests.post("https://onesignal.com/api/v1/notifications", headers=headers, json=payload)
request_status = r.status_code
#logger.debug("OneSignal response: {}".format(r.content)) #logger.debug("OneSignal response: {}".format(r.content))
if request_status == 200: return self.notify_success(req=r)
logger.info(u"PlexPy Notifiers :: Android app notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Android app notification failed: [%s] %s" % (request_status, r.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Android app notification failed.")
return False
def get_devices(self): def get_devices(self):
db = database.MonitorDatabase() db = database.MonitorDatabase()
@ -873,6 +872,7 @@ class BOXCAR(Notifier):
""" """
Boxcar notifications Boxcar notifications
""" """
NAME = 'Boxcar'
_DEFAULT_CONFIG = {'token': '', _DEFAULT_CONFIG = {'token': '',
'sound': '' 'sound': ''
} }
@ -881,23 +881,15 @@ class BOXCAR(Notifier):
if not subject or not body: if not subject or not body:
return return
try: data = {'user_credentials': self.config['token'],
data = urllib.urlencode({
'user_credentials': self.config['token'],
'notification[title]': subject.encode('utf-8'), 'notification[title]': subject.encode('utf-8'),
'notification[long_message]': body.encode('utf-8'), 'notification[long_message]': body.encode('utf-8'),
'notification[sound]': self.config['sound'] 'notification[sound]': self.config['sound']
}) }
req = urllib2.Request('https://new.boxcar.io/api/notifications') r = requests.post('https://new.boxcar.io/api/notifications', params=data)
handle = urllib2.urlopen(req, data)
handle.close()
logger.info(u"PlexPy Notifiers :: Boxcar2 notification sent.")
return True
except urllib2.URLError as e: return self.notify_success(req=r)
logger.warn(u"PlexPy Notifiers :: Boxcar2 notification failed: %s" % e)
return False
def get_sounds(self): def get_sounds(self):
sounds = {'': '', sounds = {'': '',
@ -956,6 +948,7 @@ class BROWSER(Notifier):
""" """
Browser notifications Browser notifications
""" """
NAME = 'Browser'
_DEFAULT_CONFIG = {'enabled': 0, _DEFAULT_CONFIG = {'enabled': 0,
'auto_hide_delay': 5 'auto_hide_delay': 5
} }
@ -964,7 +957,7 @@ class BROWSER(Notifier):
if not subject or not body: if not subject or not body:
return return
logger.info(u"PlexPy Notifiers :: Browser notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
def get_notifications(self): def get_notifications(self):
@ -1014,6 +1007,7 @@ class DISCORD(Notifier):
""" """
Discord Notifications Discord Notifications
""" """
NAME = 'Discord'
_DEFAULT_CONFIG = {'hook': '', _DEFAULT_CONFIG = {'hook': '',
'username': '', 'username': '',
'avatar_url': '', 'avatar_url': '',
@ -1088,30 +1082,12 @@ class DISCORD(Notifier):
data['embeds'] = [attachment] data['embeds'] = [attachment]
host = urlparse(self.config['hook']).hostname headers = {'Content-type': 'application/json'}
path = urlparse(self.config['hook']).path params = {'wait': True}
query_params = {'wait': True} r = requests.post(self.config['hook'], params=params, headers=headers, json=data)
query_string = urllib.urlencode(query_params)
http_handler = HTTPSConnection(host) return self.notify_success(req=r)
http_handler.request("POST",
path + '?' + query_string,
headers={'Content-type': "application/json"},
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200:
logger.info(u"PlexPy Notifiers :: Discord notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Discord notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Discord notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Discord Webhook URL', config_option = [{'label': 'Discord Webhook URL',
@ -1183,6 +1159,7 @@ class EMAIL(Notifier):
""" """
Email notifications Email notifications
""" """
NAME = 'Email'
_DEFAULT_CONFIG = {'from_name': '', _DEFAULT_CONFIG = {'from_name': '',
'from': '', 'from': '',
'to': '', 'to': '',
@ -1232,11 +1209,11 @@ class EMAIL(Notifier):
mailserver.sendmail(self.config['from'], recipients, msg.as_string()) mailserver.sendmail(self.config['from'], recipients, msg.as_string())
mailserver.quit() mailserver.quit()
logger.info(u"PlexPy Notifiers :: Email notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: Email notification failed: %s" % e) logger.error(u"PlexPy Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
def return_config_options(self): def return_config_options(self):
@ -1316,6 +1293,7 @@ class FACEBOOK(Notifier):
""" """
Facebook notifications Facebook notifications
""" """
NAME = 'Facebook'
_DEFAULT_CONFIG = {'redirect_uri': '', _DEFAULT_CONFIG = {'redirect_uri': '',
'access_token': '', 'access_token': '',
'app_id': '', 'app_id': '',
@ -1340,7 +1318,7 @@ class FACEBOOK(Notifier):
perms=['user_managed_groups','publish_actions']) perms=['user_managed_groups','publish_actions'])
def _get_credentials(self, code=''): def _get_credentials(self, code=''):
logger.info(u"PlexPy Notifiers :: Requesting access token from Facebook") logger.info(u"PlexPy Notifiers :: Requesting access token from {name}.".format(name=self.NAME))
app_id = plexpy.CONFIG.FACEBOOK_APP_ID app_id = plexpy.CONFIG.FACEBOOK_APP_ID
app_secret = plexpy.CONFIG.FACEBOOK_APP_SECRET app_secret = plexpy.CONFIG.FACEBOOK_APP_SECRET
@ -1362,7 +1340,7 @@ class FACEBOOK(Notifier):
plexpy.CONFIG.FACEBOOK_TOKEN = response['access_token'] plexpy.CONFIG.FACEBOOK_TOKEN = response['access_token']
except Exception as e: except Exception as e:
logger.error(u"PlexPy Notifiers :: Error requesting Facebook access token: %s" % e) logger.error(u"PlexPy Notifiers :: Error requesting {name} access token: {e}".format(name=self.NAME, e=e))
plexpy.CONFIG.FACEBOOK_TOKEN = '' plexpy.CONFIG.FACEBOOK_TOKEN = ''
# Clear out temporary config values # Clear out temporary config values
@ -1378,14 +1356,14 @@ class FACEBOOK(Notifier):
try: try:
api.put_wall_post(profile_id=self.config['group_id'], message=message, attachment=attachment) api.put_wall_post(profile_id=self.config['group_id'], message=message, attachment=attachment)
logger.info(u"PlexPy Notifiers :: Facebook notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: Error sending Facebook post: %s" % e) logger.error(u"PlexPy Notifiers :: Error sending {name} post: {e}".format(name=self.NAME, e=e))
return False return False
else: else:
logger.warn(u"PlexPy Notifiers :: Error sending Facebook post: No Facebook Group ID provided.") logger.error(u"PlexPy Notifiers :: Error sending {name} post: No {name} Group ID provided.".format(name=self.NAME))
return False return False
def notify(self, subject='', body='', action='', **kwargs): def notify(self, subject='', body='', action='', **kwargs):
@ -1514,6 +1492,7 @@ class GROUPME(Notifier):
""" """
GroupMe notifications GroupMe notifications
""" """
NAME = 'GroupMe'
_DEFAULT_CONFIG = {'access_token': '', _DEFAULT_CONFIG = {'access_token': '',
'bot_id': '', 'bot_id': '',
'incl_subject': 1, 'incl_subject': 1,
@ -1538,40 +1517,24 @@ class GROUPME(Notifier):
if poster_url: if poster_url:
headers = {'X-Access-Token': self.config['access_token'], headers = {'X-Access-Token': self.config['access_token'],
'Content-Type': 'image/jpeg'} 'Content-Type': 'image/jpeg'}
poster_data = urllib.urlopen(poster_url).read() poster_request = requests.get(poster_url)
poster_content = poster_request.content
response = requests.post('https://image.groupme.com/pictures', r = requests.post('https://image.groupme.com/pictures', headers=headers, data=poster_content)
headers=headers,
data=poster_data)
request_status = response.status_code
request_content = json.loads(response.text)
if request_status == 200: if r.status_code == 200:
logger.info(u"PlexPy Notifiers :: GroupMe poster sent.") logger.info(u"PlexPy Notifiers :: {name} poster sent.".format(name=self.NAME))
r_content = r.json()
data['attachments'] = [{'type': 'image', data['attachments'] = [{'type': 'image',
'url': request_content['payload']['picture_url']}] 'url': r_content['payload']['picture_url']}]
elif request_status >= 400 and request_status <= 500:
logger.warn(u"PlexPy Notifiers :: GroupMe poster failed: %s" % request_content.get('errors'))
else: else:
logger.warn(u"PlexPy Notifiers :: GroupMe poster failed.") logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=r))
http_handler = HTTPSConnection("api.groupme.com")
http_handler.request("POST",
"/v3/bots/post",
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 202:
logger.info(u"PlexPy Notifiers :: GroupMe notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: GroupMe notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: GroupMe notification failed.")
return False return False
r = requests.post('https://api.groupme.com/v3/bots/post', json=data)
return self.notify_success(req=r)
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'GroupMe Access Token', config_option = [{'label': 'GroupMe Access Token',
'value': self.config['access_token'], 'value': self.config['access_token'],
@ -1606,6 +1569,7 @@ class GROWL(Notifier):
""" """
Growl notifications, for OS X. Growl notifications, for OS X.
""" """
NAME = 'Growl'
_DEFAULT_CONFIG = {'host': '', _DEFAULT_CONFIG = {'host': '',
'password': '' 'password': ''
} }
@ -1642,10 +1606,10 @@ class GROWL(Notifier):
try: try:
growl.register() growl.register()
except gntp.notifier.errors.NetworkError: except gntp.notifier.errors.NetworkError:
logger.warn(u"PlexPy Notifiers :: Growl notification failed: network error") logger.error(u"PlexPy Notifiers :: {name} notification failed: network error".format(name=self.NAME))
return False return False
except gntp.notifier.errors.AuthError: except gntp.notifier.errors.AuthError:
logger.warn(u"PlexPy Notifiers :: Growl notification failed: authentication error") logger.error(u"PlexPy Notifiers :: {name} notification failed: authentication error".format(name=self.NAME))
return False return False
# Fix message # Fix message
@ -1665,10 +1629,10 @@ class GROWL(Notifier):
description=body, description=body,
icon=image icon=image
) )
logger.info(u"PlexPy Notifiers :: Growl notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except gntp.notifier.errors.NetworkError: except gntp.notifier.errors.NetworkError:
logger.warn(u"PlexPy Notifiers :: Growl notification failed: network error") logger.error(u"PlexPy Notifiers :: {name} notification failed: network error".format(name=self.NAME))
return False return False
def return_config_options(self): def return_config_options(self):
@ -1693,6 +1657,7 @@ class HIPCHAT(Notifier):
""" """
Hipchat notifications Hipchat notifications
""" """
NAME = 'Hipchat'
_DEFAULT_CONFIG = {'api_url': '', _DEFAULT_CONFIG = {'api_url': '',
'color': '', 'color': '',
'emoticon': '', 'emoticon': '',
@ -1762,26 +1727,11 @@ class HIPCHAT(Notifier):
data['message'] = text data['message'] = text
data['message_format'] = 'text' data['message_format'] = 'text'
hiphost = urlparse(self.config['api_url']).hostname headers = {'Content-type': 'application/json'}
hipfullq = urlparse(self.config['api_url']).path + '?' + urlparse(self.config['api_url']).query
http_handler = HTTPSConnection(hiphost) r = requests.post(self.config['api_url'], json=data)
http_handler.request("POST",
hipfullq,
headers={'Content-type': "application/json"},
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200 or request_status == 204: return self.notify_success(req=r)
logger.info(u"PlexPy Notifiers :: Hipchat notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Hipchat notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Hipchat notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Hipchat Custom Integrations Full URL', config_option = [{'label': 'Hipchat Custom Integrations Full URL',
@ -1847,6 +1797,7 @@ class IFTTT(Notifier):
""" """
IFTTT notifications IFTTT notifications
""" """
NAME = 'IFTTT'
_DEFAULT_CONFIG = {'key': '', _DEFAULT_CONFIG = {'key': '',
'event': 'plexpy' 'event': 'plexpy'
} }
@ -1860,23 +1811,12 @@ class IFTTT(Notifier):
data = {'value1': subject.encode("utf-8"), data = {'value1': subject.encode("utf-8"),
'value2': body.encode("utf-8")} 'value2': body.encode("utf-8")}
http_handler = HTTPSConnection("maker.ifttt.com") headers = {'Content-type': 'application/json'}
http_handler.request("POST",
"/trigger/%s/with/key/%s" % (event, self.config['key']),
headers={'Content-type': "application/json"},
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.post('https://maker.ifttt.com/trigger/{}/with/key/{}'.format(event, self.config['key']),
logger.info(u"PlexPy Notifiers :: Ifttt notification sent.") headers=headers, json=data)
return True
elif request_status >= 400 and request_status < 500: return self.notify_success(req=r)
logger.warn(u"PlexPy Notifiers :: Ifttt notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Ifttt notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Ifttt Maker Channel Key', config_option = [{'label': 'Ifttt Maker Channel Key',
@ -1905,6 +1845,7 @@ class JOIN(Notifier):
""" """
Join notifications Join notifications
""" """
NAME = 'Join'
_DEFAULT_CONFIG = {'apikey': '', _DEFAULT_CONFIG = {'apikey': '',
'device_id': '', 'device_id': '',
'incl_subject': 1 'incl_subject': 1
@ -1923,51 +1864,42 @@ class JOIN(Notifier):
if self.config['incl_subject']: if self.config['incl_subject']:
data['title'] = subject.encode("utf-8") data['title'] = subject.encode("utf-8")
response = requests.post('https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush', r = requests.post('https://joinjoaomgcd.appspot.com/_ah/api/messaging/v1/sendPush', params=data)
params=data)
request_status = response.status_code
if request_status == 200: if r.status_code == 200:
data = json.loads(response.text) response_data = r.json()
if data.get('success'): if response_data.get('success'):
logger.info(u"PlexPy Notifiers :: Join notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
else: else:
error_msg = data.get('errorMessage') error_msg = response_data.get('errorMessage')
logger.info(u"PlexPy Notifiers :: Join notification failed: %s" % error_msg) logger.error(u"PlexPy Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg))
return False
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Join notification failed: [%s] %s" % (request_status, response.reason))
return False return False
else: else:
logger.warn(u"PlexPy Notifiers :: Join notification failed.") logger.error(u"PlexPy Notifiers :: {name} notification failed: "
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
return False return False
def get_devices(self): def get_devices(self):
if self.config['apikey']: if self.config['apikey']:
http_handler = HTTPSConnection("joinjoaomgcd.appspot.com") params = {'apikey': self.config['apikey']}
http_handler.request("GET",
"/_ah/api/registration/v1/listDevices?%s" % urlencode({'apikey': self.config['apikey']}))
response = http_handler.getresponse() r = requests.get('https://joinjoaomgcd.appspot.com/_ah/api/registration/v1/listDevices', params=params)
request_status = response.status
if request_status == 200: if r.status_code == 200:
data = json.loads(response.read()) response_data = r.json()
if data.get('success'): if response_data.get('success'):
devices = data.get('records', []) devices = response_data.get('records', [])
devices = {d['deviceId']: d['deviceName'] for d in devices} devices = {d['deviceId']: d['deviceName'] for d in devices}
devices.update({'': ''}) devices.update({'': ''})
return devices return devices
else: else:
error_msg = data.get('errorMessage') error_msg = response_data.get('errorMessage')
logger.info(u"PlexPy Notifiers :: Unable to retrieve Join devices list: %s" % error_msg) logger.info(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=error_msg))
return {'': ''}
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Join devices list: %s" % response.reason)
return {'': ''} return {'': ''}
else: else:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Join devices list.") logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: "
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
return {'': ''} return {'': ''}
else: else:
@ -2012,6 +1944,7 @@ class NMA(Notifier):
""" """
Notify My Android notifications Notify My Android notifications
""" """
NAME = 'Notify My Android'
_DEFAULT_CONFIG = {'apikey': '', _DEFAULT_CONFIG = {'apikey': '',
'priority': 0 'priority': 0
} }
@ -2032,12 +1965,12 @@ class NMA(Notifier):
response = p.push(title, subject, body, priority=self.config['priority'], batch_mode=batch) response = p.push(title, subject, body, priority=self.config['priority'], batch_mode=batch)
if not response[self.config['apikey']][u'code'] == u'200': if response[self.config['apikey']][u'code'] == u'200':
logger.warn(u"PlexPy Notifiers :: NotifyMyAndroid notification failed.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return False
else:
logger.info(u"PlexPy Notifiers :: NotifyMyAndroid notification sent.")
return True return True
else:
logger.error(u"PlexPy Notifiers :: {name} notification failed.".format(name=self.NAME))
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'NotifyMyAndroid API Key', config_option = [{'label': 'NotifyMyAndroid API Key',
@ -2062,6 +1995,7 @@ class OSX(Notifier):
""" """
OSX notifications OSX notifications
""" """
NAME = 'OSX Notify'
_DEFAULT_CONFIG = {'notify_app': '/Applications/PlexPy' _DEFAULT_CONFIG = {'notify_app': '/Applications/PlexPy'
} }
@ -2131,13 +2065,13 @@ class OSX(Notifier):
notification_center = NSUserNotificationCenter.defaultUserNotificationCenter() notification_center = NSUserNotificationCenter.defaultUserNotificationCenter()
notification_center.deliverNotification_(notification) notification_center.deliverNotification_(notification)
logger.info(u"PlexPy Notifiers :: OSX Notify notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
del pool del pool
return True return True
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: OSX notification failed: %s" % e) logger.error(u"PlexPy Notifiers :: {name} failed: {e}".format(name=self.NAME, e=e))
return False return False
def return_config_options(self): def return_config_options(self):
@ -2157,6 +2091,7 @@ class PLEX(Notifier):
""" """
Plex Home Theater notifications Plex Home Theater notifications
""" """
NAME = 'Plex Home Theater'
_DEFAULT_CONFIG = {'hosts': '', _DEFAULT_CONFIG = {'hosts': '',
'username': '', 'username': '',
'password': '', 'password': '',
@ -2165,7 +2100,7 @@ class PLEX(Notifier):
} }
def _sendhttp(self, host, command): def _sendhttp(self, host, command):
url_command = urllib.urlencode(command) url_command = urlencode(command)
url = host + '/xbmcCmds/xbmcHttp/?' + url_command url = host + '/xbmcCmds/xbmcHttp/?' + url_command
if self.config['password']: if self.config['password']:
@ -2204,7 +2139,7 @@ class PLEX(Notifier):
image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/favicon.png")) image = os.path.join(plexpy.DATA_DIR, os.path.abspath("data/interfaces/default/images/favicon.png"))
for host in hosts: for host in hosts:
logger.info(u"PlexPy Notifiers :: Sending notification command to Plex Home Theater @ " + host) logger.info(u"PlexPy Notifiers :: Sending notification command to {name} @ {host}".format(name=self.NAME, host=host))
try: try:
version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major'] version = self._sendjson(host, 'Application.GetProperties', {'properties': ['version']})['version']['major']
@ -2220,10 +2155,10 @@ class PLEX(Notifier):
if not request: if not request:
raise Exception raise Exception
else: else:
logger.info(u"PlexPy Notifiers :: Plex Home Theater notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: Plex Home Theater notification failed: %s." % e) logger.error(u"PlexPy Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
return True return True
@ -2268,6 +2203,7 @@ class PROWL(Notifier):
""" """
Prowl notifications. Prowl notifications.
""" """
NAME = 'Prowl'
_DEFAULT_CONFIG = {'keys': '', _DEFAULT_CONFIG = {'keys': '',
'priority': 0 'priority': 0
} }
@ -2282,23 +2218,11 @@ class PROWL(Notifier):
'description': body.encode("utf-8"), 'description': body.encode("utf-8"),
'priority': self.config['priority']} 'priority': self.config['priority']}
http_handler = HTTPSConnection("api.prowlapp.com") headers = {'Content-type': 'application/x-www-form-urlencoded'}
http_handler.request("POST",
"/publicapi/add",
headers={'Content-type': "application/x-www-form-urlencoded"},
body=urlencode(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.post('https://api.prowlapp.com/publicapi/add', headers=headers, data=data)
logger.info(u"PlexPy Notifiers :: Prowl notification sent.")
return True return self.notify_success(req=r)
elif request_status == 401:
logger.warn(u"PlexPy Notifiers :: Prowl notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Prowl notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Prowl API Key', config_option = [{'label': 'Prowl API Key',
@ -2323,6 +2247,7 @@ class PUSHALOT(Notifier):
""" """
Pushalot notifications Pushalot notifications
""" """
NAME = 'Pushalot'
_DEFAULT_CONFIG = {'apikey': '' _DEFAULT_CONFIG = {'apikey': ''
} }
@ -2334,23 +2259,11 @@ class PUSHALOT(Notifier):
'Title': subject.encode('utf-8'), 'Title': subject.encode('utf-8'),
'Body': body.encode("utf-8")} 'Body': body.encode("utf-8")}
http_handler = HTTPSConnection("pushalot.com") headers = {'Content-type': 'application/x-www-form-urlencoded'}
http_handler.request("POST",
"/api/sendmessage",
headers={'Content-type': "application/x-www-form-urlencoded"},
body=urlencode(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.post('https://pushalot.com/api/sendmessage', headers=headers, data=data)
logger.info(u"PlexPy Notifiers :: Pushalot notification sent.")
return True return self.notify_success(req=r)
elif request_status == 410:
logger.warn(u"PlexPy Notifiers :: Pushalot notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Pushalot notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Pushalot API Key', config_option = [{'label': 'Pushalot API Key',
@ -2368,6 +2281,7 @@ class PUSHBULLET(Notifier):
""" """
Pushbullet notifications Pushbullet notifications
""" """
NAME = 'Pushbullet'
_DEFAULT_CONFIG = {'apikey': '', _DEFAULT_CONFIG = {'apikey': '',
'deviceid': '', 'deviceid': '',
'channel_tag': '' 'channel_tag': ''
@ -2377,7 +2291,7 @@ class PUSHBULLET(Notifier):
if not subject or not body: if not subject or not body:
return return
data = {'type': "note", data = {'type': 'note',
'title': subject.encode("utf-8"), 'title': subject.encode("utf-8"),
'body': body.encode("utf-8")} 'body': body.encode("utf-8")}
@ -2387,51 +2301,31 @@ class PUSHBULLET(Notifier):
elif self.config['channel_tag']: elif self.config['channel_tag']:
data['channel_tag'] = self.config['channel_tag'] data['channel_tag'] = self.config['channel_tag']
http_handler = HTTPSConnection("api.pushbullet.com") headers = {'Content-type': 'application/json',
http_handler.request("POST",
"/v2/pushes",
headers={
'Content-type': "application/json",
'Access-Token': self.config['apikey'] 'Access-Token': self.config['apikey']
}, }
body=json.dumps(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.post('https://api.pushbullet.com/v2/pushes', headers=headers, json=data)
logger.info(u"PlexPy Notifiers :: PushBullet notification sent.")
return True return self.notify_success(req=r)
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: PushBullet notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: PushBullet notification failed.")
return False
def get_devices(self): def get_devices(self):
if self.config['apikey']: if self.config['apikey']:
http_handler = HTTPSConnection("api.pushbullet.com") headers={'Content-type': "application/json",
http_handler.request("GET",
"/v2/devices",
headers={
'Content-type': "application/json",
'Access-Token': self.config['apikey'] 'Access-Token': self.config['apikey']
}) }
response = http_handler.getresponse() r = requests.get('https://api.pushbullet.com/v2/devices', headers=headers)
request_status = response.status
if request_status == 200: if r.status_code == 200:
data = json.loads(response.read()) response_data = r.json()
devices = data.get('devices', []) devices = response_data.get('devices', [])
devices = {d['iden']: d['nickname'] for d in devices if d['active']} devices = {d['iden']: d['nickname'] for d in devices if d['active']}
devices.update({'': ''}) devices.update({'': ''})
return devices return devices
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Pushbullet devices list: %s" % response.reason)
return {'': ''}
else: else:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Pushbullet devices list.") logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: "
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
return {'': ''} return {'': ''}
else: else:
@ -2468,6 +2362,7 @@ class PUSHOVER(Notifier):
""" """
Pushover notifications Pushover notifications
""" """
NAME = 'Pushover'
_DEFAULT_CONFIG = {'apitoken': '', _DEFAULT_CONFIG = {'apitoken': '',
'keys': '', 'keys': '',
'html_support': 1, 'html_support': 1,
@ -2503,41 +2398,26 @@ class PUSHOVER(Notifier):
data['url'] = provider_link data['url'] = provider_link
data['url_title'] = caption data['url_title'] = caption
http_handler = HTTPSConnection("api.pushover.net") headers = {'Content-type': 'application/x-www-form-urlencoded'}
http_handler.request("POST",
"/1/messages.json",
headers={'Content-type': "application/x-www-form-urlencoded"},
body=urlencode(data))
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.post('https://api.pushover.net/1/messages.json', headers=headers, data=data)
logger.info(u"PlexPy Notifiers :: Pushover notification sent.")
return True return self.notify_success(req=r)
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Pushover notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Pushover notification failed.")
return False
def get_sounds(self): def get_sounds(self):
if self.config['apitoken']: if self.config['apitoken']:
http_handler = HTTPSConnection("api.pushover.net") params = {'token': self.config['apitoken']}
http_handler.request("GET", "/1/sounds.json?token=" + self.config['apitoken'])
response = http_handler.getresponse()
request_status = response.status
if request_status == 200: r = requests.get('https://api.pushover.net/1/sounds.json', params=params)
data = json.loads(response.read())
sounds = data.get('sounds', {}) if r.status_code == 200:
response_data = r.json()
sounds = response_data.get('sounds', {})
sounds.update({'': ''}) sounds.update({'': ''})
return sounds return sounds
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Pushover notification sounds list: %s" % response.reason)
return {'': ''}
else: else:
logger.warn(u"PlexPy Notifiers :: Unable to retrieve Pushover notification sounds list.") logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} sounds list: "
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
return {'': ''} return {'': ''}
else: else:
@ -2598,6 +2478,7 @@ class SCRIPTS(Notifier):
""" """
Script notifications Script notifications
""" """
NAME = 'Script'
_DEFAULT_CONFIG = {'script_folder': '', _DEFAULT_CONFIG = {'script_folder': '',
'script': '', 'script': '',
'timeout': 30 'timeout': 30
@ -2775,6 +2656,7 @@ class SLACK(Notifier):
""" """
Slack Notifications Slack Notifications
""" """
NAME = 'Slack'
_DEFAULT_CONFIG = {'hook': '', _DEFAULT_CONFIG = {'hook': '',
'channel': '', 'channel': '',
'username': '', 'username': '',
@ -2849,28 +2731,11 @@ class SLACK(Notifier):
data['attachments'] = [attachment] data['attachments'] = [attachment]
host = urlparse(self.config['hook']).hostname headers = {'Content-type': 'application/json'}
port = urlparse(self.config['hook']).port
path = urlparse(self.config['hook']).path
http_handler = HTTPSConnection(host, port) r = requests.post(self.config['hook'], headers=headers, json=data)
http_handler.request("POST",
path,
headers={'Content-type': "application/json"},
body=json.dumps(data))
response = http_handler.getresponse() return self.notify_success(req=r)
request_status = response.status
if request_status == 200:
logger.info(u"PlexPy Notifiers :: Slack notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Slack notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Slack notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Slack Webhook URL', config_option = [{'label': 'Slack Webhook URL',
@ -2942,6 +2807,7 @@ class TELEGRAM(Notifier):
""" """
Telegram notifications Telegram notifications
""" """
NAME = 'Telegram'
_DEFAULT_CONFIG = {'bot_token': '', _DEFAULT_CONFIG = {'bot_token': '',
'chat_id': '', 'chat_id': '',
'disable_web_preview': 0, 'disable_web_preview': 0,
@ -2969,19 +2835,18 @@ class TELEGRAM(Notifier):
poster_url = parameters.get('poster_url','') poster_url = parameters.get('poster_url','')
if poster_url: if poster_url:
files = {'photo': (poster_url, urllib.urlopen(poster_url).read())} poster_request = requests.get(poster_url)
response = requests.post('https://api.telegram.org/bot%s/%s' % (self.config['bot_token'], 'sendPhoto'), poster_content = poster_request.content
data=poster_data,
files=files)
request_status = response.status_code
request_content = json.loads(response.text)
if request_status == 200: files = {'photo': (poster_url, poster_content)}
logger.info(u"PlexPy Notifiers :: Telegram poster sent.")
elif request_status >= 400 and request_status < 500: r = requests.post('https://api.telegram.org/bot{}/sendPhoto'.format(self.config['bot_token']),
logger.warn(u"PlexPy Notifiers :: Telegram poster failed: %s" % request_content.get('description')) data=poster_data, files=files)
if r.status_code == 200:
logger.info(u"PlexPy Notifiers :: {name} poster sent.".format(name=self.NAME))
else: else:
logger.warn(u"PlexPy Notifiers :: Telegram poster failed.") logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=r))
data['text'] = text data['text'] = text
@ -2991,24 +2856,11 @@ class TELEGRAM(Notifier):
if self.config['disable_web_preview']: if self.config['disable_web_preview']:
data['disable_web_page_preview'] = True data['disable_web_page_preview'] = True
http_handler = HTTPSConnection("api.telegram.org") headers = {'Content-type': 'application/x-www-form-urlencoded'}
http_handler.request('POST',
'/bot%s/%s' % (self.config['bot_token'], 'sendMessage'),
headers={'Content-type': 'application/x-www-form-urlencoded'},
body=urlencode(data))
response = http_handler.getresponse() r = requests.post('https://api.telegram.org/bot{}/sendMessage'.format(self.config['bot_token']), headers=headers, data=data)
request_status = response.status
if request_status == 200: return self.notify_success(req=r)
logger.info(u"PlexPy Notifiers :: Telegram notification sent.")
return True
elif request_status >= 400 and request_status < 500:
logger.warn(u"PlexPy Notifiers :: Telegram notification failed: [%s] %s" % (request_status, response.reason))
return False
else:
logger.warn(u"PlexPy Notifiers :: Telegram notification failed.")
return False
def return_config_options(self): def return_config_options(self):
config_option = [{'label': 'Telegram Bot Token', config_option = [{'label': 'Telegram Bot Token',
@ -3060,6 +2912,7 @@ class TWITTER(Notifier):
""" """
Twitter notifications Twitter notifications
""" """
NAME = 'Twitter'
REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token' REQUEST_TOKEN_URL = 'https://api.twitter.com/oauth/request_token'
ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token' ACCESS_TOKEN_URL = 'https://api.twitter.com/oauth/access_token'
AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize' AUTHORIZATION_URL = 'https://api.twitter.com/oauth/authorize'
@ -3084,10 +2937,10 @@ class TWITTER(Notifier):
try: try:
api.PostUpdate(message, media=attachment) api.PostUpdate(message, media=attachment)
logger.info(u"PlexPy Notifiers :: Twitter notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
return True return True
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: Twitter notification failed: %s" % e) logger.error(u"PlexPy Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
def notify(self, subject='', body='', action='', **kwargs): def notify(self, subject='', body='', action='', **kwargs):
@ -3159,6 +3012,7 @@ class XBMC(Notifier):
""" """
XBMC notifications XBMC notifications
""" """
NAME = 'XBMC'
_DEFAULT_CONFIG = {'hosts': '', _DEFAULT_CONFIG = {'hosts': '',
'username': '', 'username': '',
'password': '', 'password': '',
@ -3167,7 +3021,7 @@ class XBMC(Notifier):
} }
def _sendhttp(self, host, command): def _sendhttp(self, host, command):
url_command = urllib.urlencode(command) url_command = urlencode(command)
url = host + '/xbmcCmds/xbmcHttp/?' + url_command url = host + '/xbmcCmds/xbmcHttp/?' + url_command
if self.config['password']: if self.config['password']:
@ -3222,10 +3076,10 @@ class XBMC(Notifier):
if not request: if not request:
raise Exception raise Exception
else: else:
logger.info(u"PlexPy Notifiers :: XBMC notification sent.") logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
except Exception as e: except Exception as e:
logger.warn(u"PlexPy Notifiers :: Plex Home Theater notification failed: %s." % e) logger.error(u"PlexPy Notifiers :: {name} notification failed: {e}".format(name=self.NAME, e=e))
return False return False
return True return True