130 lines
4.1 KiB
Lua
130 lines
4.1 KiB
Lua
-- mod_muc_notifications
|
|
--
|
|
-- Copyright (C) 2019 Marcos de Vera Piquero <marcos.devera@quobis.com>
|
|
-- enhanced by Stefan Sänger <stefan.saenger@vnc.biz>
|
|
-- This file is MIT/X11 licensed.
|
|
--
|
|
-- A module to notify non-present members of messages in a group chat
|
|
--
|
|
|
|
local id = require"util.id"
|
|
local st = require"util.stanza"
|
|
|
|
local use_invite = module:get_option_boolean("muc_notification_invite", false)
|
|
|
|
local function dumpTable1(t, depth)
|
|
local result = "";
|
|
if (not depth) then depth = 0 end;
|
|
|
|
local prefix = string.rep(" ", depth);
|
|
|
|
if (type(t) ~= "table") then
|
|
result = result.." "..tostring(t);
|
|
else
|
|
for key,value in pairs(t) do
|
|
result = result..prefix..tostring(key).." => "..tostring(value).."\n"
|
|
end
|
|
end
|
|
|
|
return result;
|
|
end
|
|
|
|
local function dumpTable(t, depth)
|
|
local result = "";
|
|
if (not depth) then depth = 0 end;
|
|
|
|
local prefix = string.rep(" ", depth);
|
|
|
|
if (type(t) ~= "table") then
|
|
result = result.." "..tostring(t);
|
|
else
|
|
for key,value in pairs(t) do
|
|
result = result..prefix..tostring(key).." => "..dumpTable(value, depth+1).."\n"
|
|
end
|
|
end
|
|
|
|
return result;
|
|
end
|
|
|
|
-- Given a stanza, compute if it qualifies as important (notifiable)
|
|
-- return true for message stanzas with non-empty body
|
|
-- Should probably use something similar to muc-message-is-historic event
|
|
local function is_important(stanza)
|
|
local body = stanza:find("body#")
|
|
return body and #body
|
|
end
|
|
|
|
local function handle_muc_message(event)
|
|
-- event.room and event.stanza are available
|
|
local room = event.room
|
|
-- module:log("info","room: %s", dumpTable(room._occupants));
|
|
local stanza = event.stanza
|
|
local aff_jids = {};
|
|
for jid, aff in pairs(room._affiliations) do
|
|
if aff ~= "outcast" then
|
|
local is_occupant = false
|
|
local sessions = prosody.bare_sessions;
|
|
local user_online = sessions[jid] or nil;
|
|
local jid_resources = {};
|
|
if (user_online ~= nil) then
|
|
local u_sessions = user_online["sessions"] or nil;
|
|
for k,v in pairs(u_sessions) do
|
|
jid_resources[jid.."/"..tostring(k)] = true;
|
|
end
|
|
-- module:log("info", "room user %s sessions: \n %s", jid, dumpTable(jid_resources));
|
|
end
|
|
|
|
for _, occupant in pairs(room._occupants) do
|
|
if occupant.bare_jid == jid then
|
|
for k,v in pairs(occupant.sessions) do
|
|
-- module:log("info", "occupant k %s", k);
|
|
jid_resources[k] = nil;
|
|
end
|
|
-- module:log("info", "remaining resources: ", dumpTable(jid_resources));
|
|
-- module:log("info", "remaining resources#: %s", #jid_resources);
|
|
if next(jid_resources) == nil then
|
|
-- module:log("info", "user %s is occupant with all sessions", jid);
|
|
is_occupant = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
-- module:log("info", "got jid: %s", jid);
|
|
-- local sessions = prosody.bare_sessions;
|
|
-- local user_online_sessions = sessions[jid] or nil;
|
|
|
|
if not is_occupant and is_important(stanza) and (user_online ~= nil) then
|
|
-- send notification to jid
|
|
local attrs = {
|
|
to = jid,
|
|
id = id.short(),
|
|
from = room.jid,
|
|
}
|
|
local not_attrs = {
|
|
xmlns = "http://vnc.biz/xmpp/muc#hook",
|
|
jid = room.jid,
|
|
}
|
|
local reason = "You have messages in group chat "..(room:get_name() or room.jid)
|
|
local notification = st.message(attrs)
|
|
:body(reason):up()
|
|
:tag("notification", not_attrs):up()
|
|
:tag("no-store", {xmlns = "urn:xmpp:hints"})
|
|
local invite = st.message(attrs):tag("x", {xmlns = "http://jabber.org/protocol/muc#user"})
|
|
:tag("invite", {from = stanza.attr.from})
|
|
:tag("reason"):text(reason):up():up():up()
|
|
:tag("notification", not_attrs):up()
|
|
:tag("no-store", {xmlns = "urn:xmpp:hints"})
|
|
module:log("debug", "notifying with %s", tostring(use_invite and invite or notification))
|
|
module:send(use_invite and invite or notification)
|
|
module:log("debug", "sent notification of MUC message %s", use_invite and invite or notification)
|
|
else
|
|
module:log("debug", "user %s is not online or already occupant - not sending invite", jid);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
module:hook("muc-broadcast-message", handle_muc_message)
|
|
|
|
module:log("debug", "Module loaded")
|