mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-15 09:42:57 -07:00
Refactor notifier requests and better logging
This commit is contained in:
parent
6f0c650a72
commit
dc25ef857f
2 changed files with 132 additions and 59 deletions
|
@ -686,15 +686,27 @@ class Notifier(object):
|
|||
def notify(self, subject='', body='', action='', **kwargs):
|
||||
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 make_request(self, url, method='POST', **kwargs):
|
||||
response, err_msg, req_msg = request.request_response2(url, method, **kwargs)
|
||||
|
||||
if response and not err_msg:
|
||||
logger.info(u"PlexPy Notifiers :: {name} notification sent.".format(name=self.NAME))
|
||||
return True
|
||||
|
||||
else:
|
||||
verify_msg = ""
|
||||
if response is not None and response.status_code >= 400 and response.status_code < 500:
|
||||
verify_msg = " Verify you notification agent settings are correct."
|
||||
|
||||
logger.error(u"PlexPy Notifiers :: {name} notification failed.{}".format(verify_msg, name=self.NAME))
|
||||
|
||||
if err_msg:
|
||||
logger.error(u"PlexPy Notifiers :: {}".format(err_msg))
|
||||
|
||||
if req_msg:
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(req_msg))
|
||||
|
||||
return False
|
||||
|
||||
def return_config_options(self):
|
||||
config_options = []
|
||||
|
@ -784,11 +796,7 @@ class ANDROIDAPP(Notifier):
|
|||
|
||||
headers = {'Content-Type': 'application/json'}
|
||||
|
||||
r = requests.post("https://onesignal.com/api/v1/notifications", headers=headers, json=payload)
|
||||
|
||||
#logger.debug("OneSignal response: {}".format(r.content))
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request("https://onesignal.com/api/v1/notifications", headers=headers, json=payload)
|
||||
|
||||
def get_devices(self):
|
||||
db = database.MonitorDatabase()
|
||||
|
@ -889,9 +897,7 @@ class BOXCAR(Notifier):
|
|||
'notification[sound]': self.config['sound']
|
||||
}
|
||||
|
||||
r = requests.post('https://new.boxcar.io/api/notifications', params=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://new.boxcar.io/api/notifications', params=data)
|
||||
|
||||
def get_sounds(self):
|
||||
sounds = {'': '',
|
||||
|
@ -1087,9 +1093,7 @@ class DISCORD(Notifier):
|
|||
headers = {'Content-type': 'application/json'}
|
||||
params = {'wait': True}
|
||||
|
||||
r = requests.post(self.config['hook'], params=params, headers=headers, json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request(self.config['hook'], params=params, headers=headers, json=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Discord Webhook URL',
|
||||
|
@ -1530,12 +1534,11 @@ class GROUPME(Notifier):
|
|||
data['attachments'] = [{'type': 'image',
|
||||
'url': r_content['payload']['picture_url']}]
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=r))
|
||||
logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
return False
|
||||
|
||||
r = requests.post('https://api.groupme.com/v3/bots/post', json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://api.groupme.com/v3/bots/post', json=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'GroupMe Access Token',
|
||||
|
@ -1731,9 +1734,7 @@ class HIPCHAT(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/json'}
|
||||
|
||||
r = requests.post(self.config['api_url'], json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request(self.config['api_url'], json=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Hipchat Custom Integrations Full URL',
|
||||
|
@ -1815,10 +1816,8 @@ class IFTTT(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/json'}
|
||||
|
||||
r = requests.post('https://maker.ifttt.com/trigger/{}/with/key/{}'.format(event, self.config['key']),
|
||||
headers=headers, json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://maker.ifttt.com/trigger/{}/with/key/{}'.format(event, self.config['key']),
|
||||
headers=headers, json=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Ifttt Maker Channel Key',
|
||||
|
@ -1878,8 +1877,8 @@ class JOIN(Notifier):
|
|||
logger.error(u"PlexPy Notifiers :: {name} notification failed: {msg}".format(name=self.NAME, msg=error_msg))
|
||||
return False
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: {name} notification failed: "
|
||||
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
|
||||
logger.error(u"PlexPy Notifiers :: {name} notification failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
return False
|
||||
|
||||
def get_devices(self):
|
||||
|
@ -1900,8 +1899,8 @@ class JOIN(Notifier):
|
|||
logger.info(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: {msg}".format(name=self.NAME, msg=error_msg))
|
||||
return {'': ''}
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: "
|
||||
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
return {'': ''}
|
||||
|
||||
else:
|
||||
|
@ -2222,9 +2221,7 @@ class PROWL(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
r = requests.post('https://api.prowlapp.com/publicapi/add', headers=headers, data=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://api.prowlapp.com/publicapi/add', headers=headers, data=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Prowl API Key',
|
||||
|
@ -2263,9 +2260,7 @@ class PUSHALOT(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
r = requests.post('https://pushalot.com/api/sendmessage', headers=headers, data=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://pushalot.com/api/sendmessage', headers=headers, data=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Pushalot API Key',
|
||||
|
@ -2307,9 +2302,7 @@ class PUSHBULLET(Notifier):
|
|||
'Access-Token': self.config['apikey']
|
||||
}
|
||||
|
||||
r = requests.post('https://api.pushbullet.com/v2/pushes', headers=headers, json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://api.pushbullet.com/v2/pushes', headers=headers, json=data)
|
||||
|
||||
def get_devices(self):
|
||||
if self.config['apikey']:
|
||||
|
@ -2326,8 +2319,8 @@ class PUSHBULLET(Notifier):
|
|||
devices.update({'': ''})
|
||||
return devices
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: "
|
||||
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} devices list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
return {'': ''}
|
||||
|
||||
else:
|
||||
|
@ -2402,9 +2395,7 @@ class PUSHOVER(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
r = requests.post('https://api.pushover.net/1/messages.json', headers=headers, data=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://api.pushover.net/1/messages.json', headers=headers, data=data)
|
||||
|
||||
def get_sounds(self):
|
||||
if self.config['apitoken']:
|
||||
|
@ -2418,8 +2409,8 @@ class PUSHOVER(Notifier):
|
|||
sounds.update({'': ''})
|
||||
return sounds
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} sounds list: "
|
||||
"[{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=req))
|
||||
logger.error(u"PlexPy Notifiers :: Unable to retrieve {name} sounds list: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
return {'': ''}
|
||||
|
||||
else:
|
||||
|
@ -2735,9 +2726,7 @@ class SLACK(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/json'}
|
||||
|
||||
r = requests.post(self.config['hook'], headers=headers, json=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request(self.config['hook'], headers=headers, json=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Slack Webhook URL',
|
||||
|
@ -2848,7 +2837,8 @@ class TELEGRAM(Notifier):
|
|||
if r.status_code == 200:
|
||||
logger.info(u"PlexPy Notifiers :: {name} poster sent.".format(name=self.NAME))
|
||||
else:
|
||||
logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}: {r.text}".format(name=self.NAME, r=r))
|
||||
logger.error(u"PlexPy Notifiers :: {name} poster failed: [{r.status_code}] {r.reason}".format(name=self.NAME, r=r))
|
||||
logger.debug(u"PlexPy Notifiers :: Request response: {}".format(request.server_message(r, True)))
|
||||
|
||||
data['text'] = text
|
||||
|
||||
|
@ -2860,9 +2850,7 @@ class TELEGRAM(Notifier):
|
|||
|
||||
headers = {'Content-type': 'application/x-www-form-urlencoded'}
|
||||
|
||||
r = requests.post('https://api.telegram.org/bot{}/sendMessage'.format(self.config['bot_token']), headers=headers, data=data)
|
||||
|
||||
return self.notify_success(req=r)
|
||||
return self.make_request('https://api.telegram.org/bot{}/sendMessage'.format(self.config['bot_token']), headers=headers, data=data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Telegram Bot Token',
|
||||
|
|
|
@ -120,6 +120,88 @@ def request_response(url, method="get", auto_raise=True,
|
|||
logger.error("Request raised exception: %s", e)
|
||||
|
||||
|
||||
def request_response2(url, method="get", auto_raise=True,
|
||||
whitelist_status_code=None, lock=fake_lock, **kwargs):
|
||||
"""
|
||||
Convenient wrapper for `requests.get', which will capture the exceptions
|
||||
and log them. On success, the Response object is returned. In case of a
|
||||
exception, None is returned.
|
||||
|
||||
Additionally, there is support for rate limiting. To use this feature,
|
||||
supply a tuple of (lock, request_limit). The lock is used to make sure no
|
||||
other request with the same lock is executed. The request limit is the
|
||||
minimal time between two requests (and so 1/request_limit is the number of
|
||||
requests per seconds).
|
||||
"""
|
||||
|
||||
# Convert whitelist_status_code to a list if needed
|
||||
if whitelist_status_code and type(whitelist_status_code) != list:
|
||||
whitelist_status_code = [whitelist_status_code]
|
||||
|
||||
# Disable verification of SSL certificates if requested. Note: this could
|
||||
# pose a security issue!
|
||||
kwargs['verify'] = bool(plexpy.CONFIG.VERIFY_SSL_CERT)
|
||||
|
||||
# Map method to the request.XXX method. This is a simple hack, but it
|
||||
# allows requests to apply more magic per method. See lib/requests/api.py.
|
||||
request_method = getattr(requests, method.lower())
|
||||
|
||||
response = None
|
||||
err_msg = http_err = req_msg = None
|
||||
|
||||
try:
|
||||
with lock:
|
||||
response = request_method(url, **kwargs)
|
||||
|
||||
# If status code != OK, then raise exception, except if the status code
|
||||
# is white listed.
|
||||
if whitelist_status_code and auto_raise:
|
||||
if response.status_code not in whitelist_status_code:
|
||||
try:
|
||||
response.raise_for_status()
|
||||
except:
|
||||
raise
|
||||
elif auto_raise:
|
||||
response.raise_for_status()
|
||||
|
||||
except requests.exceptions.SSLError as e:
|
||||
if kwargs["verify"]:
|
||||
err_msg = "Unable to connect to remote host because of a SSL error."
|
||||
else:
|
||||
err_msg = "Unable to connect to remote host because of a SSL error, " \
|
||||
"with certificate verification turned off: {}".format(e)
|
||||
|
||||
except requests.ConnectionError:
|
||||
err_msg = "Unable to connect to remote host. Check if the remote host is up and running."
|
||||
|
||||
except requests.Timeout:
|
||||
err_msg = "Request to the remote host timed out."
|
||||
|
||||
except requests.HTTPError as e:
|
||||
if e.response is not None:
|
||||
if e.response.status_code >= 500:
|
||||
http_err = "[{e.response.status_code}] {e.response.reason} (remote server error).".format(e=e)
|
||||
|
||||
elif e.response.status_code >= 400:
|
||||
http_err = "[{e.response.status_code}] {e.response.reason} (local client error).".format(e=e)
|
||||
|
||||
else:
|
||||
http_err = "Unknown HTTP error."
|
||||
|
||||
err_msg = "Request raised a HTTP error: {}".format(http_err)
|
||||
|
||||
if plexpy.VERBOSE:
|
||||
req_msg = server_message(e.response, return_msg=True)
|
||||
|
||||
else:
|
||||
err_msg = "Request raised a HTTP error: Unknown response."
|
||||
|
||||
except requests.RequestException as e:
|
||||
err_msg = "Request raised an exception: {}".format(e)
|
||||
|
||||
return response, err_msg, req_msg
|
||||
|
||||
|
||||
def request_soup(url, **kwargs):
|
||||
"""
|
||||
Wrapper for `request_response', which will return a BeatifulSoup object if
|
||||
|
@ -195,7 +277,7 @@ def request_feed(url, **kwargs):
|
|||
return feedparser.parse(response.content)
|
||||
|
||||
|
||||
def server_message(response):
|
||||
def server_message(response, return_msg=False):
|
||||
"""
|
||||
Extract server message from response and log in to logger with DEBUG level.
|
||||
|
||||
|
@ -235,4 +317,7 @@ def server_message(response):
|
|||
if len(message) > 150:
|
||||
message = message[:150] + "..."
|
||||
|
||||
if return_msg:
|
||||
return message
|
||||
|
||||
logger.debug("Server responded with message: %s", message)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue