--- a/mod_cloud_notify/mod_cloud_notify.lua Mon May 28 05:27:03 2018 +0200
+++ b/mod_cloud_notify/mod_cloud_notify.lua Mon May 28 05:28:07 2018 +0200
@@ -1,12 +1,13 @@
-- XEP-0357: Push (aka: My mobile OS vendor won't let me have persistent TCP connections)
-- Copyright (C) 2015-2016 Kim Alvefur
--- Copyright (C) 2017 Thilo Molitor
+-- Copyright (C) 2017-2018 Thilo Molitor
--
-- This file is MIT/X11 licensed.
local t_insert = table.insert;
local s_match = string.match;
local s_sub = string.sub;
+local os_time = os.time;
local st = require"util.stanza";
local jid = require"util.jid";
local dataform = require"util.dataforms".new;
@@ -18,13 +19,79 @@
-- configuration
local include_body = module:get_option_boolean("push_notification_with_body", false);
local include_sender = module:get_option_boolean("push_notification_with_sender", false);
-local max_push_errors = module:get_option_number("push_max_errors", 50);
-local dummy_body = module:get_option_string("push_notification_important_body", "");
+local max_push_errors = module:get_option_number("push_max_errors", 16);
+local max_push_devices = module:get_option_number("push_max_devices", 5);
+local dummy_body = module:get_option_string("push_notification_important_body", "New Message!");
local host_sessions = prosody.hosts[module.host].sessions;
local push_errors = {};
local id2node = {};
+-- ordered table iterator, allow to iterate on the natural order of the keys of a table,
+-- see http://lua-users.org/wiki/SortedIteration
+local function __genOrderedIndex( t )
+ local orderedIndex = {}
+ for key in pairs(t) do
+ table.insert( orderedIndex, key )
+ end
+ -- sort in reverse order (newest one first)
+ table.sort( orderedIndex, function(a, b)
+ if a == nil or t[a] == nil or b == nil or t[b] == nil then return false end
+ -- only one timestamp given, this is the newer one
+ if t[a].timestamp ~= nil and t[b].timestamp == nil then return true end
+ if t[a].timestamp == nil and t[b].timestamp ~= nil then return false end
+ -- both timestamps given, sort normally
+ if t[a].timestamp ~= nil and t[b].timestamp ~= nil then return t[a].timestamp > t[b].timestamp end
+ return false -- normally not reached
+ end)
+ return orderedIndex
+end
+local function orderedNext(t, state)
+ -- Equivalent of the next function, but returns the keys in timestamp
+ -- order. We use a temporary ordered key table that is stored in the
+ -- table being iterated.
+
+ local key = nil
+ --print("orderedNext: state = "..tostring(state) )
+ if state == nil then
+ -- the first time, generate the index
+ t.__orderedIndex = __genOrderedIndex( t )
+ key = t.__orderedIndex[1]
+ else
+ -- fetch the next value
+ for i = 1,table.getn(t.__orderedIndex) do
+ if t.__orderedIndex[i] == state then
+ key = t.__orderedIndex[i+1]
+ end
+ end
+ end
+
+ if key then
+ return key, t[key]
+ end
+
+ -- no more value to return, cleanup
+ t.__orderedIndex = nil
+ return
+end
+local function orderedPairs(t)
+ -- Equivalent of the pairs() function on tables. Allows to iterate
+ -- in order
+ return orderedNext, t, nil
+end
+
+-- small helper function to return new table with only "maximum" elements containing only the newest entries
+local function reduce_table(table, maximum)
+ local count = 0;
+ local result = {};
+ for key, value in orderedPairs(table) do
+ count = count + 1;
+ if count > maximum then break end
+ result[key] = value;
+ end
+ return result;
+end
+
-- For keeping state across reloads while caching reads
local push_store = (function()
local store = module:open_store();
@@ -44,7 +111,7 @@
return push_services[user], true;
end
function api:set(user, data)
- push_services[user] = data;
+ push_services[user] = reduce_table(data, max_push_devices);
local ok, err = store:set(user, push_services[user]);
if not ok then
module:log("error", "Error writing push notification storage for user '%s': %s", user, tostring(err));
@@ -160,6 +227,7 @@
node = push_node;
include_payload = include_payload;
options = publish_options and st.preserialize(publish_options);
+ timestamp = os_time();
};
local ok = push_store:set_identifier(origin.username, push_identifier, push_service);
if not ok then
@@ -418,7 +486,7 @@
-- archive message added
local function archive_message_added(event)
-- event is: { origin = origin, stanza = stanza, for_user = store_user, id = id }
- -- only notify for new mam messages when at least one device is only
+ -- only notify for new mam messages when at least one device is online
if not event.for_user or not host_sessions[event.for_user] then return; end
local stanza = event.stanza;
local user_session = host_sessions[event.for_user].sessions;