Skip to content

Commit 77b90e9

Browse files
committed
Apprise: Accept omitted/empty addrs attribute
- Improve query parameter serialization - Adjust software tests - Add example for Discord to the documentation - Improve configuration snippets within the documentation
1 parent f4e6e08 commit 77b90e9

File tree

4 files changed

+60
-28
lines changed

4 files changed

+60
-28
lines changed

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ in progress
1010
This helps for service plugins like Apprise to make the configuration
1111
snippet more compact. Now, service configurations can omit the ``targets``
1212
option altogether.
13+
- Apprise service: Accept omitted/empty `addrs` attribute.
14+
- Apprise service: Improve query parameter serialization.
1315

1416

1517
2021-10-17 0.27.0

HANDBOOK.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -529,9 +529,11 @@ This configuration snippet will activate two service plugins
529529
530530
```ini
531531
[defaults]
532-
launch = apprise-mail, apprise-json
532+
launch = apprise-mail, apprise-json, apprise-discord
533533
534534
[config:apprise-mail]
535+
; Submit emails for notifying users.
536+
; https://github.com/caronc/apprise/wiki/Notify_email
535537
module = 'apprise'
536538
baseuri = 'mailtos://smtp_username:[email protected]'
537539
@@ -541,12 +543,22 @@ targets = {
541543
}
542544
543545
[config:apprise-json]
546+
; Post message to HTTP endpoint, in JSON format.
547+
; https://github.com/caronc/apprise/wiki/Notify_Custom_JSON
544548
module = 'apprise'
545549
baseuri = 'json://localhost:1234/mqtthook'
546550
551+
[config:apprise-discord]
552+
; Post message to Discord channel, via Webhook.
553+
; https://github.com/caronc/apprise/wiki/Notify_discord
554+
; https://discord.com/developers/docs/resources/webhook
555+
; discord://{WebhookID}/{WebhookToken}/
556+
module = 'apprise'
557+
baseuri = 'discord://4174216298/JHMHI8qBe7bk2ZwO5U711o3dV_js'
558+
547559
[apprise-test]
548560
topic = apprise/#
549-
targets = apprise-mail:demo, apprise-json
561+
targets = apprise-mail:demo, apprise-json, apprise-discord
550562
format = Alarm from {device}: {payload}
551563
title = Alarm from {device}
552564
```

mqttwarn/services/apprise.py

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
# -*- coding: utf-8 -*-
22

33
__author__ = 'Andreas Motl <[email protected]>'
4-
__copyright__ = 'Copyright 2020 Andreas Motl'
4+
__copyright__ = 'Copyright 2020-2021 Andreas Motl'
55
__license__ = 'Eclipse Public License - v 1.0 (http://www.eclipse.org/legal/epl-v10.html)'
66

77
# https://github.com/caronc/apprise#developers
8+
from urllib.parse import urlencode
9+
from collections import OrderedDict
10+
811
import apprise
912

1013

@@ -13,30 +16,33 @@ def plugin(srv, item):
1316

1417
srv.logging.debug("*** MODULE=%s: service=%s, target=%s", __file__, item.service, item.target)
1518

16-
addresses = item.addrs
17-
18-
if not addresses:
19-
srv.logging.warning("Skipped sending notification to Apprise %s, "
20-
"no addresses configured" % (item.target))
21-
return False
22-
2319
sender = item.config.get('sender')
2420
sender_name = item.config.get('sender_name')
2521
baseuri = item.config['baseuri']
22+
addresses = item.addrs
2623
title = item.title
2724
body = item.message
2825

2926
try:
30-
srv.logging.debug("Sending notification to Apprise %s, addresses: %s" % (item.target, addresses))
27+
srv.logging.debug("Sending notification to Apprise. target=%s, addresses=%s" % (item.target, addresses))
3128
to = ','.join(addresses)
3229

3330
# Create an Apprise instance.
3431
apobj = apprise.Apprise(asset=apprise.AppriseAsset(async_mode=False))
3532

36-
# Add notification services by server url.
37-
uri = '{baseuri}?from={sender}&to={to}'.format(baseuri=baseuri, sender=sender, to=to)
33+
# Collect URL parameters.
34+
params = OrderedDict()
35+
if sender:
36+
params["from"] = sender
37+
if to:
38+
params["to"] = to
3839
if sender_name:
39-
uri += '&name={sender_name}'.format(sender_name=sender_name)
40+
params["name"] = sender_name
41+
42+
# Add notification services by server url.
43+
uri = baseuri
44+
if params:
45+
uri += '?' + urlencode(params)
4046
apobj.add(uri)
4147

4248
# Submit notification.

tests/services/test_apprise.py

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ def test_apprise_success(apprise_asset, apprise_mock, srv, caplog):
3131
assert apprise_mock.mock_calls == [
3232
call(asset=mock.ANY),
3333
call().add(
34-
"mailtos://smtp_username:[email protected]?from=None&to=foo@example.org,bar@example.org"
34+
"mailtos://smtp_username:[email protected]?to=foo%40example.org%2Cbar%40example.org"
3535
),
3636
call().notify(body="⚽ Notification message ⚽", title="⚽ Message title ⚽"),
3737
call().notify().__bool__(),
3838
]
3939

4040
assert outcome is True
4141
assert (
42-
"Sending notification to Apprise test, addresses: ['[email protected]', '[email protected]']"
42+
"Sending notification to Apprise. target=test, addresses=['[email protected]', '[email protected]']"
4343
in caplog.text
4444
)
4545
assert "Successfully sent message using Apprise" in caplog.text
@@ -48,28 +48,40 @@ def test_apprise_success(apprise_asset, apprise_mock, srv, caplog):
4848
@surrogate("apprise")
4949
@mock.patch("apprise.Apprise", create=True)
5050
@mock.patch("apprise.AppriseAsset", create=True)
51-
def test_apprise_failure_no_addresses(apprise_asset, apprise_mock, srv, caplog):
51+
def test_apprise_success_no_addresses(apprise_asset, apprise_mock, srv, caplog):
52+
"""
53+
Some Apprise notifiers don't need any target address information.
54+
Proof that also works by processing an `Item` with no `target`
55+
and `addrs` attributes supplied.
56+
"""
5257

5358
with caplog.at_level(logging.DEBUG):
5459

5560
module = load_module_from_file("mqttwarn/services/apprise.py")
5661

5762
item = Item(
58-
config={"baseuri": "mailtos://smtp_username:[email protected]"},
59-
target="test",
60-
addrs=[],
63+
config={"baseuri": "json://localhost:1234/mqtthook"},
6164
title="⚽ Message title ⚽",
6265
message="⚽ Notification message ⚽",
6366
)
6467

6568
outcome = module.plugin(srv, item)
6669

67-
assert apprise_mock.mock_calls == []
70+
assert apprise_mock.mock_calls == [
71+
call(asset=mock.ANY),
72+
call().add(
73+
"json://localhost:1234/mqtthook"
74+
),
75+
call().notify(body="⚽ Notification message ⚽", title="⚽ Message title ⚽"),
76+
call().notify().__bool__(),
77+
]
6878

69-
assert outcome is False
79+
assert outcome is True
7080
assert (
71-
"Skipped sending notification to Apprise test, no addresses configured" in caplog.text
81+
"Sending notification to Apprise. target=None, addresses=[]"
82+
in caplog.messages
7283
)
84+
assert "Successfully sent message using Apprise" in caplog.messages
7385

7486

7587
@surrogate("apprise")
@@ -106,13 +118,13 @@ def error(*args, **kwargs):
106118
]
107119
assert mock_connection.mock_calls == [
108120
call.add(
109-
"mailtos://smtp_username:[email protected]?from=None&to=foo@example.org,bar@example.org"
121+
"mailtos://smtp_username:[email protected]?to=foo%40example.org%2Cbar%40example.org"
110122
),
111123
]
112124

113125
assert outcome is False
114126
assert (
115-
"Sending notification to Apprise test, addresses: ['[email protected]', '[email protected]']"
127+
"Sending notification to Apprise. target=test, addresses=['[email protected]', '[email protected]']"
116128
in caplog.text
117129
)
118130
assert "Sending message using Apprise failed" in caplog.text
@@ -152,13 +164,13 @@ def error(*args, **kwargs):
152164
]
153165
assert mock_connection.mock_calls == [
154166
call.add(
155-
"mailtos://smtp_username:[email protected]?from=None&to=foo@example.org,bar@example.org"
167+
"mailtos://smtp_username:[email protected]?to=foo%40example.org%2Cbar%40example.org"
156168
),
157169
]
158170

159171
assert outcome is False
160172
assert (
161-
"Sending notification to Apprise test, addresses: ['[email protected]', '[email protected]']"
173+
"Sending notification to Apprise. target=test, addresses=['[email protected]', '[email protected]']"
162174
in caplog.text
163175
)
164176
assert "Error sending message to test: something failed" in caplog.text
@@ -190,7 +202,7 @@ def test_apprise_success_with_sender(apprise_asset, apprise_mock, srv, caplog):
190202
assert apprise_mock.mock_calls == [
191203
call(asset=mock.ANY),
192204
call().add(
193-
"mailtos://smtp_username:[email protected]?from=example@example.org&to=foo@example.org,bar@example.org&name=Max Mustermann"
205+
"mailtos://smtp_username:[email protected]?from=example%40example.org&to=foo%40example.org%2Cbar%40example.org&name=Max+Mustermann"
194206
),
195207
call().notify(body="⚽ Notification message ⚽", title="⚽ Message title ⚽"),
196208
call().notify().__bool__(),

0 commit comments

Comments
 (0)