Skip to content

Commit 1517397

Browse files
Add send_badge_counts option for GCM pushkin (#421)
Co-authored-by: Andrew Morgan <1342360+anoadragon453@users.noreply.github.com>
1 parent da48ba7 commit 1517397

File tree

4 files changed

+76
-4
lines changed

4 files changed

+76
-4
lines changed

changelog.d/421.feature

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add `send_badge_counts` option for FCM/GCM pushkin.

sygnal.yaml.sample

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,15 @@ apps:
212212
# project_id: project-id
213213
# service_account_file: /path/to/service_account.json
214214
#
215+
# # This enables sending the unread message, notification and missed call
216+
# # counts in the push notification data. While this value is useful for non-
217+
# # encrypted contexts, when the user is part of encrypted rooms these
218+
# # count values won't be accurate due to the homeserver being unable
219+
# # to decrypt user and keyword mentions. So there's no point in sending them.
220+
# # If the associated app supports encryption then this should probably be
221+
# # false. Defaults to true.
222+
# #send_badge_counts: false
223+
#
215224
# # This is the maximum number of connections to GCM servers at any one time
216225
# # the default is 20.
217226
# #max_connections: 20

sygnal/gcmpushkin.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class GcmPushkin(ConcurrencyLimitedPushkin):
126126
"max_connections",
127127
"project_id",
128128
"service_account_file",
129+
"send_badge_counts",
129130
} | ConcurrencyLimitedPushkin.UNDERSTOOD_CONFIG_FIELDS
130131

131132
def __init__(self, name: str, sygnal: "Sygnal", config: Dict[str, Any]) -> None:
@@ -538,7 +539,10 @@ async def _dispatch_notification_unlimited(
538539
# TODO: Implement collapse_key to queue only one message per room.
539540
failed: List[str] = []
540541

541-
data = GcmPushkin._build_data(n, device, self.api_version)
542+
send_badge_counts = self.get_config("send_badge_counts", bool, True)
543+
data = GcmPushkin._build_data(
544+
n, device, self.api_version, send_badge_counts
545+
)
542546

543547
# Reject pushkey(s) if default_payload is misconfigured
544548
if data is None:
@@ -651,13 +655,16 @@ def _build_data(
651655
n: Notification,
652656
device: Device,
653657
api_version: APIVersion,
658+
send_badge_counts: bool,
654659
) -> Optional[Dict[str, Any]]:
655660
"""
656661
Build the payload data to be sent.
657662
Args:
658663
n: Notification to build the payload for.
659664
device: Device information to which the constructed payload
660665
will be sent.
666+
api_version: API version used by Firebase/GCM.
667+
send_badge_counts: If set to `True`, will send the unread and missed_call counts.
661668
662669
Returns:
663670
JSON-compatible dict or None if the default_payload is misconfigured
@@ -714,13 +721,15 @@ def _build_data(
714721
if n.prio == "low":
715722
data["prio"] = "normal"
716723

717-
if getattr(n, "counts", None):
724+
if send_badge_counts and getattr(n, "counts", None):
718725
if api_version is APIVersion.Legacy:
719726
data["unread"] = n.counts.unread
720727
data["missed_calls"] = n.counts.missed_calls
721728
elif api_version is APIVersion.V1:
722-
data["unread"] = str(n.counts.unread)
723-
data["missed_calls"] = str(n.counts.missed_calls)
729+
if n.counts.unread:
730+
data["unread"] = str(n.counts.unread)
731+
if n.counts.missed_calls:
732+
data["missed_calls"] = str(n.counts.missed_calls)
724733

725734
if overflow_fields > MAX_NOTIFICATION_OVERFLOW_FIELDS:
726735
logger.warning(

tests/test_gcm.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ def config_setup(self, config: Dict[str, Any]) -> None:
161161
"api_key": "kii",
162162
"fcm_options": {"content_available": True, "mutable_content": True},
163163
}
164+
config["apps"]["fcm-with-disabled-badge-count"] = {
165+
"type": "tests.test_gcm.TestGcmPushkin",
166+
"api_key": "kii",
167+
"fcm_options": {"content_available": True, "mutable_content": True},
168+
# This pusher is specifically testing that this field is `False`.
169+
"send_badge_counts": False,
170+
}
164171
self.service_account_file = tempfile.NamedTemporaryFile()
165172
self.service_account_file.write(FAKE_SERVICE_ACCOUNT_FILE)
166173
self.service_account_file.flush()
@@ -542,6 +549,52 @@ def test_fcm_options(self) -> None:
542549
self.assertEqual(gcm.last_request_body["mutable_content"], True)
543550
self.assertEqual(gcm.last_request_body["content_available"], True)
544551

552+
def test_send_badge_counts(self) -> None:
553+
"""
554+
Tests that the config option `send_badge_counts` being disabled
555+
actually removes the unread and missed call count from notifications
556+
"""
557+
gcm = self.get_test_pushkin("fcm-with-disabled-badge-count")
558+
gcm.preload_with_response(
559+
200, {"results": [{"registration_id": "spqr_new", "message_id": "msg42"}]}
560+
)
561+
562+
resp = self._request(
563+
self._make_dummy_notification(
564+
[
565+
{
566+
"app_id": "fcm-with-disabled-badge-count",
567+
"pushkey": "spqr",
568+
"pushkey_ts": 42,
569+
}
570+
]
571+
)
572+
)
573+
574+
self.assertEqual(resp, {"rejected": []})
575+
assert gcm.last_request_body is not None
576+
577+
# No 'unread' or 'missed_call' fields are present
578+
self.assertEqual(
579+
gcm.last_request_body["data"],
580+
{
581+
"content": {
582+
"body": "I'm floating in a most peculiar way.",
583+
"msgtype": "m.text",
584+
"other": 1,
585+
},
586+
"event_id": "$qTOWWTEL48yPm3uT-gdNhFcoHxfKbZuqRVnnWWSkGBs",
587+
"membership": None,
588+
"prio": "high",
589+
"room_alias": "#exampleroom:matrix.org",
590+
"room_id": "!slw48wfj34rtnrf:example.com",
591+
"room_name": "Mission Control",
592+
"sender": "@exampleuser:matrix.org",
593+
"sender_display_name": "Major Tom",
594+
"type": "m.room.message",
595+
},
596+
)
597+
545598
def test_api_v1_large_fields(self) -> None:
546599
"""
547600
Tests the gcm pushkin truncates unusually large fields. Includes large

0 commit comments

Comments
 (0)