Default body format handling added (#32)

This commit is contained in:
Chris Caron 2020-12-31 13:00:23 -05:00 committed by GitHub
parent 5bbc79e8db
commit 54e8e06fcf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 150 additions and 6 deletions

View File

@ -44,6 +44,15 @@ NOTIFICATION_TYPES = (
(apprise.NotifyType.FAILURE, _('Failure')), (apprise.NotifyType.FAILURE, _('Failure')),
) )
# Define our potential input text categories
INPUT_FORMATS = (
(apprise.NotifyFormat.TEXT, _('TEXT')),
(apprise.NotifyFormat.MARKDOWN, _('MARKDOWN')),
(apprise.NotifyFormat.HTML, _('HTML')),
# As-is - do not interpret it
(None, _('IGNORE')),
)
URLS_MAX_LEN = 1024 URLS_MAX_LEN = 1024
URLS_PLACEHOLDER = 'mailto://user:pass@domain.com, ' \ URLS_PLACEHOLDER = 'mailto://user:pass@domain.com, ' \
'slack://tokena/tokenb/tokenc, ...' 'slack://tokena/tokenb/tokenc, ...'
@ -88,6 +97,13 @@ class NotifyForm(forms.Form):
potential asset information (if yaml file) and tag details. potential asset information (if yaml file) and tag details.
""" """
format = forms.ChoiceField(
label=_('Process As'),
initial=INPUT_FORMATS[0][0],
choices=INPUT_FORMATS,
required=False,
)
type = forms.ChoiceField( type = forms.ChoiceField(
label=_('Type'), label=_('Type'),
choices=NOTIFICATION_TYPES, choices=NOTIFICATION_TYPES,
@ -125,6 +141,16 @@ class NotifyForm(forms.Form):
data = apprise.NotifyType.INFO data = apprise.NotifyType.INFO
return data return data
def clean_format(self):
"""
We just ensure there is a format always set
"""
data = self.cleaned_data['format']
if not data:
# Always set a type
data = apprise.NotifyFormat.TEXT
return data
class NotifyByUrlForm(NotifyForm): class NotifyByUrlForm(NotifyForm):
""" """

View File

@ -64,6 +64,9 @@ class NotifyTests(SimpleTestCase):
# we always set a type if one wasn't done so already # we always set a type if one wasn't done so already
assert form.cleaned_data['type'] == apprise.NotifyType.INFO assert form.cleaned_data['type'] == apprise.NotifyType.INFO
# we always set a format if one wasn't done so already
assert form.cleaned_data['format'] == apprise.NotifyFormat.TEXT
# Send our notification # Send our notification
response = self.client.post( response = self.client.post(
'/notify/{}'.format(key), form.cleaned_data) '/notify/{}'.format(key), form.cleaned_data)
@ -104,6 +107,9 @@ class NotifyTests(SimpleTestCase):
# we always set a type if one wasn't done so already # we always set a type if one wasn't done so already
assert form.cleaned_data['type'] == apprise.NotifyType.INFO assert form.cleaned_data['type'] == apprise.NotifyType.INFO
# we always set a format if one wasn't done so already
assert form.cleaned_data['format'] == apprise.NotifyFormat.TEXT
# Set our return value; first we return a true, then we fail # Set our return value; first we return a true, then we fail
# on the second call # on the second call
mock_notify.side_effect = (True, False) mock_notify.side_effect = (True, False)
@ -225,3 +231,56 @@ class NotifyTests(SimpleTestCase):
# internal errors are correctly identified # internal errors are correctly identified
assert response.status_code == 500 assert response.status_code == 500
assert mock_notify.call_count == 0 assert mock_notify.call_count == 0
# Reset our count
mock_notify.reset_mock()
# Test with invalid format
json_data = {
'body': 'test message',
'format': 'invalid'
}
# Test referencing a key that doesn't exist
response = self.client.post(
'/notify/{}'.format(key),
data=json.dumps(json_data),
content_type='application/json',
)
assert response.status_code == 400
assert mock_notify.call_count == 0
# Reset our count
mock_notify.reset_mock()
# If an empty format is specified, it is accepted and
# no imput format is specified
json_data = {
'body': 'test message',
'format': None,
}
# Test referencing a key that doesn't exist
response = self.client.post(
'/notify/{}'.format(key),
data=json.dumps(json_data),
content_type='application/json',
)
assert response.status_code == 200
assert mock_notify.call_count == 1
# Reset our count
mock_notify.reset_mock()
# Same results for any empty string:
json_data['format'] = ''
response = self.client.post(
'/notify/{}'.format(key),
data=json.dumps(json_data),
content_type='application/json',
)
assert response.status_code == 200
assert mock_notify.call_count == 1

View File

@ -58,6 +58,31 @@ class StatelessNotifyTests(SimpleTestCase):
assert response.status_code == 200 assert response.status_code == 200
assert mock_notify.call_count == 1 assert mock_notify.call_count == 1
# Reset our count
mock_notify.reset_mock()
form_data = {
'urls': 'mailto://user:pass@hotmail.com',
'body': 'test notifiction',
'format': apprise.NotifyFormat.MARKDOWN,
}
form = NotifyByUrlForm(data=form_data)
assert form.is_valid()
response = self.client.post('/notify', form.cleaned_data)
assert response.status_code == 200
assert mock_notify.call_count == 1
# Reset our count
mock_notify.reset_mock()
form_data = {
'urls': 'mailto://user:pass@hotmail.com',
'body': 'test notifiction',
# Invalid formats cause an error
'format': 'invalid'
}
form = NotifyByUrlForm(data=form_data)
assert not form.is_valid()
@patch('apprise.NotifyBase.notify') @patch('apprise.NotifyBase.notify')
def test_partial_notify(self, mock_notify): def test_partial_notify(self, mock_notify):
""" """
@ -202,3 +227,25 @@ class StatelessNotifyTests(SimpleTestCase):
assert response.status_code == 400 assert response.status_code == 400
assert mock_notify.call_count == 0 assert mock_notify.call_count == 0
# Reset our count
mock_notify.reset_mock()
# Preare our JSON data
json_data = {
'urls': 'mailto://user:pass@yahoo.ca',
'body': 'test notifiction',
# invalid server side format
'format': 'invalid'
}
# Send our notification as a JSON object
response = self.client.post(
'/notify',
data=json.dumps(json_data),
content_type='application/json',
)
# Still supported
assert response.status_code == 400
assert mock_notify.call_count == 0

View File

@ -376,6 +376,13 @@ class NotifyView(View):
_('An invalid payload was specified.'), _('An invalid payload was specified.'),
status=ResponseCode.bad_request) status=ResponseCode.bad_request)
# Acquire our body format (if identified)
body_format = content.get('format', apprise.NotifyFormat.TEXT)
if body_format and body_format not in apprise.NOTIFY_FORMATS:
return HttpResponse(
_('An invalid body input format was specified.'),
status=ResponseCode.bad_request)
# If we get here, we have enough information to generate a notification # If we get here, we have enough information to generate a notification
# with. # with.
config, format = ConfigCache.get(key) config, format = ConfigCache.get(key)
@ -400,9 +407,8 @@ class NotifyView(View):
) )
# Prepare ourselves a default Asset # Prepare ourselves a default Asset
asset = apprise.AppriseAsset( asset = None if not body_format else \
body_format=apprise.NotifyFormat.TEXT, apprise.AppriseAsset(body_format=body_format)
)
# Prepare our apprise object # Prepare our apprise object
a_obj = apprise.Apprise(asset=asset) a_obj = apprise.Apprise(asset=asset)
@ -487,10 +493,16 @@ class StatelessNotifyView(View):
_('An invalid payload was specified.'), _('An invalid payload was specified.'),
status=ResponseCode.bad_request) status=ResponseCode.bad_request)
# Acquire our body format (if identified)
body_format = content.get('format', apprise.NotifyFormat.TEXT)
if body_format and body_format not in apprise.NOTIFY_FORMATS:
return HttpResponse(
_('An invalid (body) format was specified.'),
status=ResponseCode.bad_request)
# Prepare ourselves a default Asset # Prepare ourselves a default Asset
asset = apprise.AppriseAsset( asset = None if not body_format else \
body_format=apprise.NotifyFormat.TEXT, apprise.AppriseAsset(body_format=body_format)
)
# Prepare our apprise object # Prepare our apprise object
a_obj = apprise.Apprise(asset=asset) a_obj = apprise.Apprise(asset=asset)