Software /
code /
prosody-modules
Comparison
mod_cloud_notify/mod_cloud_notify.lua @ 3943:f5e6368a1c39
mod_cloud_notify: Cleanup code and drop support for prosody 0.9
This removes some legacy stuff that was needed for prosody 0.9
We now use util.stanza:find instead of our own patched version to be more mainstream
The unneeded module unloading code was removed, too
author | tmolitor <thilo@eightysoft.de> |
---|---|
date | Wed, 11 Mar 2020 20:00:50 +0100 |
parent | 3940:675726ab06d3 |
child | 3979:6bf362008052 |
comparison
equal
deleted
inserted
replaced
3942:e93e58b33bf6 | 3943:f5e6368a1c39 |
---|---|
12 local st = require"util.stanza"; | 12 local st = require"util.stanza"; |
13 local jid = require"util.jid"; | 13 local jid = require"util.jid"; |
14 local dataform = require"util.dataforms".new; | 14 local dataform = require"util.dataforms".new; |
15 local filters = require"util.filters"; | 15 local filters = require"util.filters"; |
16 local hashes = require"util.hashes"; | 16 local hashes = require"util.hashes"; |
17 local random = require"util.random"; | |
18 local cache = require"util.cache"; | |
17 | 19 |
18 local xmlns_push = "urn:xmpp:push:0"; | 20 local xmlns_push = "urn:xmpp:push:0"; |
19 | 21 |
20 -- configuration | 22 -- configuration |
21 local include_body = module:get_option_boolean("push_notification_with_body", false); | 23 local include_body = module:get_option_boolean("push_notification_with_body", false); |
25 local dummy_body = module:get_option_string("push_notification_important_body", "New Message!"); | 27 local dummy_body = module:get_option_string("push_notification_important_body", "New Message!"); |
26 | 28 |
27 local host_sessions = prosody.hosts[module.host].sessions; | 29 local host_sessions = prosody.hosts[module.host].sessions; |
28 local push_errors = {}; | 30 local push_errors = {}; |
29 local id2node = {}; | 31 local id2node = {}; |
30 | 32 local id2identifier = {}; |
31 -- ordered table iterator, allow to iterate on the natural order of the keys of a table, | |
32 -- see http://lua-users.org/wiki/SortedIteration | |
33 local function __genOrderedIndex( t ) | |
34 local orderedIndex = {} | |
35 for key in pairs(t) do | |
36 table.insert( orderedIndex, key ) | |
37 end | |
38 -- sort in reverse order (newest one first) | |
39 table.sort( orderedIndex, function(a, b) | |
40 if a == nil or t[a] == nil or b == nil or t[b] == nil then return false end | |
41 -- only one timestamp given, this is the newer one | |
42 if t[a].timestamp ~= nil and t[b].timestamp == nil then return true end | |
43 if t[a].timestamp == nil and t[b].timestamp ~= nil then return false end | |
44 -- both timestamps given, sort normally | |
45 if t[a].timestamp ~= nil and t[b].timestamp ~= nil then return t[a].timestamp > t[b].timestamp end | |
46 return false -- normally not reached | |
47 end) | |
48 return orderedIndex | |
49 end | |
50 local function orderedNext(t, state) | |
51 -- Equivalent of the next function, but returns the keys in timestamp | |
52 -- order. We use a temporary ordered key table that is stored in the | |
53 -- table being iterated. | |
54 | |
55 local key = nil | |
56 --print("orderedNext: state = "..tostring(state) ) | |
57 if state == nil then | |
58 -- the first time, generate the index | |
59 t.__orderedIndex = __genOrderedIndex( t ) | |
60 key = t.__orderedIndex[1] | |
61 else | |
62 -- fetch the next value | |
63 for i = 1, #t.__orderedIndex do | |
64 if t.__orderedIndex[i] == state then | |
65 key = t.__orderedIndex[i+1] | |
66 end | |
67 end | |
68 end | |
69 | |
70 if key then | |
71 return key, t[key] | |
72 end | |
73 | |
74 -- no more value to return, cleanup | |
75 t.__orderedIndex = nil | |
76 return | |
77 end | |
78 local function orderedPairs(t) | |
79 -- Equivalent of the pairs() function on tables. Allows to iterate | |
80 -- in order | |
81 return orderedNext, t, nil | |
82 end | |
83 | |
84 -- small helper function to return new table with only "maximum" elements containing only the newest entries | |
85 local function reduce_table(table, maximum) | |
86 local count = 0; | |
87 local result = {}; | |
88 for key, value in orderedPairs(table) do | |
89 count = count + 1; | |
90 if count > maximum then break end | |
91 result[key] = value; | |
92 end | |
93 return result; | |
94 end | |
95 | |
96 local function stoppable_timer(delay, callback) | |
97 local stopped = false; | |
98 local timer = module:add_timer(delay, function (t) | |
99 if stopped then return; end | |
100 return callback(t); | |
101 end); | |
102 if timer and timer.stop then return timer; end -- new prosody api includes stop() function | |
103 return { | |
104 stop = function(self) stopped = true end; | |
105 timer; | |
106 }; | |
107 end | |
108 | 33 |
109 -- For keeping state across reloads while caching reads | 34 -- For keeping state across reloads while caching reads |
35 -- This uses util.cache for caching the most recent devices and removing all old devices when max_push_devices is reached | |
110 local push_store = (function() | 36 local push_store = (function() |
111 local store = module:open_store(); | 37 local store = module:open_store(); |
112 local push_services = {}; | 38 local push_services = {}; |
113 local api = {}; | 39 local api = {}; |
114 function api:get(user) | 40 function api:get(user) |
115 if not push_services[user] then | 41 if not push_services[user] then |
116 local err; | 42 local loaded, err = store:get(user); |
117 push_services[user], err = store:get(user); | 43 if not loaded and err then |
118 if not push_services[user] and err then | |
119 module:log("warn", "Error reading push notification storage for user '%s': %s", user, tostring(err)); | 44 module:log("warn", "Error reading push notification storage for user '%s': %s", user, tostring(err)); |
120 push_services[user] = {}; | 45 push_services[user] = cache.new(max_push_devices):table(); |
121 return push_services[user], false; | 46 return push_services[user], false; |
122 end | 47 end |
123 end | 48 if loaded then |
124 if not push_services[user] then push_services[user] = {} end | 49 push_services[user] = cache.new(max_push_devices):table(); |
50 -- copy over plain table loaded from disk into our cache | |
51 for k, v in pairs(loaded) do push_services[user][k] = v; end | |
52 else | |
53 push_services[user] = cache.new(max_push_devices):table(); | |
54 end | |
55 end | |
125 return push_services[user], true; | 56 return push_services[user], true; |
126 end | 57 end |
127 function api:set(user, data) | 58 function api:flush_to_disk(user) |
128 push_services[user] = reduce_table(data, max_push_devices); | 59 local plain_table = {}; |
129 local ok, err = store:set(user, push_services[user]); | 60 for k, v in pairs(push_services[user]) do plain_table[k] = v; end |
61 local ok, err = store:set(user, plain_table); | |
130 if not ok then | 62 if not ok then |
131 module:log("error", "Error writing push notification storage for user '%s': %s", user, tostring(err)); | 63 module:log("error", "Error writing push notification storage for user '%s': %s", user, tostring(err)); |
132 return false; | 64 return false; |
133 end | 65 end |
134 return true; | 66 return true; |
135 end | 67 end |
136 function api:set_identifier(user, push_identifier, data) | 68 function api:set_identifier(user, push_identifier, data) |
137 local services = self:get(user); | 69 local services = self:get(user); |
138 services[push_identifier] = data; | 70 services[push_identifier] = data; |
139 return self:set(user, services); | |
140 end | 71 end |
141 return api; | 72 return api; |
142 end)(); | 73 end)(); |
143 | 74 |
144 | 75 |
147 | 78 |
148 function handle_push_error(event) | 79 function handle_push_error(event) |
149 local stanza = event.stanza; | 80 local stanza = event.stanza; |
150 local error_type, condition = stanza:get_error(); | 81 local error_type, condition = stanza:get_error(); |
151 local node = id2node[stanza.attr.id]; | 82 local node = id2node[stanza.attr.id]; |
83 local identifier = id2identifier[stanza.attr.id]; | |
152 if node == nil then return false; end -- unknown stanza? Ignore for now! | 84 if node == nil then return false; end -- unknown stanza? Ignore for now! |
153 local from = stanza.attr.from; | 85 local from = stanza.attr.from; |
154 local user_push_services = push_store:get(node); | 86 local user_push_services = push_store:get(node); |
155 local changed = false; | 87 local changed = false; |
156 | 88 |
157 for push_identifier, _ in pairs(user_push_services) do | 89 for push_identifier, _ in pairs(user_push_services) do |
158 local stanza_id = hashes.sha256(push_identifier, true); | 90 if push_identifier == identifier then |
159 if stanza_id == stanza.attr.id then | |
160 if user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and error_type ~= "wait" then | 91 if user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and error_type ~= "wait" then |
161 push_errors[push_identifier] = push_errors[push_identifier] + 1; | 92 push_errors[push_identifier] = push_errors[push_identifier] + 1; |
162 module:log("info", "Got error of type '%s' (%s) for identifier '%s': " | 93 module:log("info", "Got error of type '%s' (%s) for identifier '%s': " |
163 .."error count for this identifier is now at %s", error_type, condition, push_identifier, | 94 .."error count for this identifier is now at %s", error_type, condition, push_identifier, |
164 tostring(push_errors[push_identifier])); | 95 tostring(push_errors[push_identifier])); |
177 -- save changed global config | 108 -- save changed global config |
178 changed = true; | 109 changed = true; |
179 user_push_services[push_identifier] = nil | 110 user_push_services[push_identifier] = nil |
180 push_errors[push_identifier] = nil; | 111 push_errors[push_identifier] = nil; |
181 -- unhook iq handlers for this identifier (if possible) | 112 -- unhook iq handlers for this identifier (if possible) |
182 if module.unhook then | 113 module:unhook("iq-error/host/"..stanza.attr.id, handle_push_error); |
183 module:unhook("iq-error/host/"..stanza_id, handle_push_error); | 114 module:unhook("iq-result/host/"..stanza.attr.id, handle_push_success); |
184 module:unhook("iq-result/host/"..stanza_id, handle_push_success); | 115 id2node[stanza.attr.id] = nil; |
185 id2node[stanza_id] = nil; | 116 id2identifier[stanza.attr.id] = nil; |
186 end | |
187 end | 117 end |
188 elseif user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and error_type == "wait" then | 118 elseif user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and error_type == "wait" then |
189 module:log("debug", "Got error of type '%s' (%s) for identifier '%s': " | 119 module:log("debug", "Got error of type '%s' (%s) for identifier '%s': " |
190 .."NOT increasing error count for this identifier", error_type, condition, push_identifier); | 120 .."NOT increasing error count for this identifier", error_type, condition, push_identifier); |
191 end | 121 end |
192 end | 122 end |
193 end | 123 end |
194 if changed then | 124 if changed then |
195 push_store:set(node, user_push_services); | 125 push_store:flush_to_disk(node); |
196 end | 126 end |
197 return true; | 127 return true; |
198 end | 128 end |
199 | 129 |
200 function handle_push_success(event) | 130 function handle_push_success(event) |
201 local stanza = event.stanza; | 131 local stanza = event.stanza; |
202 local node = id2node[stanza.attr.id]; | 132 local node = id2node[stanza.attr.id]; |
133 local identifier = id2identifier[stanza.attr.id]; | |
203 if node == nil then return false; end -- unknown stanza? Ignore for now! | 134 if node == nil then return false; end -- unknown stanza? Ignore for now! |
204 local from = stanza.attr.from; | 135 local from = stanza.attr.from; |
205 local user_push_services = push_store:get(node); | 136 local user_push_services = push_store:get(node); |
206 | 137 |
207 for push_identifier, _ in pairs(user_push_services) do | 138 for push_identifier, _ in pairs(user_push_services) do |
208 if hashes.sha256(push_identifier, true) == stanza.attr.id then | 139 if push_identifier == identifier then |
209 if user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and push_errors[push_identifier] > 0 then | 140 if user_push_services[push_identifier] and user_push_services[push_identifier].jid == from and push_errors[push_identifier] > 0 then |
210 push_errors[push_identifier] = 0; | 141 push_errors[push_identifier] = 0; |
211 -- unhook iq handlers for this identifier (if possible) | 142 -- unhook iq handlers for this identifier (if possible) |
212 if module.unhook then | 143 module:unhook("iq-error/host/"..stanza.attr.id, handle_push_error); |
213 module:unhook("iq-error/host/"..stanza.attr.id, handle_push_error); | 144 module:unhook("iq-result/host/"..stanza.attr.id, handle_push_success); |
214 module:unhook("iq-result/host/"..stanza.attr.id, handle_push_success); | 145 id2node[stanza.attr.id] = nil; |
215 id2node[stanza.attr.id] = nil; | 146 id2identifier[stanza.attr.id] = nil; |
216 end | |
217 module:log("debug", "Push succeeded, error count for identifier '%s' is now at %s again", push_identifier, tostring(push_errors[push_identifier])); | 147 module:log("debug", "Push succeeded, error count for identifier '%s' is now at %s again", push_identifier, tostring(push_errors[push_identifier])); |
218 end | 148 end |
219 end | 149 end |
220 end | 150 end |
221 return true; | 151 return true; |
254 node = push_node; | 184 node = push_node; |
255 include_payload = include_payload; | 185 include_payload = include_payload; |
256 options = publish_options and st.preserialize(publish_options); | 186 options = publish_options and st.preserialize(publish_options); |
257 timestamp = os_time(); | 187 timestamp = os_time(); |
258 }; | 188 }; |
259 local ok = push_store:set_identifier(origin.username, push_identifier, push_service); | 189 push_store:set_identifier(origin.username, push_identifier, push_service); |
190 local ok = push_store:flush_to_disk(origin.username); | |
260 if not ok then | 191 if not ok then |
261 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); | 192 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); |
262 else | 193 else |
263 origin.push_identifier = push_identifier; | 194 origin.push_identifier = push_identifier; |
264 origin.push_settings = push_service; | 195 origin.push_settings = push_service; |
288 origin.push_settings = nil; | 219 origin.push_settings = nil; |
289 origin.first_hibernated_push = nil; | 220 origin.first_hibernated_push = nil; |
290 end | 221 end |
291 user_push_services[key] = nil; | 222 user_push_services[key] = nil; |
292 push_errors[key] = nil; | 223 push_errors[key] = nil; |
293 if module.unhook then | 224 for stanza_id, identifier in pairs(id2identifier) do |
294 local stanza_id = hashes.sha256(key, true) | 225 if identifier == key then |
295 module:unhook("iq-error/host/"..stanza_id, handle_push_error); | 226 module:unhook("iq-error/host/"..stanza_id, handle_push_error); |
296 module:unhook("iq-result/host/"..stanza_id, handle_push_success); | 227 module:unhook("iq-result/host/"..stanza_id, handle_push_success); |
297 id2node[stanza_id] = nil; | 228 id2node[stanza_id] = nil; |
298 end | 229 id2identifier[stanza_id] = nil; |
299 end | 230 end |
300 end | 231 end |
301 local ok = push_store:set(origin.username, user_push_services); | 232 end |
233 end | |
234 local ok = push_store:flush_to_disk(origin.username); | |
302 if not ok then | 235 if not ok then |
303 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); | 236 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); |
304 else | 237 else |
305 origin.send(st.reply(stanza)); | 238 origin.send(st.reply(stanza)); |
306 end | 239 end |
307 return true; | 240 return true; |
308 end | 241 end |
309 module:hook("iq-set/self/"..xmlns_push..":disable", push_disable); | 242 module:hook("iq-set/self/"..xmlns_push..":disable", push_disable); |
310 | |
311 -- Patched version of util.stanza:find() that supports giving stanza names | |
312 -- without their namespace, allowing for every namespace. | |
313 local function find(self, path) | |
314 local pos = 1; | |
315 local len = #path + 1; | |
316 | |
317 repeat | |
318 local xmlns, name, text; | |
319 local char = s_sub(path, pos, pos); | |
320 if char == "@" then | |
321 return self.attr[s_sub(path, pos + 1)]; | |
322 elseif char == "{" then | |
323 xmlns, pos = s_match(path, "^([^}]+)}()", pos + 1); | |
324 end | |
325 name, text, pos = s_match(path, "^([^@/#]*)([/#]?)()", pos); | |
326 name = name ~= "" and name or nil; | |
327 if pos == len then | |
328 if text == "#" then | |
329 local child = xmlns ~= nil and self:get_child(name, xmlns) or self:child_with_name(name); | |
330 return child and child:get_text() or nil; | |
331 end | |
332 return xmlns ~= nil and self:get_child(name, xmlns) or self:child_with_name(name); | |
333 end | |
334 self = xmlns ~= nil and self:get_child(name, xmlns) or self:child_with_name(name); | |
335 until not self | |
336 return nil; | |
337 end | |
338 | 243 |
339 -- is this push a high priority one (this is needed for ios apps not using voip pushes) | 244 -- is this push a high priority one (this is needed for ios apps not using voip pushes) |
340 local function is_important(stanza) | 245 local function is_important(stanza) |
341 local st_name = stanza and stanza.name or nil; | 246 local st_name = stanza and stanza.name or nil; |
342 if not st_name then return false; end -- nonzas are never important here | 247 if not st_name then return false; end -- nonzas are never important here |
346 -- unpack carbon copies | 251 -- unpack carbon copies |
347 local stanza_direction = "in"; | 252 local stanza_direction = "in"; |
348 local carbon; | 253 local carbon; |
349 local st_type; | 254 local st_type; |
350 -- support carbon copied message stanzas having an arbitrary message-namespace or no message-namespace at all | 255 -- support carbon copied message stanzas having an arbitrary message-namespace or no message-namespace at all |
351 if not carbon then carbon = find(stanza, "{urn:xmpp:carbons:2}/forwarded/message"); end | 256 if not carbon then carbon = stanza:find("{urn:xmpp:carbons:2}/{urn:xmpp:forward:0}/{jabber:client}message"); end |
352 if not carbon then carbon = find(stanza, "{urn:xmpp:carbons:1}/forwarded/message"); end | |
353 stanza_direction = carbon and stanza:child_with_name("sent") and "out" or "in"; | 257 stanza_direction = carbon and stanza:child_with_name("sent") and "out" or "in"; |
354 if carbon then stanza = carbon; end | 258 if carbon then stanza = carbon; end |
355 st_type = stanza.attr.type; | 259 st_type = stanza.attr.type; |
356 | 260 |
357 -- headline message are always not important | 261 -- headline message are always not important |
388 }; | 292 }; |
389 | 293 |
390 -- http://xmpp.org/extensions/xep-0357.html#publishing | 294 -- http://xmpp.org/extensions/xep-0357.html#publishing |
391 local function handle_notify_request(stanza, node, user_push_services, log_push_decline) | 295 local function handle_notify_request(stanza, node, user_push_services, log_push_decline) |
392 local pushes = 0; | 296 local pushes = 0; |
393 if not user_push_services or next(user_push_services) == nil then return pushes end | 297 if not #user_push_services then return pushes end |
394 | 298 |
395 for push_identifier, push_info in pairs(user_push_services) do | 299 for push_identifier, push_info in pairs(user_push_services) do |
396 local send_push = true; -- only send push to this node when not already done for this stanza or if no stanza is given at all | 300 local send_push = true; -- only send push to this node when not already done for this stanza or if no stanza is given at all |
397 if stanza then | 301 if stanza then |
398 if not stanza._push_notify then stanza._push_notify = {}; end | 302 if not stanza._push_notify then stanza._push_notify = {}; end |
405 stanza._push_notify[push_identifier] = true; | 309 stanza._push_notify[push_identifier] = true; |
406 end | 310 end |
407 | 311 |
408 if send_push then | 312 if send_push then |
409 -- construct push stanza | 313 -- construct push stanza |
410 local stanza_id = hashes.sha256(push_identifier, true); | 314 local stanza_id = hashes.sha256(random.bytes(8), true); |
411 local push_publish = st.iq({ to = push_info.jid, from = module.host, type = "set", id = stanza_id }) | 315 local push_publish = st.iq({ to = push_info.jid, from = module.host, type = "set", id = stanza_id }) |
412 :tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" }) | 316 :tag("pubsub", { xmlns = "http://jabber.org/protocol/pubsub" }) |
413 :tag("publish", { node = push_info.node }) | 317 :tag("publish", { node = push_info.node }) |
414 :tag("item") | 318 :tag("item") |
415 :tag("notification", { xmlns = xmlns_push }); | 319 :tag("notification", { xmlns = xmlns_push }); |
436 module:log("debug", "Sending%s push notification for %s@%s to %s (%s)", form_data["last-message-body"] and " important" or "", node, module.host, push_info.jid, tostring(push_info.node)); | 340 module:log("debug", "Sending%s push notification for %s@%s to %s (%s)", form_data["last-message-body"] and " important" or "", node, module.host, push_info.jid, tostring(push_info.node)); |
437 -- module:log("debug", "PUSH STANZA: %s", tostring(push_publish)); | 341 -- module:log("debug", "PUSH STANZA: %s", tostring(push_publish)); |
438 -- handle push errors for this node | 342 -- handle push errors for this node |
439 if push_errors[push_identifier] == nil then | 343 if push_errors[push_identifier] == nil then |
440 push_errors[push_identifier] = 0; | 344 push_errors[push_identifier] = 0; |
441 module:hook("iq-error/host/"..stanza_id, handle_push_error); | 345 end |
442 module:hook("iq-result/host/"..stanza_id, handle_push_success); | 346 module:hook("iq-error/host/"..stanza_id, handle_push_error); |
443 id2node[stanza_id] = node; | 347 module:hook("iq-result/host/"..stanza_id, handle_push_success); |
444 end | 348 id2node[stanza_id] = node; |
349 id2identifier[stanza_id] = push_identifier; | |
445 module:send(push_publish); | 350 module:send(push_publish); |
446 pushes = pushes + 1; | 351 pushes = pushes + 1; |
447 end | 352 end |
448 end | 353 end |
449 return pushes; | 354 return pushes; |
498 if not session.push_queue then session.push_queue = {}; end | 403 if not session.push_queue then session.push_queue = {}; end |
499 local queue = session.push_queue; | 404 local queue = session.push_queue; |
500 queue[#queue+1] = st.clone(stanza); | 405 queue[#queue+1] = st.clone(stanza); |
501 if #queue == 1 then -- first stanza --> start timer | 406 if #queue == 1 then -- first stanza --> start timer |
502 session.log("debug", "Invoking cloud handle_notify_request() for newly smacks queued stanza (in a moment)"); | 407 session.log("debug", "Invoking cloud handle_notify_request() for newly smacks queued stanza (in a moment)"); |
503 session.awaiting_push_timer = stoppable_timer(1e-06, function () | 408 session.awaiting_push_timer = module:add_timer(1e-06, function () |
504 session.log("debug", "Invoking cloud handle_notify_request() for newly smacks queued stanzas (now in timer)"); | 409 session.log("debug", "Invoking cloud handle_notify_request() for newly smacks queued stanzas (now in timer)"); |
505 process_stanza_queue(session.push_queue, session, "push"); | 410 process_stanza_queue(session.push_queue, session, "push"); |
506 session.push_queue = {}; -- clean up queue after push | 411 session.push_queue = {}; -- clean up queue after push |
507 end); | 412 end); |
508 end | 413 end |
550 to = to and jid.split(to) or event.origin.username; | 455 to = to and jid.split(to) or event.origin.username; |
551 | 456 |
552 -- only notify if the stanza destination is the mam user we store it for | 457 -- only notify if the stanza destination is the mam user we store it for |
553 if event.for_user == to then | 458 if event.for_user == to then |
554 local user_push_services = push_store:get(to); | 459 local user_push_services = push_store:get(to); |
555 if next(user_push_services) == nil then return end | |
556 | 460 |
557 -- only notify nodes with no active sessions (smacks is counted as active and handled separate) | 461 -- only notify nodes with no active sessions (smacks is counted as active and handled separate) |
558 local notify_push_services = {}; | 462 local notify_push_services = {}; |
559 for identifier, push_info in pairs(user_push_services) do | 463 for identifier, push_info in pairs(user_push_services) do |
560 local identifier_found = nil; | 464 local identifier_found = nil; |
582 module:hook("archive-message-added", archive_message_added); | 486 module:hook("archive-message-added", archive_message_added); |
583 | 487 |
584 local function send_ping(event) | 488 local function send_ping(event) |
585 local user = event.user; | 489 local user = event.user; |
586 local push_services = event.push_services or push_store:get(user); | 490 local push_services = event.push_services or push_store:get(user); |
587 handle_notify_request(nil, user, push_services, true); | 491 module:log("debug", "Handling event 'cloud-notify-ping' for user '%s'", user); |
492 local retval = handle_notify_request(nil, user, push_services, true); | |
493 module:log("debug", "handle_notify_request() returned %s", tostring(retval)); | |
588 end | 494 end |
589 -- can be used by other modules to ping one or more (or all) push endpoints | 495 -- can be used by other modules to ping one or more (or all) push endpoints |
590 module:hook("cloud-notify-ping", send_ping); | 496 module:hook("cloud-notify-ping", send_ping); |
591 | 497 |
592 module:log("info", "Module loaded"); | 498 module:log("info", "Module loaded"); |
593 function module.unload() | 499 function module.unload() |
594 if module.unhook then | |
595 module:unhook("account-disco-info", account_dico_info); | |
596 module:unhook("iq-set/self/"..xmlns_push..":enable", push_enable); | |
597 module:unhook("iq-set/self/"..xmlns_push..":disable", push_disable); | |
598 | |
599 module:unhook("smacks-hibernation-start", hibernate_session); | |
600 module:unhook("smacks-hibernation-end", restore_session); | |
601 module:unhook("smacks-ack-delayed", ack_delayed); | |
602 module:unhook("archive-message-added", archive_message_added); | |
603 module:unhook("cloud-notify-ping", send_ping); | |
604 | |
605 for push_identifier, _ in pairs(push_errors) do | |
606 local stanza_id = hashes.sha256(push_identifier, true); | |
607 module:unhook("iq-error/host/"..stanza_id, handle_push_error); | |
608 module:unhook("iq-result/host/"..stanza_id, handle_push_success); | |
609 id2node[stanza_id] = nil; | |
610 end | |
611 end | |
612 | |
613 module:log("info", "Module unloaded"); | 500 module:log("info", "Module unloaded"); |
614 end | 501 end |