# HG changeset patch # User Matthew Wild # Date 1610556647 0 # Node ID 6872e55cfb92a6242951e78dc6b01f52b821f5cb # Parent e03dadd4f2d1921c8dfb120410c38b27d99d942e mod_cloud_notify_filters: New module to support push notification filters diff -r e03dadd4f2d1 -r 6872e55cfb92 mod_cloud_notify_filters/README.md --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_cloud_notify_filters/README.md Wed Jan 13 16:50:47 2021 +0000 @@ -0,0 +1,26 @@ +--- +labels: +- 'Stage-Alpha' +summary: 'Support for push notification filtering rules' +... + +Introduction +============ + +This module implements support for a group of [push notification extensions](https://xeps.tigase.net//docs/push-notifications/filters) +by the Tigase team that allow a client to specify filters to be applied to +push notifications. + +It is a custom extension to [XEP-0357: Push Notifications](https://xmpp.org/extensions/xep-0357.html). + +It is planned that this will evolve to a XEP in the near future. + +Details +======= + +Add to modules_enabled, there are no configuration options. + +Compatibility +============= + +Not tested, but hopefully works on 0.11.x and later. diff -r e03dadd4f2d1 -r 6872e55cfb92 mod_cloud_notify_filters/mod_cloud_notify_filters.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_cloud_notify_filters/mod_cloud_notify_filters.lua Wed Jan 13 16:50:47 2021 +0000 @@ -0,0 +1,99 @@ +local jid = require "util.jid"; + +local is_contact_subscribed = require "core.rostermanager".is_contact_subscribed; + +local xmlns_push = "urn:xmpp:push:0"; +local xmlns_push_filter_unknown = "tigase:push:filter:ignore-unknown:0"; +local xmlns_push_filter_muted = "tigase:push:filter:muted:0"; +local xmlns_push_filter_groupchat = "tigase:push:filter:groupchat:0"; +local xmlns_references = "urn:xmpp:reference:0"; + +-- https://xeps.tigase.net//docs/push-notifications/encrypt/#41-discovering-support +local function account_disco_info(event) + event.reply:tag("feature", {var=xmlns_push_filter_unknown}):up(); + event.reply:tag("feature", {var=xmlns_push_filter_muted}):up(); + event.reply:tag("feature", {var=xmlns_push_filter_groupchat}):up(); +end +module:hook("account-disco-info", account_disco_info); + +function handle_register(event) + local enable = event.stanza:get_child("enable", xmlns_push); + + local filter_unknown = enable:get_child("ignore-unknown", xmlns_push_filter_unknown); + if filter_unknown then + event.push_info.filter_unknown = true; + end + + local filter_muted = enable:get_child("muted", xmlns_push_filter_muted); + if filter_muted then + local muted_jids = {}; + for item in filter_muted:childtags("item") do + muted_jids[jid.prep(item.attr.jid)] = true; + end + event.push_info.muted_jids = muted_jids; + end + + local filter_groupchat = enable:get_child("groupchat", xmlns_push_filter_groupchat); + if filter_groupchat then + local groupchat_rules = {}; + for item in filter_groupchat:childtags("room") do + groupchat_rules[jid.prep(item.attr.jid)] = { + when = item.attr.allow; + nick = item.attr.nick; + }; + end + event.push_info.groupchat_rules = groupchat_rules; + end +end + +function handle_push(event) + local push_info = event.push_info; + local stanza = event.original_stanza; + local user_name, user_host = jid.split(stanza.attr.to); + local sender_jid = jid.bare(stanza.attr.from); + + if push_info.filter_unknown then + if user_host == module.host and not is_contact_subscribed(user_name, user_host, sender_jid) then + event.reason = "Filtering: unknown sender"; + return true; + end + end + + if push_info.muted_jids then + if push_info.muted_jids[sender_jid] then + event.reason = "Filtering: muted"; + return true; + end + end + + if stanza.attr.type == "groupchat" and push_info.groupchat_rules then + local rule = push_info.groupchat_rules[sender_jid]; + if rule then + if rule.when == "never" then + event.reason = "Filtering: muted group chat"; + return true; + elseif rule.when == "mentioned" then + local mentioned = false; + local our_uri = "xmpp:"..jid.bare(stanza.attr.to); + local our_muc_uri = rule.nick and "xmpp:"..sender_jid.."/"..rule.nick; + for reference in stanza:childtags("reference", xmlns_references) do + if reference.attr.type == "mention" then + local mention_uri = reference.attr.uri; + if mention_uri == our_uri or mention_uri == our_muc_uri then + mentioned = true; + break; + end + end + end + if not mentioned then + event.reason = "Filtering: not mentioned"; + return true; + end + end + end + end +end + +module:hook("cloud_notify/registration", handle_register); +module:hook("cloud_notify/push", handle_push); +