mirror of
https://github.com/Tautulli/Tautulli.git
synced 2025-07-10 23:42:37 -07:00
Add webhook notification agent
This commit is contained in:
parent
9dbb681f22
commit
4648e3df5f
5 changed files with 159 additions and 23 deletions
|
@ -21,7 +21,13 @@
|
|||
<li role="presentation" class="active"><a href="#tabs-notifier_config" aria-controls="tabs-notifier_config" role="tab" data-toggle="tab">Configuration</a></li>
|
||||
<li role="presentation"><a href="#tabs-notify_triggers" aria-controls="tabs-notify_triggers" role="tab" data-toggle="tab">Triggers</a></li>
|
||||
<li role="presentation"><a href="#tabs-notify_conditions" aria-controls="tabs-notify_conditions" role="tab" data-toggle="tab">Conditions</a></li>
|
||||
<li role="presentation"><a href="#tabs-notify_text" aria-controls="tabs-notify_text" role="tab" data-toggle="tab">${'Arguments' if notifier['agent_name'] == 'scripts' else 'Text'}</a></li>
|
||||
% if notifier['agent_name'] == 'scripts':
|
||||
<li role="presentation"><a href="#tabs-notify_text" aria-controls="tabs-notify_text" role="tab" data-toggle="tab">Arguments</a></li>
|
||||
% elif notifier['agent_name'] == 'webhook':
|
||||
<li role="presentation"><a href="#tabs-notify_text" aria-controls="tabs-notify_text" role="tab" data-toggle="tab">Data</a></li>
|
||||
% else:
|
||||
<li role="presentation"><a href="#tabs-notify_text" aria-controls="tabs-notify_text" role="tab" data-toggle="tab">Text</a></li>
|
||||
% endif
|
||||
<li role="presentation"><a href="#tabs-test_notifications" aria-controls="tabs-test_notifications" role="tab" data-toggle="tab">Test Notifications</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -184,6 +190,8 @@
|
|||
<p class="help-block">
|
||||
% if notifier['agent_name'] == 'scripts':
|
||||
Set the custom arguments passed to the script for each type of notification.
|
||||
% elif notifier['agent_name'] == 'webhook':
|
||||
Set the custom JSON data sent to the webhook for each type of notification.
|
||||
% else:
|
||||
Set the custom formatted text for each type of notification.
|
||||
% endif
|
||||
|
@ -225,6 +233,32 @@
|
|||
</ul>
|
||||
</li>
|
||||
% endfor
|
||||
% elif notifier['agent_name'] == 'webhook':
|
||||
% for action in available_notification_actions:
|
||||
<li>
|
||||
<div class="link">
|
||||
<span class="toggle-left"><i class="fa ${action['icon']} fa-fw"></i></span>
|
||||
${action['label']}
|
||||
<span class="toggle-right"><i class="fa fa-chevron-down"></i></span>
|
||||
</div>
|
||||
<ul class="submenu">
|
||||
<li>
|
||||
<div class="form-group">
|
||||
<label for="${action['name']}_body">JSON Data</label>
|
||||
<textarea class="form-control" id="${action['name']}_body" name="${action['name']}_body" data-parsley-trigger="change" data-autoresize required>${notifier['notify_text'][action['name']]['body']}</textarea>
|
||||
<p class="help-block">Set custom JSON data.</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<input type="button" class="btn btn-bright notifier-text-preview" data-action="${action['name']}" value="Preview JSON Data">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
% endfor
|
||||
% else:
|
||||
% for action in available_notification_actions:
|
||||
<li>
|
||||
|
@ -291,6 +325,16 @@
|
|||
</div>
|
||||
<p class="help-block">Set custom arguments passed to the script.</p>
|
||||
</div>
|
||||
% elif notifier['agent_name'] == 'webhook':
|
||||
<div class="form-group">
|
||||
<label for="test_body">JSON Data</label>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<textarea class="form-control" id="test_body" name="test_body" data-autoresize></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block">Set custom JSON data sent to the webhook.</p>
|
||||
</div>
|
||||
% else:
|
||||
<div class="form-group">
|
||||
<label for="test_subject">Subject Line</label>
|
||||
|
@ -305,7 +349,7 @@
|
|||
<label for="test_body">Message Body</label>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<input class="form-control" type="text" id="test_body" name="test_body" value="Test notification">
|
||||
<textarea class="form-control" id="test_body" name="test_body" data-autoresize>Test Notification</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block">Set a custom body.</p>
|
||||
|
|
|
@ -9,7 +9,9 @@
|
|||
% for item in text:
|
||||
<div style="padding-bottom: 10px;">
|
||||
<h4>${item['media_type'].capitalize()}</h4>
|
||||
% if agent != 'webhook':
|
||||
<pre>${item['subject']}</pre>
|
||||
% endif
|
||||
% if agent != 'scripts':
|
||||
<pre>${item['body']}</pre>
|
||||
% endif
|
||||
|
|
|
@ -1115,3 +1115,23 @@ def grouper(iterable, n, fillvalue=None):
|
|||
# grouper('ABCDEFG', 3, 'x') --> ABC DEF Gxx
|
||||
args = [iter(iterable)] * n
|
||||
return izip_longest(fillvalue=fillvalue, *args)
|
||||
|
||||
|
||||
def traverse_map(obj, func):
|
||||
if isinstance(obj, list):
|
||||
new_obj = []
|
||||
for i in obj:
|
||||
new_obj.append(traverse_map(i, func))
|
||||
|
||||
elif isinstance(obj, dict):
|
||||
new_obj = {}
|
||||
for k, v in obj.iteritems():
|
||||
new_obj[traverse_map(k, func)] = traverse_map(v, func)
|
||||
|
||||
elif isinstance(obj, basestring):
|
||||
new_obj = func(obj)
|
||||
|
||||
else:
|
||||
new_obj = obj
|
||||
|
||||
return new_obj
|
||||
|
|
|
@ -1039,6 +1039,7 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
|
|||
# Remove the unwanted tags and strip any unmatch tags too.
|
||||
subject = strip_tag(re.sub(pattern, '', subject), agent_id).strip(' \t\n\r')
|
||||
body = strip_tag(re.sub(pattern, '', body), agent_id).strip(' \t\n\r')
|
||||
script_args = []
|
||||
|
||||
if test:
|
||||
return subject, body
|
||||
|
@ -1055,9 +1056,24 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
|
|||
except Exception as e:
|
||||
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom script arguments: %s. Using fallback." % e)
|
||||
script_args = []
|
||||
else:
|
||||
script_args = []
|
||||
|
||||
elif agent_id == 25:
|
||||
try:
|
||||
body = json.loads(body)
|
||||
except ValueError as e:
|
||||
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook json data: %s. Using fallback." % e)
|
||||
|
||||
try:
|
||||
body = json.dumps(helpers.traverse_map(body,
|
||||
lambda x: custom_formatter.format(x, **parameters).decode(plexpy.SYS_ENCODING, 'ignore')))
|
||||
except LookupError as e:
|
||||
logger.error(u"Tautulli NotificationHandler :: Unable to parse parameter %s in webhook data. Using fallback." % e)
|
||||
body = ''
|
||||
except Exception as e:
|
||||
logger.error(u"Tautulli NotificationHandler :: Unable to parse custom webhook data: %s. Using fallback." % e)
|
||||
body = ''
|
||||
|
||||
else:
|
||||
try:
|
||||
subject = custom_formatter.format(unicode(subject), **parameters)
|
||||
except LookupError as e:
|
||||
|
|
|
@ -91,7 +91,8 @@ AGENT_IDS = {'growl': 0,
|
|||
'androidapp': 21,
|
||||
'groupme': 22,
|
||||
'mqtt': 23,
|
||||
'zapier': 24
|
||||
'zapier': 24,
|
||||
'webhook': 25
|
||||
}
|
||||
|
||||
DEFAULT_CUSTOM_CONDITIONS = [{'parameter': '', 'operator': '', 'value': ''}]
|
||||
|
@ -190,6 +191,10 @@ def available_notification_agents():
|
|||
'name': 'twitter',
|
||||
'id': AGENT_IDS['twitter']
|
||||
},
|
||||
{'label': 'Webhook',
|
||||
'name': 'webhook',
|
||||
'id': AGENT_IDS['webhook']
|
||||
},
|
||||
{'label': 'Zapier',
|
||||
'name': 'zapier',
|
||||
'id': AGENT_IDS['zapier']
|
||||
|
@ -386,6 +391,8 @@ def get_agent_class(agent_id=None, config=None):
|
|||
return MQTT(config=config)
|
||||
elif agent_id == 24:
|
||||
return ZAPIER(config=config)
|
||||
elif agent_id == 25:
|
||||
return WEBHOOK(config=config)
|
||||
else:
|
||||
return Notifier(config=config)
|
||||
else:
|
||||
|
@ -513,7 +520,7 @@ def add_notifier_config(agent_id=None, **kwargs):
|
|||
'custom_conditions_logic': ''
|
||||
}
|
||||
|
||||
if agent['name'] == 'scripts':
|
||||
if agent['name'] in ('scripts', 'webhook'):
|
||||
for a in available_notification_actions():
|
||||
values[a['name'] + '_subject'] = ''
|
||||
values[a['name'] + '_body'] = ''
|
||||
|
@ -774,7 +781,7 @@ class Notifier(object):
|
|||
return self._DEFAULT_CONFIG.copy()
|
||||
|
||||
def notify(self, subject='', body='', action='', **kwargs):
|
||||
if self.NAME != 'Script':
|
||||
if self.NAME not in ('Script', 'Webhook'):
|
||||
if not subject and self.config.get('incl_subject', True):
|
||||
logger.error(u"Tautulli Notifiers :: %s notification subject cannot be blank." % self.NAME)
|
||||
return
|
||||
|
@ -3534,6 +3541,53 @@ class TWITTER(Notifier):
|
|||
return config_option
|
||||
|
||||
|
||||
class WEBHOOK(Notifier):
|
||||
"""
|
||||
Webhook notifications
|
||||
"""
|
||||
NAME = 'Webhook'
|
||||
_DEFAULT_CONFIG = {'hook': '',
|
||||
'method': ''
|
||||
}
|
||||
|
||||
def agent_notify(self, subject='', body='', action='', **kwargs):
|
||||
if body:
|
||||
try:
|
||||
webhook_data = json.loads(body)
|
||||
except ValueError as e:
|
||||
logger.error(u"Tautulli Notifiers :: Invalid {name} json data: {e}".format(name=self.NAME, e=e))
|
||||
return False
|
||||
|
||||
else:
|
||||
webhook_data = None
|
||||
|
||||
headers = {'Content-type': 'application/json'}
|
||||
|
||||
return self.make_request(self.config['hook'], method=self.config['method'], headers=headers, json=webhook_data)
|
||||
|
||||
def return_config_options(self):
|
||||
config_option = [{'label': 'Webhook URL',
|
||||
'value': self.config['hook'],
|
||||
'name': 'webhook_hook',
|
||||
'description': 'Your Webhook URL.',
|
||||
'input_type': 'text'
|
||||
},
|
||||
{'label': 'Webhook Method',
|
||||
'value': self.config['method'],
|
||||
'name': 'webhook_method',
|
||||
'description': 'The Webhook HTTP request method.',
|
||||
'input_type': 'select',
|
||||
'select_options': {'': '',
|
||||
'GET': 'GET',
|
||||
'POST': 'POST',
|
||||
'PUT': 'PUT',
|
||||
'DELETE': 'DELETE'}
|
||||
}
|
||||
]
|
||||
|
||||
return config_option
|
||||
|
||||
|
||||
class XBMC(Notifier):
|
||||
"""
|
||||
Kodi notifications
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue