changeset 2141:218a3d3f7f97

mod_cloud_notify: added ability to notify even if the session is hibernated by mod_smacks
author tmolitor <thilo@eightysoft.de>
date Tue, 29 Mar 2016 19:47:08 +0200
parents 3a94b3cd31e2
children d6fbb57a216c
files mod_cloud_notify/README.markdown mod_cloud_notify/mod_cloud_notify.lua
diffstat 2 files changed, 49 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/mod_cloud_notify/README.markdown	Sun Mar 27 16:13:20 2016 +0200
+++ b/mod_cloud_notify/README.markdown	Tue Mar 29 19:47:08 2016 +0200
@@ -28,12 +28,5 @@
 
 Configured in-band by supporting clients.
 
-Future
-======
-
-Adding support for sending notifications for users who are online but
-not currently connected, such as when `mod_smacks` is keeping their
-session alive, should be added.
-
 [^1]: The service which is expected to forward notifications to
     something like Google Cloud Messaging or Apple Notification Service
--- a/mod_cloud_notify/mod_cloud_notify.lua	Sun Mar 27 16:13:20 2016 +0200
+++ b/mod_cloud_notify/mod_cloud_notify.lua	Tue Mar 29 19:47:08 2016 +0200
@@ -6,6 +6,7 @@
 local st = require"util.stanza";
 local jid = require"util.jid";
 local dataform = require"util.dataforms".new;
+local filters = require "util.filters";
 
 local xmlns_push = "urn:xmpp:push:0";
 
@@ -78,8 +79,7 @@
 };
 
 -- http://xmpp.org/extensions/xep-0357.html#publishing
-module:hook("message/offline/handle", function(event)
-	local origin, stanza = event.origin, event.stanza;
+local function handle_notify_request(origin, stanza)
 	local to = stanza.attr.to;
 	local node = to and jid.split(to) or origin.username;
 	local user_push_services = push_enabled[node];
@@ -111,8 +111,55 @@
 		end
 		module:send(push_publish);
 	end
+end
+
+-- publish on offline message
+module:hook("message/offline/handle", function(event)
+	if event.stanza._notify then
+		event.stanza._notify = nil;
+		return;
+	end
+	return handle_notify_request(event.origin, event.stanza);
 end, 1);
 
+-- publish on unacked smacks message
+local function process_new_stanza(stanza, session)
+	if getmetatable(stanza) ~= st.stanza_mt then
+		return stanza; -- Things we don't want to touch
+	end
+	if stanza.name == "message" and stanza.attr.xmlns == nil and
+			( stanza.attr.type == "chat" or ( stanza.attr.type or "normal" ) == "normal" ) and
+			-- not already notified via cloud
+			not stanza._notify then
+		stanza._notify = true;
+		session.log("debug", "Invoking cloud handle_notify_request for new smacks hibernated stanza...");
+		handle_notify_request(session, stanza)
+	end
+	return stanza;
+end
+
+-- smacks hibernation is started
+local function hibernate_session(event)
+	local session = event.origin;
+	local queue = event.queue;
+	-- process already unacked stanzas
+	for i=1,#queue do
+		process_new_stanza(queue[i], session);
+	end
+	-- process future unacked (hibernated) stanzas
+	filters.add_filter(session, "stanzas/out", process_new_stanza);
+end
+
+-- smacks hibernation is ended
+local function restore_session(event)
+	local session = event.origin;
+	filters.remove_filter(session, "stanzas/out", process_new_stanza);
+end
+
+module:hook("smacks-hibernation-start", hibernate_session);
+module:hook("smacks-hibernation-end", restore_session);
+
+
 module:hook("message/offline/broadcast", function(event)
 	local user_push_services = push_enabled[event.origin.username];
 	if not user_push_services then return end