Changeset

6216:2f2539ce8f3b

mod_push2: implement grace period
author Stephen Paul Weber <singpolyma@singpolyma.net>
date Mon, 24 Mar 2025 22:18:47 -0500
parents 6215:e53f0967520c
children 6217:8ecd53452af8
files mod_push2/mod_push2.lua mod_push2/push2.md
diffstat 2 files changed, 25 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/mod_push2/mod_push2.lua	Mon Mar 24 13:01:05 2025 -0500
+++ b/mod_push2/mod_push2.lua	Mon Mar 24 22:18:47 2025 -0500
@@ -44,6 +44,9 @@
 			match.chats[chatel.attr.jid] = chat
 		end
 
+		match.grace = matchel:get_child_text("grace")
+		if match.grace then match.grace = tonumber(match.grace) end
+
 		local send = matchel:get_child("send", "urn:xmpp:push2:send:notify-only:0")
 		if send then
 			match.send = send.attr.xmlns
@@ -367,13 +370,24 @@
 					does_match = stanza:get_child("stana-id", "urn:xmpp:sid:0") and has_body(stanza)
 				end
 
+				local to_user, to_host = jid.split(stanza.attr.to)
+				to_user = to_user or session.username
+				to_host = to_host or module.host
+
+				-- If another session has recent activity within configured grace period, don't send push
+				if does_match and match.grace and to_host == module.host and host_sessions[to_user] then
+					local now = os_time()
+					for _, session in pairs(host_sessions[to_user].sessions) do
+						if session.last_activity and session.push_registration_id ~= push_registration_id and (now - session.last_activity) < match.grace then
+							does_match = false
+						end
+					end
+				end
+
 				local chat = match.chats and (match.chats[stanza.attr.from] or match.chats[jid.bare(stanza.attr.from)] or match.chats[jid.host(stanza.attr.from)])
 				if does_match and chat then
 					does_match = false
 
-					local to_user, to_host = jid.split(stanza.attr.to)
-					to_user = to_user or session.username
-					to_host = to_host or module.host
 					local nick = session.rooms_joined[jid.bare(stanza.attr.from)] or to_user
 
 					if not does_match and chat.mention then
@@ -612,6 +626,11 @@
 
 		handle_notify_request(stanza, to_user, notify_push_services, event.origin, true);
 	end
+
+	-- This is a message the user has sent, indicates activity on a session
+	if event.for_user == jid.node(stanza.attr.from) and module.host == jid.host(stanza.attr.from) then
+		event.origin.last_activity = os_time()
+	end
 end
 
 module:hook("smacks-hibernation-start", hibernate_session);
--- a/mod_push2/push2.md	Mon Mar 24 13:01:05 2025 -0500
+++ b/mod_push2/push2.md	Mon Mar 24 22:18:47 2025 -0500
@@ -15,6 +15,7 @@
     <service>pusher@push.example.com</service>
     <client>https://push.example.com/adlfkjadafdasf</client>
     <match profile="urn:xmpp:push2:match:archived-with-body">
+        <grace>144</grace>
         <chat jid="somemuc@conference.example.com">
             <mention/>
         </chat>
@@ -31,6 +32,8 @@
 
 The optional `<chat/>` child of `<match/>` allows extra filtering of pushes for only specific chats. No specified filters means muted, do not push. `<mention/>` means push on mentions, `<reply/>` means push on replies.
 
+The optional `<grace/>` child of `<match/>` allows specifying a "grace period" in seconds where activity on another session by the same user (such as sending a message) will temporarily pause sending push notifications.
+
 ## Match and send profiles
 
 Different clients and push services have different requirements for push notifications, often due to the differing capabilities of target platforms.