changeset 4336:6872e55cfb92

mod_cloud_notify_filters: New module to support push notification filters
author Matthew Wild <mwild1@gmail.com>
date Wed, 13 Jan 2021 16:50:47 +0000
parents e03dadd4f2d1
children 83f89ffe427b
files mod_cloud_notify_filters/README.md mod_cloud_notify_filters/mod_cloud_notify_filters.lua
diffstat 2 files changed, 125 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /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.
--- /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);
+