mirror of
https://github.com/caronc/apprise.git
synced 2025-01-20 21:08:38 +01:00
Co-authored-by: phantom <phantom@sictamil.com>
This commit is contained in:
parent
1e4b4355ce
commit
9620901afc
@ -40,6 +40,8 @@ from itertools import chain
|
||||
from .base import NotifyBase
|
||||
from ..common import NotifyType
|
||||
from ..common import NotifyImageSize
|
||||
from ..utils import decode_b64_dict
|
||||
from ..utils import encode_b64_dict
|
||||
from ..utils import validate_regex
|
||||
from ..utils import parse_list
|
||||
from ..utils import parse_bool
|
||||
@ -167,6 +169,12 @@ class NotifyOneSignal(NotifyBase):
|
||||
'default': True,
|
||||
'map_to': 'use_contents',
|
||||
},
|
||||
'decode': {
|
||||
'name': _('Decode Template Args'),
|
||||
'type': 'bool',
|
||||
'default': False,
|
||||
'map_to': 'decode_tpl_args',
|
||||
},
|
||||
'template': {
|
||||
'alias_of': 'template',
|
||||
},
|
||||
@ -195,7 +203,8 @@ class NotifyOneSignal(NotifyBase):
|
||||
|
||||
def __init__(self, app, apikey, targets=None, include_image=True,
|
||||
template=None, subtitle=None, language=None, batch=None,
|
||||
use_contents=None, custom=None, postback=None, **kwargs):
|
||||
use_contents=None, decode_tpl_args=None,
|
||||
custom=None, postback=None, **kwargs):
|
||||
"""
|
||||
Initialize OneSignal
|
||||
|
||||
@ -228,6 +237,11 @@ class NotifyOneSignal(NotifyBase):
|
||||
use_contents if use_contents is not None else
|
||||
self.template_args['contents']['default']) else False
|
||||
|
||||
# Prepare Decode Template Arguments Flag
|
||||
self.decode_tpl_args = True if (
|
||||
decode_tpl_args if decode_tpl_args is not None else
|
||||
self.template_args['decode']['default']) else False
|
||||
|
||||
# Place a thumbnail image inline with the message body
|
||||
self.include_image = include_image
|
||||
|
||||
@ -301,6 +315,9 @@ class NotifyOneSignal(NotifyBase):
|
||||
# Custom Data
|
||||
self.custom_data = {}
|
||||
if custom and isinstance(custom, dict):
|
||||
if self.decode_tpl_args:
|
||||
custom = decode_b64_dict(custom)
|
||||
|
||||
self.custom_data.update(custom)
|
||||
|
||||
elif custom:
|
||||
@ -471,9 +488,12 @@ class NotifyOneSignal(NotifyBase):
|
||||
# Extend our parameters
|
||||
params.update(self.url_parameters(privacy=privacy, *args, **kwargs))
|
||||
|
||||
custom_data, needs_decoding = encode_b64_dict(self.custom_data)
|
||||
# custom_data, needs_decoding = self.custom_data, False
|
||||
# Save our template data
|
||||
params.update(
|
||||
{':{}'.format(k): v for k, v in self.custom_data.items()})
|
||||
{':{}'.format(k): v for k, v in custom_data.items()}
|
||||
)
|
||||
|
||||
# Save our postback data
|
||||
params.update(
|
||||
@ -482,6 +502,11 @@ class NotifyOneSignal(NotifyBase):
|
||||
if self.use_contents != self.template_args['contents']['default']:
|
||||
params['contents'] = 'yes' if self.use_contents else 'no'
|
||||
|
||||
if (self.decode_tpl_args != self.template_args['decode']['default']
|
||||
or needs_decoding):
|
||||
params['decode'] = 'yes' if (self.decode_tpl_args or
|
||||
needs_decoding) else 'no'
|
||||
|
||||
return '{schema}://{tp_id}{app}@{apikey}/{targets}?{params}'.format(
|
||||
schema=self.secure_protocol,
|
||||
tp_id='{}:'.format(
|
||||
@ -568,6 +593,13 @@ class NotifyOneSignal(NotifyBase):
|
||||
'contents',
|
||||
NotifyOneSignal.template_args['contents']['default']))
|
||||
|
||||
# Get Use Contents Boolean (if set)
|
||||
results['decode_tpl_args'] = \
|
||||
parse_bool(
|
||||
results['qsd'].get(
|
||||
'decode',
|
||||
NotifyOneSignal.template_args['decode']['default']))
|
||||
|
||||
# The API Key is stored in the hostname
|
||||
results['apikey'] = NotifyOneSignal.unquote(results['host'])
|
||||
|
||||
|
@ -25,13 +25,15 @@
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import copy
|
||||
import re
|
||||
import sys
|
||||
import json
|
||||
import contextlib
|
||||
import os
|
||||
import locale
|
||||
import typing
|
||||
import base64
|
||||
from itertools import chain
|
||||
from os.path import expanduser
|
||||
from functools import reduce
|
||||
@ -1600,3 +1602,35 @@ def dict_full_update(dict1, dict2):
|
||||
|
||||
_merge(dict1, dict2)
|
||||
return
|
||||
|
||||
|
||||
def decode_b64_dict(di: dict) -> dict:
|
||||
di = copy.deepcopy(di)
|
||||
for k, v in di.items():
|
||||
if not isinstance(v, str) or not v.startswith("b64:"):
|
||||
continue
|
||||
try:
|
||||
parsed_v = base64.b64decode(v[4:])
|
||||
parsed_v = json.loads(parsed_v)
|
||||
except Exception:
|
||||
parsed_v = v
|
||||
di[k] = parsed_v
|
||||
return di
|
||||
|
||||
|
||||
def encode_b64_dict(
|
||||
di: dict
|
||||
) -> typing.Tuple[dict, bool]:
|
||||
di = copy.deepcopy(di)
|
||||
needs_decoding = False
|
||||
for k, v in di.items():
|
||||
if isinstance(v, str):
|
||||
continue
|
||||
try:
|
||||
encoded = base64.urlsafe_b64encode(json.dumps(v).encode())
|
||||
encoded = "b64:{}".format(encoded.decode())
|
||||
needs_decoding = True
|
||||
except Exception:
|
||||
encoded = str(v)
|
||||
di[k] = encoded
|
||||
return di, needs_decoding
|
||||
|
@ -361,3 +361,56 @@ def test_plugin_onesignal_notifications(mock_post):
|
||||
'small_icon': 'https://github.com/caronc/apprise'
|
||||
'/raw/master/apprise/assets/themes/default/apprise-info-32x32.png',
|
||||
'include_external_user_ids': ['@user']}
|
||||
|
||||
# Test without decoding parameters
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=b64:eyJhIjoxLCJiIjoyfQ==&decode=no')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {"par": "b64:eyJhIjoxLCJiIjoyfQ=="}
|
||||
|
||||
# Now same with loading parameters
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=b64:eyJhIjoxLCJiIjoyfQ==&decode=yes')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {"par": {"a": 1, "b": 2}}
|
||||
|
||||
# Test bad data in general
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=garbage1&decode=yes')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {"par": 'garbage1'}
|
||||
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=b64:garbage2&decode=yes')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {"par": 'b64:garbage2'}
|
||||
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=b64:garbage3==&decode=yes')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {"par": 'b64:garbage3=='}
|
||||
|
||||
# Now same with not-base64 parameters
|
||||
instance = Apprise.instantiate(
|
||||
'onesignal://templateid:appid@apikey/@user/'
|
||||
'?:par=eyJhIjoxLCJiIjoyfQ==&:par2=123&decode=yes')
|
||||
assert isinstance(instance, NotifyOneSignal) and \
|
||||
instance.custom_data == {
|
||||
"par": "eyJhIjoxLCJiIjoyfQ==", "par2": "123"
|
||||
}
|
||||
|
||||
# Test incorrect base64 parameters. Second one has incorrect padding
|
||||
url = 'onesignal://templateid:appid@apikey/@user/' \
|
||||
'?:par=b64:1234=&:par2=b64:eyJhIjoxLCJiIjoyfQ&' \
|
||||
':par3=b64:eyJhIjoxLCJiIjoyfQ==&decode=yes'
|
||||
instance = Apprise.instantiate(url)
|
||||
assert isinstance(instance, NotifyOneSignal) and instance.custom_data == {
|
||||
"par": "b64:1234=",
|
||||
"par2": "b64:eyJhIjoxLCJiIjoyfQ",
|
||||
"par3": {"a": 1, "b": 2}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user