From 315187748804d4095ecd33954380f5e62627fab1 Mon Sep 17 00:00:00 2001 From: Chris Caron Date: Sun, 30 Mar 2025 14:00:23 -0400 Subject: [PATCH] Ntfy.sh Internationalized URL support added for click= (#1312) --- apprise/plugins/ntfy.py | 9 ++++++--- test/test_plugin_ntfy.py | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/apprise/plugins/ntfy.py b/apprise/plugins/ntfy.py index 58d8db6d..070b9165 100644 --- a/apprise/plugins/ntfy.py +++ b/apprise/plugins/ntfy.py @@ -40,7 +40,7 @@ import requests from json import loads from json import dumps from os.path import basename - +from urllib.parse import quote from .base import NotifyBase from ..common import NotifyFormat from ..common import NotifyType @@ -347,7 +347,10 @@ class NotifyNtfy(NotifyBase): self.filename = filename # A clickthrough option for notifications - self.click = click + # Support Internationalized URLs + self.click = None if not isinstance(click, str) else ( + click if not any(ord(char) > 127 for char in click) + else quote(click, safe=':/?&=[]')) # Time delay for notifications (various string formats) self.delay = delay @@ -539,7 +542,7 @@ class NotifyNtfy(NotifyBase): headers['X-Delay'] = self.delay if self.click is not None: - headers['X-Click'] = self.click + headers['X-Click'] = quote(self.click, safe=':/?@&=#') if self.email is not None: headers['X-Email'] = self.email diff --git a/test/test_plugin_ntfy.py b/test/test_plugin_ntfy.py index f2ce8468..d29e452c 100644 --- a/test/test_plugin_ntfy.py +++ b/test/test_plugin_ntfy.py @@ -583,6 +583,46 @@ def test_plugin_ntfy_config_files(mock_post, mock_get): assert obj.url_id() == obj2.url_id() +@mock.patch('requests.post') +def test_plugin_ntfy_internationalized_urls(mock_post): + """ + NotifyNtfy() Internationalized URL Support + + """ + + # Prepare Mock return object + response = mock.Mock() + response.content = GOOD_RESPONSE_TEXT + response.status_code = requests.codes.ok + mock_post.return_value = response + + # Our input + title = 'My Title' + body = 'My Body' + + # Google Translate promised me this just says 'Apprise Example' (I hope + # this is the case 🙏). Below is a URL requiring encoding so that it + # can be correctly passed into an http header: + click = 'https://通知の例' + + # Prepare our object + obj = apprise.Apprise.instantiate(f'ntfy://ntfy.sh/topic1?click={click}') + + # Send our notification + assert obj.notify(title=title, body=body) + assert mock_post.call_count == 1 + + assert mock_post.call_args_list[0][0][0] == 'http://ntfy.sh' + + # Verify that our International URL was correctly escaped + assert 'https://%25E9%2580%259A%25E7%259F' \ + '%25A5%25E3%2581%25AE%25E4%25BE%258B' in \ + mock_post.call_args_list[0][1]['headers']['X-Click'] + + # Validate that we did not obstruct our URL in anyway + assert apprise.Apprise.instantiate(obj.url()).url() == obj.url() + + @mock.patch('requests.post') def test_plugin_ntfy_message_to_attach(mock_post): """