Add custom modifiers to notification text

This commit is contained in:
JonnyWong16 2017-11-11 18:07:42 -08:00
parent fdff9d7454
commit 718049b9f3
3 changed files with 140 additions and 34 deletions

View file

@ -113,6 +113,7 @@
<div role="tabpanel" class="tab-pane" id="tabs-notify_triggers">
<div class="row">
<div class="col-md-12">
<label>Notification Triggers</label>
<p class="help-block">
Select items that will trigger a notification for this ${notifier['agent_label']} notifiation agent.
</p>
@ -129,6 +130,7 @@
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-notify_conditions">
<label>Notification Conditions</label>
<p class="help-block">
Add custom notification conditions.
<a href="#notify-text-sub-modal" data-toggle="modal">Click here</a> for a description of all the parameters.
@ -152,6 +154,7 @@
</div>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-notify_text">
<label>Notification Text</label>
<p class="help-block">
% if notifier['agent_name'] == 'scripts':
Set the custom arguments passed to the script for each type of notification.
@ -160,6 +163,10 @@
% endif
<a href="#notify-text-sub-modal" data-toggle="modal">Click here</a> for a list of available parameters which can be used.
</p>
<p class="help-block">
You can also add text modifiers to change the case or slice parameters with a list of items.
<a href="#notify-text-modifiers-modal" data-toggle="modal">Click here</a> to view usage information.
</p>
<p class="help-block">
You can also add tags to exclude certain text depending on the media type.
<a href="#notify-text-tags-modal" data-toggle="modal">Click here</a> to view usage information.
@ -219,48 +226,61 @@
</ul>
</div>
<div role="tabpanel" class="tab-pane" id="tabs-test_notifications">
<div class="row">
<div class="col-md-12">
<p class="help-block">
Test if ${notifier['agent_label']} notifications are working. Check the <a href="logs">logs</a> for troubleshooting.
</p>
<p class="help-block">
Note: Test with the real values since parameters will not be substituted.
(i.e. Use <span class="inline-pre">"Game of Thrones"</span> not <span class="inline-pre">{title}</span>)
</p>
% if notifier['agent_name'] == 'scripts':
<div class="form-group">
<label for="test_script">Script</label>
<label>Test Notifications</label>
<p class="help-block">
Test if ${notifier['agent_label']} notifications are working. Check the <a href="logs">logs</a> for troubleshooting.
</p>
<p class="help-block">
Note: Test with the real values since parameters will not be substituted.
(i.e. Use <span class="inline-pre">"Game of Thrones"</span> not <span class="inline-pre">{title}</span>)
</p>
% if notifier['agent_name'] == 'scripts':
<div class="form-group">
<label for="test_script">Script</label>
<div class="row">
<div class="col-md-12">
<select class="form-control" id="test_script" name="test_script">
% for key, value in sorted(notifier['config_options'][2]['select_options'].iteritems()):
<option value="${key}">${value}</option>
% endfor
</select>
<p class="help-block">Choose the script to test.</p>
</div>
<div class="form-group">
<label for="test_script_args">Script Arguments</label>
</div>
<p class="help-block">Choose the script to test.</p>
</div>
<div class="form-group">
<label for="test_script_args">Script Arguments</label>
<div class="row">
<div class="col-md-12">
<input class="form-control" type="text" id="test_script_args" name="test_script_args" value="">
<p class="help-block">Set custom arguments passed to the script.</p>
</div>
% else:
<div class="form-group">
<label for="test_subject">Subject Line</label>
</div>
<p class="help-block">Set custom arguments passed to the script.</p>
</div>
% else:
<div class="form-group">
<label for="test_subject">Subject Line</label>
<div class="row">
<div class="col-md-12">
<input class="form-control" type="text" id="test_subject" name="test_subject" value="PlexPy">
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<label for="test_body">Message Body</label>
</div>
<p class="help-block">Set a custom subject line.</p>
</div>
<div class="form-group">
<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">
<p class="help-block">Set a custom body.</p>
</div>
% endif
<div class="form-group">
<div class="row">
<div class="col-md-8">
<input type="button" class="btn btn-bright" id="test_notifier" name="test_notifier" value="Test ${notifier['agent_label']}">
</div>
</div>
</div>
<p class="help-block">Set a custom body.</p>
</div>
% endif
<div class="form-group">
<div class="row">
<div class="col-md-8">
<input type="button" class="btn btn-bright" id="test_notifier" name="test_notifier" value="Test ${notifier['agent_label']}">
</div>
</div>
</div>

View file

@ -1342,6 +1342,57 @@
</div>
</div>
</div>
<div id="notify-text-modifiers-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notify-text-modifiers-modal">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true"><i class="fa fa-remove"></i></button>
<h4 class="modal-title">Notification Text Modifiers</h4>
</div>
<div class="modal-body">
<div>
<div>
<h4>Case Modifiers</h4>
</div>
<div>
<p class="help-block">Notification parameters with the <span class="inline-pre">!u</span> modifier will be converted to uppercase.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{video_codec} --> hevc
{video_codec!u} --> HEVC</pre>
</div>
<div>
<p class="help-block">Notification parameters with the <span class="inline-pre">!l</span> modifier will be converted to lowercase.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{content_rating} --> TV-PG
{content_rating!l} --> tv-pg</pre>
</div>
<div style="padding-bottom: 10px;">
<p class="help-block">Notification parameters with the <span class="inline-pre">!c</span> modifier will be converted to title case.</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{media_type} --> movie
{media_type!c} --> Movie</pre>
</div>
<div>
<h4>List Slicing</h4>
</div>
<div>
<p class="help-block">
Notification parameters which have a list of items can be sliced with a slice formatter <span class="inline-pre">:[X:Y]</span> to limit the number of items.
Note: the first item in the list is numbered <span class="inline-pre">0</span>.
</p>
<p><strong style="color: #fff;">Example:</strong></p>
<pre>{actors:[0]} --> Only include the 1st actor (Actors: 0)
{actors:[:4]} --> Only the first 4 actors (Actors: 0, 1, 2, 3)
{actors:[2:]} --> Only the 3rd to last actors (Actors: 2, 3, 4, ...)
{actors:[1:5]} --> Only the 2nd to 5th actors (Actors: 1, 2, 3, 4)</pre>
</div>
</div>
</div>
<div class="modal-footer">
</div>
</div>
</div>
</div>
<div id="notifier-text-preview-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="notifier-text-preview-modal">
</div>
<div id="changelog-modal" class="modal fade wide" tabindex="-1" role="dialog" aria-labelledby="changelog-modal">

View file

@ -21,6 +21,7 @@ import json
from operator import itemgetter
import os
import re
from string import Formatter
import threading
import time
@ -911,9 +912,11 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
if test:
return subject, body
custom_formatter = CustomFormatter()
if agent_id == 15:
try:
script_args = [unicode(arg).format(**parameters) for arg in subject.split()]
script_args = [custom_formatter.format(unicode(arg), **parameters) for arg in subject.split()]
except LookupError as e:
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in script argument. Using fallback." % e)
script_args = []
@ -924,7 +927,7 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
script_args = []
try:
subject = unicode(subject).format(**parameters)
subject = custom_formatter.format(unicode(subject), **parameters)
except LookupError as e:
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification subject. Using fallback." % e)
subject = unicode(default_subject).format(**parameters)
@ -933,7 +936,7 @@ def build_notify_text(subject='', body='', notify_action=None, parameters=None,
subject = unicode(default_subject).format(**parameters)
try:
body = unicode(body).format(**parameters)
body = custom_formatter.format(unicode(body), **parameters)
except LookupError as e:
logger.error(u"PlexPy NotificationHandler :: Unable to parse field %s in notification body. Using fallback." % e)
body = unicode(default_body).format(**parameters)
@ -1179,4 +1182,36 @@ def get_themoviedb_info(rating_key=None, media_type=None, themoviedb_id=None):
if req_msg:
logger.debug(u"PlexPy NotificationHandler :: Request response: {}".format(req_msg))
return themoviedb_json
return themoviedb_json
class CustomFormatter(Formatter):
def convert_field(self, value, conversion):
if conversion is None:
return value
elif conversion == 's':
return str(value)
elif conversion == 'r':
return repr(value)
elif conversion == 'u': # uppercase
return str(value).upper()
elif conversion == 'l': # lowercase
return str(value).lower()
elif conversion == 'c': # capitalize
return str(value).title()
else:
return value
def format_field(self, value, format_spec):
if format_spec.startswith('[') and format_spec.endswith(']'):
pattern = re.compile(r'\[(\d*):?(\d*)\]')
if re.match(pattern, format_spec): # slice
items = [x.strip() for x in str(value).split(',')]
slice_start, slice_end = re.search(pattern, format_spec).groups()
slice_start = max(int(slice_start), 0) if slice_start else None
slice_end = min(int(slice_end), len(items)) if slice_end else None
return ', '.join(items[slice_start:slice_end])
else:
return value
else:
return super(CustomFormatter, self).format_field(value, format_spec)