Mercurial > prosody-modules
comparison mod_cloud_notify/mod_cloud_notify.lua @ 3055:6abee021d9db
mod_cloud_notify: Limit number of devices to 5 and change some default settings
author | tmolitor <thilo@eightysoft.de> |
---|---|
date | Mon, 28 May 2018 05:28:07 +0200 |
parents | 7ee59f417c16 |
children | 6b860de18a53 |
comparison
equal
deleted
inserted
replaced
3054:5e94061c1aa7 | 3055:6abee021d9db |
---|---|
1 -- XEP-0357: Push (aka: My mobile OS vendor won't let me have persistent TCP connections) | 1 -- XEP-0357: Push (aka: My mobile OS vendor won't let me have persistent TCP connections) |
2 -- Copyright (C) 2015-2016 Kim Alvefur | 2 -- Copyright (C) 2015-2016 Kim Alvefur |
3 -- Copyright (C) 2017 Thilo Molitor | 3 -- Copyright (C) 2017-2018 Thilo Molitor |
4 -- | 4 -- |
5 -- This file is MIT/X11 licensed. | 5 -- This file is MIT/X11 licensed. |
6 | 6 |
7 local t_insert = table.insert; | 7 local t_insert = table.insert; |
8 local s_match = string.match; | 8 local s_match = string.match; |
9 local s_sub = string.sub; | 9 local s_sub = string.sub; |
10 local os_time = os.time; | |
10 local st = require"util.stanza"; | 11 local st = require"util.stanza"; |
11 local jid = require"util.jid"; | 12 local jid = require"util.jid"; |
12 local dataform = require"util.dataforms".new; | 13 local dataform = require"util.dataforms".new; |
13 local filters = require"util.filters"; | 14 local filters = require"util.filters"; |
14 local hashes = require"util.hashes"; | 15 local hashes = require"util.hashes"; |
16 local xmlns_push = "urn:xmpp:push:0"; | 17 local xmlns_push = "urn:xmpp:push:0"; |
17 | 18 |
18 -- configuration | 19 -- configuration |
19 local include_body = module:get_option_boolean("push_notification_with_body", false); | 20 local include_body = module:get_option_boolean("push_notification_with_body", false); |
20 local include_sender = module:get_option_boolean("push_notification_with_sender", false); | 21 local include_sender = module:get_option_boolean("push_notification_with_sender", false); |
21 local max_push_errors = module:get_option_number("push_max_errors", 50); | 22 local max_push_errors = module:get_option_number("push_max_errors", 16); |
22 local dummy_body = module:get_option_string("push_notification_important_body", ""); | 23 local max_push_devices = module:get_option_number("push_max_devices", 5); |
24 local dummy_body = module:get_option_string("push_notification_important_body", "New Message!"); | |
23 | 25 |
24 local host_sessions = prosody.hosts[module.host].sessions; | 26 local host_sessions = prosody.hosts[module.host].sessions; |
25 local push_errors = {}; | 27 local push_errors = {}; |
26 local id2node = {}; | 28 local id2node = {}; |
29 | |
30 -- ordered table iterator, allow to iterate on the natural order of the keys of a table, | |
31 -- see http://lua-users.org/wiki/SortedIteration | |
32 local function __genOrderedIndex( t ) | |
33 local orderedIndex = {} | |
34 for key in pairs(t) do | |
35 table.insert( orderedIndex, key ) | |
36 end | |
37 -- sort in reverse order (newest one first) | |
38 table.sort( orderedIndex, function(a, b) | |
39 if a == nil or t[a] == nil or b == nil or t[b] == nil then return false end | |
40 -- only one timestamp given, this is the newer one | |
41 if t[a].timestamp ~= nil and t[b].timestamp == nil then return true end | |
42 if t[a].timestamp == nil and t[b].timestamp ~= nil then return false end | |
43 -- both timestamps given, sort normally | |
44 if t[a].timestamp ~= nil and t[b].timestamp ~= nil then return t[a].timestamp > t[b].timestamp end | |
45 return false -- normally not reached | |
46 end) | |
47 return orderedIndex | |
48 end | |
49 local function orderedNext(t, state) | |
50 -- Equivalent of the next function, but returns the keys in timestamp | |
51 -- order. We use a temporary ordered key table that is stored in the | |
52 -- table being iterated. | |
53 | |
54 local key = nil | |
55 --print("orderedNext: state = "..tostring(state) ) | |
56 if state == nil then | |
57 -- the first time, generate the index | |
58 t.__orderedIndex = __genOrderedIndex( t ) | |
59 key = t.__orderedIndex[1] | |
60 else | |
61 -- fetch the next value | |
62 for i = 1,table.getn(t.__orderedIndex) do | |
63 if t.__orderedIndex[i] == state then | |
64 key = t.__orderedIndex[i+1] | |
65 end | |
66 end | |
67 end | |
68 | |
69 if key then | |
70 return key, t[key] | |
71 end | |
72 | |
73 -- no more value to return, cleanup | |
74 t.__orderedIndex = nil | |
75 return | |
76 end | |
77 local function orderedPairs(t) | |
78 -- Equivalent of the pairs() function on tables. Allows to iterate | |
79 -- in order | |
80 return orderedNext, t, nil | |
81 end | |
82 | |
83 -- small helper function to return new table with only "maximum" elements containing only the newest entries | |
84 local function reduce_table(table, maximum) | |
85 local count = 0; | |
86 local result = {}; | |
87 for key, value in orderedPairs(table) do | |
88 count = count + 1; | |
89 if count > maximum then break end | |
90 result[key] = value; | |
91 end | |
92 return result; | |
93 end | |
27 | 94 |
28 -- For keeping state across reloads while caching reads | 95 -- For keeping state across reloads while caching reads |
29 local push_store = (function() | 96 local push_store = (function() |
30 local store = module:open_store(); | 97 local store = module:open_store(); |
31 local push_services = {}; | 98 local push_services = {}; |
42 end | 109 end |
43 if not push_services[user] then push_services[user] = {} end | 110 if not push_services[user] then push_services[user] = {} end |
44 return push_services[user], true; | 111 return push_services[user], true; |
45 end | 112 end |
46 function api:set(user, data) | 113 function api:set(user, data) |
47 push_services[user] = data; | 114 push_services[user] = reduce_table(data, max_push_devices); |
48 local ok, err = store:set(user, push_services[user]); | 115 local ok, err = store:set(user, push_services[user]); |
49 if not ok then | 116 if not ok then |
50 module:log("error", "Error writing push notification storage for user '%s': %s", user, tostring(err)); | 117 module:log("error", "Error writing push notification storage for user '%s': %s", user, tostring(err)); |
51 return false; | 118 return false; |
52 end | 119 end |
158 local push_service = { | 225 local push_service = { |
159 jid = push_jid; | 226 jid = push_jid; |
160 node = push_node; | 227 node = push_node; |
161 include_payload = include_payload; | 228 include_payload = include_payload; |
162 options = publish_options and st.preserialize(publish_options); | 229 options = publish_options and st.preserialize(publish_options); |
230 timestamp = os_time(); | |
163 }; | 231 }; |
164 local ok = push_store:set_identifier(origin.username, push_identifier, push_service); | 232 local ok = push_store:set_identifier(origin.username, push_identifier, push_service); |
165 if not ok then | 233 if not ok then |
166 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); | 234 origin.send(st.error_reply(stanza, "wait", "internal-server-error")); |
167 else | 235 else |
416 end | 484 end |
417 | 485 |
418 -- archive message added | 486 -- archive message added |
419 local function archive_message_added(event) | 487 local function archive_message_added(event) |
420 -- event is: { origin = origin, stanza = stanza, for_user = store_user, id = id } | 488 -- event is: { origin = origin, stanza = stanza, for_user = store_user, id = id } |
421 -- only notify for new mam messages when at least one device is only | 489 -- only notify for new mam messages when at least one device is online |
422 if not event.for_user or not host_sessions[event.for_user] then return; end | 490 if not event.for_user or not host_sessions[event.for_user] then return; end |
423 local stanza = event.stanza; | 491 local stanza = event.stanza; |
424 local user_session = host_sessions[event.for_user].sessions; | 492 local user_session = host_sessions[event.for_user].sessions; |
425 local to = stanza.attr.to; | 493 local to = stanza.attr.to; |
426 to = to and jid.split(to) or event.origin.username; | 494 to = to and jid.split(to) or event.origin.username; |