mirror of https://github.com/caronc/apprise
Custom JSON wrapper updated to properly remap keys (#920)
parent
e2f619846d
commit
f799066e0f
|
@ -182,19 +182,6 @@ class NotifyJSON(NotifyBase):
|
||||||
self.logger.warning(msg)
|
self.logger.warning(msg)
|
||||||
raise TypeError(msg)
|
raise TypeError(msg)
|
||||||
|
|
||||||
# A payload map allows users to over-ride the default mapping if
|
|
||||||
# they're detected with the :overide=value. Normally this would
|
|
||||||
# create a new key and assign it the value specified. However
|
|
||||||
# if the key you specify is actually an internally mapped one,
|
|
||||||
# then a re-mapping takes place using the value
|
|
||||||
self.payload_map = {
|
|
||||||
JSONPayloadField.VERSION: JSONPayloadField.VERSION,
|
|
||||||
JSONPayloadField.TITLE: JSONPayloadField.TITLE,
|
|
||||||
JSONPayloadField.MESSAGE: JSONPayloadField.MESSAGE,
|
|
||||||
JSONPayloadField.ATTACHMENTS: JSONPayloadField.ATTACHMENTS,
|
|
||||||
JSONPayloadField.MESSAGETYPE: JSONPayloadField.MESSAGETYPE,
|
|
||||||
}
|
|
||||||
|
|
||||||
self.params = {}
|
self.params = {}
|
||||||
if params:
|
if params:
|
||||||
# Store our extra headers
|
# Store our extra headers
|
||||||
|
@ -205,21 +192,10 @@ class NotifyJSON(NotifyBase):
|
||||||
# Store our extra headers
|
# Store our extra headers
|
||||||
self.headers.update(headers)
|
self.headers.update(headers)
|
||||||
|
|
||||||
self.payload_overrides = {}
|
|
||||||
self.payload_extras = {}
|
self.payload_extras = {}
|
||||||
if payload:
|
if payload:
|
||||||
# Store our extra payload entries
|
# Store our extra payload entries
|
||||||
self.payload_extras.update(payload)
|
self.payload_extras.update(payload)
|
||||||
for key in list(self.payload_extras.keys()):
|
|
||||||
# Any values set in the payload to alter a system related one
|
|
||||||
# alters the system key. Hence :message=msg maps the 'message'
|
|
||||||
# variable that otherwise already contains the payload to be
|
|
||||||
# 'msg' instead (containing the payload)
|
|
||||||
if key in self.payload_map:
|
|
||||||
self.payload_map[key] = self.payload_extras[key].strip()
|
|
||||||
self.payload_overrides[key] = \
|
|
||||||
self.payload_extras[key].strip()
|
|
||||||
del self.payload_extras[key]
|
|
||||||
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
@ -245,8 +221,6 @@ class NotifyJSON(NotifyBase):
|
||||||
# Append our payload extra's into our parameters
|
# Append our payload extra's into our parameters
|
||||||
params.update(
|
params.update(
|
||||||
{':{}'.format(k): v for k, v in self.payload_extras.items()})
|
{':{}'.format(k): v for k, v in self.payload_extras.items()})
|
||||||
params.update(
|
|
||||||
{':{}'.format(k): v for k, v in self.payload_overrides.items()})
|
|
||||||
|
|
||||||
# Determine Authentication
|
# Determine Authentication
|
||||||
auth = ''
|
auth = ''
|
||||||
|
@ -320,22 +294,30 @@ class NotifyJSON(NotifyBase):
|
||||||
self.logger.debug('I/O Exception: %s' % str(e))
|
self.logger.debug('I/O Exception: %s' % str(e))
|
||||||
return False
|
return False
|
||||||
|
|
||||||
# prepare JSON Object
|
# Prepare JSON Object
|
||||||
payload = {}
|
payload = {
|
||||||
for key, value in (
|
JSONPayloadField.VERSION: self.json_version,
|
||||||
(JSONPayloadField.VERSION, self.json_version),
|
JSONPayloadField.TITLE: title,
|
||||||
(JSONPayloadField.TITLE, title),
|
JSONPayloadField.MESSAGE: body,
|
||||||
(JSONPayloadField.MESSAGE, body),
|
JSONPayloadField.ATTACHMENTS: attachments,
|
||||||
(JSONPayloadField.ATTACHMENTS, attachments),
|
JSONPayloadField.MESSAGETYPE: notify_type,
|
||||||
(JSONPayloadField.MESSAGETYPE, notify_type)):
|
}
|
||||||
|
|
||||||
if not self.payload_map[key]:
|
for key, value in self.payload_extras.items():
|
||||||
|
|
||||||
|
if key in payload:
|
||||||
|
if not value:
|
||||||
# Do not store element in payload response
|
# Do not store element in payload response
|
||||||
continue
|
del payload[key]
|
||||||
payload[self.payload_map[key]] = value
|
|
||||||
|
|
||||||
# Apply any/all payload over-rides defined
|
else:
|
||||||
payload.update(self.payload_extras)
|
# Re-map
|
||||||
|
payload[value] = payload[key]
|
||||||
|
del payload[key]
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Append entry
|
||||||
|
payload[key] = value
|
||||||
|
|
||||||
auth = None
|
auth = None
|
||||||
if self.user:
|
if self.user:
|
||||||
|
|
|
@ -295,3 +295,71 @@ def test_notify_json_plugin_attachments(mock_post):
|
||||||
body='body', title='title', notify_type=NotifyType.INFO,
|
body='body', title='title', notify_type=NotifyType.INFO,
|
||||||
attach=attach) is True
|
attach=attach) is True
|
||||||
assert mock_post.call_count == 1
|
assert mock_post.call_count == 1
|
||||||
|
|
||||||
|
|
||||||
|
# Based on incomming webhook details defined here:
|
||||||
|
# https://kb.synology.com/en-au/DSM/help/Chat/chat_integration
|
||||||
|
@mock.patch('requests.post')
|
||||||
|
def test_plugin_custom_form_for_synology(mock_post):
|
||||||
|
"""
|
||||||
|
NotifyJSON() Synology Chat Test Case
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Prepare our response
|
||||||
|
response = requests.Request()
|
||||||
|
response.status_code = requests.codes.ok
|
||||||
|
|
||||||
|
# Prepare Mock
|
||||||
|
mock_post.return_value = response
|
||||||
|
|
||||||
|
# This is rather confusing, it may be easier to leverage the
|
||||||
|
# synology:// and synologys:// plugins instead, but this is just to prove
|
||||||
|
# that the same message can be sent using the json:// plugin.
|
||||||
|
|
||||||
|
results = NotifyJSON.parse_url(
|
||||||
|
'jsons://localhost:8081/webapi/entry.cgi?'
|
||||||
|
'-api=SYNO.Chat.External&-method=incoming&-version=2&-token=abc123'
|
||||||
|
'&:message=text&:version=&:type=&:title=&:attachments'
|
||||||
|
'&:file_url=https://i.redd.it/my2t4d2fx0u31.jpg')
|
||||||
|
|
||||||
|
assert isinstance(results, dict)
|
||||||
|
assert results['user'] is None
|
||||||
|
assert results['password'] is None
|
||||||
|
assert results['port'] == 8081
|
||||||
|
assert results['host'] == 'localhost'
|
||||||
|
assert results['fullpath'] == '/webapi/entry.cgi'
|
||||||
|
assert results['path'] == '/webapi/'
|
||||||
|
assert results['query'] == 'entry.cgi'
|
||||||
|
assert results['schema'] == 'jsons'
|
||||||
|
assert results['url'] == 'jsons://localhost:8081/webapi/entry.cgi'
|
||||||
|
assert isinstance(results['qsd:'], dict) is True
|
||||||
|
# Header Entries
|
||||||
|
assert results['qsd-']['api'] == 'SYNO.Chat.External'
|
||||||
|
assert results['qsd-']['method'] == 'incoming'
|
||||||
|
assert results['qsd-']['version'] == '2'
|
||||||
|
assert results['qsd-']['token'] == 'abc123'
|
||||||
|
|
||||||
|
instance = NotifyJSON(**results)
|
||||||
|
assert isinstance(instance, NotifyJSON)
|
||||||
|
|
||||||
|
response = instance.send(title='title', body='body')
|
||||||
|
assert response is True
|
||||||
|
assert mock_post.call_count == 1
|
||||||
|
|
||||||
|
details = mock_post.call_args_list[0]
|
||||||
|
assert details[0][0] == 'https://localhost:8081/webapi/entry.cgi'
|
||||||
|
|
||||||
|
params = details[1]['params']
|
||||||
|
assert params.get('api') == 'SYNO.Chat.External'
|
||||||
|
assert params.get('method') == 'incoming'
|
||||||
|
assert params.get('version') == '2'
|
||||||
|
assert params.get('token') == 'abc123'
|
||||||
|
|
||||||
|
payload = json.loads(details[1]['data'])
|
||||||
|
assert 'version' not in payload
|
||||||
|
assert 'title' not in payload
|
||||||
|
assert 'message' not in payload
|
||||||
|
assert 'type' not in payload
|
||||||
|
assert payload.get('text') == 'body'
|
||||||
|
assert payload.get('file_url') == 'https://i.redd.it/my2t4d2fx0u31.jpg'
|
||||||
|
|
Loading…
Reference in New Issue