mod_cloud_notify/mod_mobile_notify.lua
changeset 1788 1656d4fd71d0
parent 1787 b31fe2d22310
child 1789 a28ed18cb176
equal deleted inserted replaced
1787:b31fe2d22310 1788:1656d4fd71d0
     1 -- XEP-0357: Push (aka: My mobile OS vendor won't let me have persistent TCP connections)
       
     2 -- Copyright (C) 2015 Kim Alvefur
       
     3 --
       
     4 -- This file is MIT/X11 licensed.
       
     5 
       
     6 local st = require"util.stanza";
       
     7 local jid = require"util.jid";
       
     8 local dataform = require"util.dataforms".new;
       
     9 
       
    10 local xmlns_push = "urn:xmpp:push:0";
       
    11 
       
    12 module:add_feature(xmlns_push);
       
    13 
       
    14 local push_enabled = module:shared("push-enabled-users");
       
    15 
       
    16 module:hook("iq-set/self/"..xmlns_push..":enable", function (event)
       
    17 	local origin, stanza = event.origin, event.stanza;
       
    18 	local push_jid, push_node = stanza.tags[1].attr.jid, stanza.tags[1].attr.node;
       
    19 	if not push_jid or not push_node then
       
    20 		origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing jid or node"));
       
    21 		return true;
       
    22 	end
       
    23 	local publish_options = stanza.tags[1].tags[1];
       
    24 	if publish_options and ( publish_options.name ~= "x" or publish_options.attr.xmlns ~= "jabber:x:data" ) then
       
    25 		origin.send(st.error_reply(stanza, "modify", "bad-request", "Invalid publish options"));
       
    26 		return true;
       
    27 	end
       
    28 	local user_push_services = push_enabled[origin.username];
       
    29 	if not user_push_services then
       
    30 		user_push_services = {};
       
    31 	end
       
    32 	user_push_services[push_jid .. "<" .. push_node] = {
       
    33 		jid = push_jid;
       
    34 		node = push_node;
       
    35 		count = 0;
       
    36 		options = publish_options;
       
    37 	};
       
    38 	origin.send(st.reply(stanza));
       
    39 	return true;
       
    40 end);
       
    41 
       
    42 module:hook("iq-set/self/"..xmlns_push..":disable", function (event)
       
    43 	local origin, stanza = event.origin, event.stanza;
       
    44 	local push_jid, push_node = stanza.tags[1].attr.jid, stanza.tags[1].attr.node;
       
    45 	if not push_jid or not push_node then
       
    46 		origin.send(st.error_reply(stanza, "modify", "bad-request", "Missing jid or node"));
       
    47 		return true;
       
    48 	end
       
    49 	local user_push_services = push_enabled[origin.username];
       
    50 	if user_push_services then
       
    51 		user_push_services[push_jid .. "<" .. push_node] = nil;
       
    52 	end
       
    53 	origin.send(st.reply(stanza));
       
    54 	return true;
       
    55 end);
       
    56 
       
    57 local push_form = dataform {
       
    58 	{ name = "FORM_TYPE"; type = "hidden"; value = "urn:xmpp:push:summary"; };
       
    59 	{ name = "message-count"; type = "text-single"; };
       
    60 	{ name = "pending-subscription-count"; type = "text-single"; };
       
    61 	{ name = "last-message-sender"; type = "jid-single"; };
       
    62 	{ name = "last-message-body"; type = "text-single"; };
       
    63 };
       
    64 
       
    65 module:hook("message/offline/handle", function(event)
       
    66 	local origin, stanza = event.origin, event.stanza;
       
    67 	local to = stanza.attr.to;
       
    68 	local node = to and jid.split(to) or origin.username;
       
    69 	local user_push_services = push_enabled[origin.username];
       
    70 	if not user_push_services then return end
       
    71 
       
    72 	for _, push_info in pairs(push_info) do
       
    73 		push_info.count = push_info.count + 1;
       
    74 		local push_jid, push_node = push_info.jid, push_info.node;
       
    75 		local push_publish = st.iq({ to = push_jid, from = module.host, type = "set", id = "push" })
       
    76 			:tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" })
       
    77 				:tag("publish", { node = push_node });
       
    78 		push_publish:add_child(push_form:form({
       
    79 			["message-count"] = tostring(push_info.count);
       
    80 			["last-message-sender"] = stanza.attr.from;
       
    81 			["last-message-body"] = stanza:get_child_text("body");
       
    82 		}));
       
    83 		push_publish:up(); -- / publish
       
    84 		if push_info.options then
       
    85 			push_publish:tag("publish-options"):add_child(push_info.options);
       
    86 		end
       
    87 		module:send(push_publish);
       
    88 	end
       
    89 end, 1);
       
    90 
       
    91 module:hook("message/offline/broadcast", function(event)
       
    92 	local user_push_services = push_enabled[origin.username];
       
    93 	if not user_push_services then return end
       
    94 
       
    95 	for _, push_info in pairs(push_info) do
       
    96 		if push_info then
       
    97 			push_info.count = 0;
       
    98 		end
       
    99 	end
       
   100 end, 1);