Skip to content

Instantly share code, notes, and snippets.

Created February 7, 2023 17:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Half-Shot/f9501916363894761a1659250aa25181 to your computer and use it in GitHub Desktop.
Save Half-Shot/f9501916363894761a1659250aa25181 to your computer and use it in GitHub Desktop.
Unread room notifs

How unread notifications work

N.B: This may have changed in sliding sync, I haven't looked into it. This covers the present day CS APIs.

In unencrypted rooms, your unread (that is, highlighting rooms in in your room list) notifications are calculated by the server in a field called unread_notifications that appears down sync in two fields.

There are two types of unread notification:

  • Total (notification_count): The number of unread messages in a room that should increment the counter.
  • Highlight (highlight_count): The number of unread messages that have explicitly highlighted you (makes the room go red).

The server calculates these based on your push rules (Yes, unhelpfully named. It's not just used for push).  Push notifications are a different topic and not covered here.

// ...inside a room from the "join" field of a /sync
	"unread_notifications": {
	  "highlight_count": 1,
	  "notification_count": 5
	"unread_thread_notifications": {
	  "$threadroot": {
			"highlight_count": 3,
			"notification_count": 6

This is amazing and great, but not for encrypted rooms...

Encrypted rooms

Encrypted notifications are for the most part calculated clientside, because the server only has very limited access to the content of a event. A server can see an event's room_id, the sender...and that's about all that's really useful. Any push rules that check the content of a message are ignored.

This has mostly been fine for now because most of our encrypted conversations are between humans (that use encrypted messages) and bots (that use unencrypted messages). The result is that:

  • If you don't want to listen to events, you simply set a push rule that disables notifications.
  • If you want to listen for events in a room, the server will always increment the counter for events which are invariably sent by humans.
  • And hightlights are of course never sent by the server, so you can calculate those client-side.
  • And bots will always send messages in the clear text so the server can figure out what to do with them.

And for the most part, that made everyone very happy. We never really had to care about the Total count because it would only increment for effectively messages from humans, or would not increment at all because you silenced the room.

And then, hookshot gained encryption support and with that, we started sending messages that should sometimes be ignored (msgtype=m.notice) in encrypted rooms. This means that the notification_count value would continue to increment for all messages, but sometimes it would be wrong.

Any user with the "Messages sent by bot" setting set to off in their notification settings would get pinged for every message the bot sent, which is understandably quite annoying (we use these things to send webhooks by the 100s into rooms sometimes).

This means that we can no longer rely on the Total count for incrementing the room counter from the server and effectively have to process all messages in encrypted rooms ourselves.

So in conclusion

Which leaves a few open questions:

  • We've built some fairly complex logic in the matrix-js-sdk for processing push rules and handling this, but it's imperative other clients also do this. It's also imperative that other clients do this the same way.
    • To that end, should we be building out some sort of library for dealing with this (hello rust-sdk?)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment