diff -r ada71b81425a -r f24b02e0d706 mod_presence_dedup/mod_presence_dedup.lua --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mod_presence_dedup/mod_presence_dedup.lua Sun Apr 03 17:09:03 2016 +0200 @@ -0,0 +1,44 @@ +local st = require "util.stanza"; +local cache = require "util.cache"; +local add_filter = require "util.filters".add_filter; + +local cache_size = module:get_option_number("presence_dedup_cache_size", 100); + +-- stanza equality tests +local function attr_eq(a, b) + if a == b then return true; end -- unlikely but not impossible + for k,v in pairs(a) do if b[k] ~= v then return false; end end + for k,v in pairs(b) do if a[k] ~= v then return false; end end + return true; +end + +local function st_eq(a, b) + if a == b then return true; end + if type(b) ~= "table" then return false; end + if getmetatable(b) ~= st.stanza_mt then return false; end + if a.name ~= b.name then return false; end + if #a ~= #b then return false; end + if not attr_eq(a.attr, b.attr) then return false; end + for i = 1, #a do if not st_eq(a[i], b[i]) then return false; end end + return true; +end + +local function dedup_presence(stanza, session) + if session.presence_cache and session.presence + and getmetatable(stanza) == st.stanza_mt and stanza.name == "presence" + and stanza.attr.xmlns == nil and stanza.attr.from then + local cached = session.presence_cache:get(stanza.attr.from); + if st_eq(stanza, cached) then + return nil; + else + session.presence_cache:set(stanza.attr.from, st.clone(stanza)); + end + end + return stanza; +end + +module:hook("presence/initial", function (event) + local session, stanza = event.origin, event.stanza; + session.presence_cache = cache.new(cache_size); + add_filter(session, "stanzas/out", dedup_presence, 90); +end);