655 lines
24 KiB
Lua
655 lines
24 KiB
Lua
-- mod_muc_notifications
|
|
--
|
|
--
|
|
-- This file is MIT/X11 licensed.
|
|
--
|
|
-- A module to notify non-present members of messages in a group chat
|
|
--
|
|
|
|
local http = require "net.http";
|
|
local json = require "util.json";
|
|
-- local ltn12 = require "ltn12"
|
|
local jid_bare = require "util.jid".bare;
|
|
local jid_split = require "util.jid".split;
|
|
local timer = require "util.timer";
|
|
local id = require"util.id"
|
|
local st = require"util.stanza"
|
|
local storage_host = module:get_option_string("storage_host");
|
|
|
|
module:log("info","founs storage_host: %s", storage_host);
|
|
|
|
|
|
local fcmAPIKey = module:get_option_string("fcm_api_key");
|
|
local fcmAPIURL = module:get_option_string("fcm_api_url");
|
|
|
|
local moduleIsActive = fcmAPIURL and fcmAPIKey;
|
|
|
|
local inactive_devices = {};
|
|
|
|
local ThisDomain = module.host;
|
|
|
|
local xmlns_sm2 = "urn:xmpp:sm:2";
|
|
local xmlns_sm3 = "urn:xmpp:sm:3";
|
|
|
|
|
|
local fcm_token_store = module:open_store("fcmtoken");
|
|
local fcm_token_map_store = module:open_store("fcmtoken", "map");
|
|
local vcard_storage = module:open_store("vcard");
|
|
local private_storage = module:open_store("private");
|
|
|
|
timer.add_task(3, function ()
|
|
private_storage = module:open_host_store(storage_host, "private");
|
|
vcard_storage = module:open_host_store(storage_host, "vcard");
|
|
fcm_token_store = module:open_host_store(storage_host, "fcmtoken");
|
|
fcm_token_map_store = module:open_host_store(storage_host, "fcmtoken", "map");
|
|
if not private_storage or not vcard_storage then
|
|
module:log("info", "private/vcard_store %s/%s not found? - will try again", private_storage, vcard_storage);
|
|
return 3;
|
|
else
|
|
module:log("info", "private/vcard_store are now %s/%s", private_storage, vcard_storage);
|
|
end
|
|
end
|
|
);
|
|
|
|
|
|
-- some helper functions
|
|
local function deserializeDataElement(pdElement, expectedName)
|
|
--module:log("debug", "deserializeDataElement("..expectedName..", "..dumpTable(pdElement)..")");
|
|
if (not pdElement) then return nil end
|
|
if (type(pdElement) ~= "table") then return nil end
|
|
|
|
if (pdElement[1] and pdElement["attr"] and pdElement["attr"]["key"] and (pdElement["attr"]["key"] == expectedName))
|
|
then
|
|
local result = json.decode(pdElement[1]);
|
|
--module:log("debug", "deserializeDataElement() = '"..dumpTable(result).."'");
|
|
return result;
|
|
end
|
|
return nil;
|
|
end
|
|
|
|
|
|
local function contains(list, x)
|
|
if (list) then
|
|
for _, v in pairs(list) do
|
|
if (v == x) then return true end
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
local function starts_with(str, start)
|
|
return str:sub(1, #start) == start
|
|
end
|
|
|
|
local function trim(s)
|
|
if s and (type(s) == "string") then
|
|
return (s:gsub("^%s*(.-)%s*$", "%1"))
|
|
else
|
|
return s
|
|
end
|
|
end
|
|
|
|
local function collapseSpaces(s)
|
|
if s and (type(s) == "string") then
|
|
return (s:gsub("%s+", " "))
|
|
else
|
|
return s
|
|
end
|
|
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
|
|
|
|
|
|
local function prettyUsername(userName)
|
|
userName = string.upper(string.sub(userName, 1, 1))..string.sub(userName, 2, -1) -- upcase first char in any case
|
|
if string.find(userName, "%.") -- contains dot
|
|
then
|
|
local i = 1
|
|
while true do
|
|
local j = string.find(userName, "%.", i)
|
|
if j == nil or #userName == i then break end
|
|
-- replace dot with space and upcase next char
|
|
userName = string.sub(userName, 1, j-1).." "..string.upper(string.sub(userName, j+1, j+1))..string.sub(userName, j+2, -1)
|
|
if #userName <= j then break end
|
|
i = j
|
|
end
|
|
end
|
|
return trim(collapseSpaces(userName));
|
|
end
|
|
|
|
|
|
local function getDisplayName(userName)
|
|
-- module:log("info", "getDisplayName user: %s", userName);
|
|
local vCard, err = vcard_storage:get(userName);
|
|
if vCard then
|
|
vCard = st.deserialize(vCard);
|
|
end
|
|
local name = nil;
|
|
if not vCard or err then
|
|
module:log("debug", "Unable to get vCard for %s : %s ", userName, tostring(err));
|
|
else
|
|
name = vCard:find("{vcard-temp}FN#");
|
|
end
|
|
if not name then name = prettyUsername(userName) or userName end
|
|
-- module:log("info", "name for %s : %s", userName, name)
|
|
return name;
|
|
end
|
|
|
|
local function getPostCallback(_fcmId, _userName)
|
|
return function(body, code, response)
|
|
local shortKey = string.sub(_fcmId, 1, 6)
|
|
if code ~= 200 then
|
|
module:log("info", "FCM result %s@%s : HTTP %s %s", _userName, shortKey, tostring(code), tostring(body))
|
|
-- if body then module:log("error", body); end
|
|
else
|
|
module:log("debug", "FCM result %s@%s : HTTP %s %s", _userName, shortKey, tostring(code), tostring(body))
|
|
end
|
|
return false -- close request
|
|
--return true -- keep request open
|
|
end
|
|
end
|
|
|
|
local function postFCM(_userName, _fcmId, _source, _body, _type, _senderName, _groupTopic, _attachment_type, _lang, _msgid, _vncTalkConferenceEtype, _vncTalkConferenceId, _nFromJid, _jitsiURL, _jitsiRoom)
|
|
|
|
if (not moduleIsActive) then return end;
|
|
local domainname = "";
|
|
local v_attachment = "";
|
|
domainname = module:get_option_string("storage_host");
|
|
|
|
if (_attachment_type ~= "") and (_attachment_type ~=nil) then
|
|
v_attachment = _attachment_type;
|
|
end
|
|
|
|
local lsource = _source;
|
|
local ltype = _type;
|
|
local signal = nil;
|
|
local nfrom = _source;
|
|
local nJitsiURL = "";
|
|
local nJitsiRoom = "";
|
|
|
|
if (_vncTalkConferenceId ~= nil) then
|
|
if string.match(_vncTalkConferenceId, "@") then
|
|
lsource = _vncTalkConferenceId;
|
|
end
|
|
end
|
|
|
|
if (_vncTalkConferenceEtype ~=nil) then
|
|
signal = "1";
|
|
ltype = _vncTalkConferenceEtype;
|
|
end
|
|
|
|
if (_nFromJid ~= nil) then
|
|
nfrom = _nFromJid;
|
|
end
|
|
|
|
if (_jitsiURL ~= nil) then
|
|
nJitsiURL = _jitsiURL;
|
|
end
|
|
|
|
if (_jitsiRoom ~= nil) then
|
|
nJitsiRoom = _jitsiRoom;
|
|
end
|
|
|
|
local stamp = os.time();
|
|
|
|
module:log("info", "postFCM username %s", _userName);
|
|
local uname = "";
|
|
if string.match(_userName, "@") then
|
|
uname = _userName;
|
|
else
|
|
uname = _userName.."@"..domainname;
|
|
end
|
|
|
|
local fcmRequest = {
|
|
to = _fcmId,
|
|
content_available = true,
|
|
priority = "high",
|
|
data = {
|
|
nType = "local_notification", -- notification type
|
|
eType = ltype, -- event type
|
|
jid = lsource, -- source jid (room jid or 1:1 chat peer bare jid)
|
|
nfrom = nfrom,
|
|
nto = uname,
|
|
name = _senderName, -- group chat nick name or single chat peer vCard name",
|
|
gt = _groupTopic, -- topic of room iff groupchat
|
|
aft = v_attachment,
|
|
callSignal = signal,
|
|
jitsiURL = nJitsiURL,
|
|
jitsiRoom = nJitsiRoom,
|
|
t = stamp,
|
|
lang = _lang,
|
|
msgid = _msgid,
|
|
body = _body -- notification body/text content
|
|
}
|
|
};
|
|
|
|
fcmRequest["android"] = { priority = "high", ttl = 345600 };
|
|
fcmRequest["webpush"] = { headers = { Urgency = "high", TTL = 345600 } };
|
|
|
|
local data = json.encode(fcmRequest);
|
|
|
|
local httpRequestOptions = {
|
|
method = "POST",
|
|
body = data,
|
|
headers = {
|
|
["Connection"] = 'close',
|
|
["Authorization"] = "key="..fcmAPIKey,
|
|
["Content-Type"] = "application/json; charset=utf-8"
|
|
}
|
|
}
|
|
|
|
-- module:log("info", "sending notification to %s for token %s - from: %s - msgid: %s - body: %s", _userName.."@"..domainname, _fcmId, _source, _msgid, _body);
|
|
-- ssl does not seem to work with net.http, so we proxy it
|
|
--http.request("https://fcm.googleapis.com/fcm/send", httpRequestOptions, postCallback)
|
|
http.request(fcmAPIURL, httpRequestOptions, getPostCallback(_fcmId, _userName))
|
|
end
|
|
|
|
local function postFCMIOS(_userName, _fcmId, _source, _body, _type, _senderName, _groupTopic, _attachment_type, _lang, _msgid, _vncTalkConferenceEtype, _vncTalkConferenceId, _nFromJid, _jitsiURL, _jitsiRoom)
|
|
|
|
if (not moduleIsActive) then return end;
|
|
local domainname = "";
|
|
local ntitle = "";
|
|
local nbody = "";
|
|
local v_attachment = "";
|
|
local nJitsiURL = "";
|
|
local nJitsiRoom = "";
|
|
|
|
domainname = module:get_option_string("storage_host");
|
|
if (_groupTopic ~= "") and (_groupTopic ~= nil) then
|
|
ntitle = _groupTopic;
|
|
else
|
|
ntitle = jid_split(_source);
|
|
end
|
|
|
|
if (_attachment_type ~= "") and (_attachment_type ~=nil) then
|
|
v_attachment = _attachment_type;
|
|
end
|
|
|
|
local _click_action = _type:upper();
|
|
|
|
if (_click_action == "NORMAL") then
|
|
_click_action = "CHAT";
|
|
end
|
|
|
|
local lsource = _source;
|
|
local ltype = _type;
|
|
local signal = nil;
|
|
local nfrom = _source;
|
|
|
|
if (_vncTalkConferenceId ~= nil) then
|
|
if string.match(_vncTalkConferenceId, "@") then
|
|
lsource = _vncTalkConferenceId;
|
|
end
|
|
end
|
|
|
|
if (_vncTalkConferenceEtype ~=nil) then
|
|
signal = "1";
|
|
ltype = _vncTalkConferenceEtype;
|
|
end
|
|
|
|
if (_nFromJid ~= nil) then
|
|
nfrom = _nFromJid;
|
|
end
|
|
if (_jitsiURL ~= nil) then
|
|
nJitsiURL = _jitsiURL;
|
|
end
|
|
|
|
if (_jitsiRoom ~= nil) then
|
|
nJitsiRoom = _jitsiRoom;
|
|
end
|
|
|
|
local fcmRequest = {
|
|
to = _fcmId,
|
|
priority = "high",
|
|
notification = {
|
|
title = ntitle,
|
|
body = _body,
|
|
mutable_content = true,
|
|
sound = "incoming-call-loop.caff",
|
|
thread_id = lsource,
|
|
click_action = _click_action
|
|
},
|
|
data = {
|
|
nType = "local_notification", -- notification type
|
|
eType = ltype, -- event type
|
|
jid = lsource, -- source jid (room jid or 1:1 chat peer bare jid)
|
|
nfrom = nfrom,
|
|
nto = _userName.."@"..domainname,
|
|
name = _senderName, -- group chat nick name or single chat peer vCard name",
|
|
gt = ntitle, -- topic of room iff groupchat
|
|
aft = v_attachment,
|
|
callSignal = signal,
|
|
jitsiURL = nJitsiURL,
|
|
jitsiRoom = nJitsiRoom,
|
|
lang = _lang,
|
|
msgid = _msgid,
|
|
body = _body -- notification body/text content
|
|
}
|
|
};
|
|
|
|
local data = json.encode(fcmRequest);
|
|
|
|
local httpRequestOptions = {
|
|
method = "POST",
|
|
body = data,
|
|
headers = {
|
|
["Connection"] = 'close',
|
|
["Authorization"] = "key="..fcmAPIKey,
|
|
["Content-Type"] = "application/json; charset=utf-8"
|
|
}
|
|
}
|
|
|
|
-- module:log("debug", "sending notification to %s for token %s - from: %s - msgid: %s - body: %s", _userName.."@"..domainname, _fcmId, _source, _msgid, string.sub(_body, 20).."...");
|
|
module:log("debug", "sending notification to %s for token %s - from: %s - msgid: %s - body: %s", _userName.."@"..domainname, _fcmId, _source, _msgid, _body.."...");
|
|
-- ssl does not seem to work with net.http, so we proxy it
|
|
--http.request("https://fcm.googleapis.com/fcm/send", httpRequestOptions, postCallback)
|
|
module:log("debug", "calling http.request -- fcmAPIURL: %s", fcmAPIURL);
|
|
http.request(fcmAPIURL, httpRequestOptions, getPostCallback(_fcmId, _userName))
|
|
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
|
|
|
|
|
|
-- get notify options for local users
|
|
local function getNotifyOptionsForUser(userName)
|
|
--module:log("debug", "getFCMtokenForUser("..userName..")");
|
|
local pd, pfFetchError = private_storage:get(userName);
|
|
if (pfFetchError) then
|
|
module:log(
|
|
"error",
|
|
"Fetching private data for '%s' failed : %s", tostring(userName), tostring(pfFetchError)
|
|
);
|
|
return 0,{};
|
|
elseif (pd) then
|
|
local tokens;
|
|
local nType;
|
|
local nLang;
|
|
for key,value in pairs(pd)
|
|
do
|
|
-- module:log("info", "PD("..userName..") : "..tostring(key).." => "..tostring(value));
|
|
module:log("debug", "PD( %s) : %s => %s ", userName,tostring(key),tostring(value));
|
|
if ((key == "documents:stanza:io:json") and (type(value) == "table")) then
|
|
--module:log("debug", "PD("..userName..") : "..json.encode(value));
|
|
-- module:log("debug", "PD( %s ) : %s ", userName ,json.encode(value));
|
|
for k2,v2 in pairs(value) do
|
|
if (not tokens) then
|
|
local fcm = deserializeDataElement(v2, "fcm");
|
|
if (type(fcm) == "table") then
|
|
tokens = {};
|
|
for token,x in pairs(fcm) do
|
|
-- module:log("debug", "token: %s - x[os]: %s", token, x["os"]);
|
|
if (x["os"] ~= nil) then
|
|
table.insert(tokens, token.."@"..x["os"])
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if (not nType) then
|
|
local options = deserializeDataElement(v2, "notifyOptions");
|
|
if (options and (type(options) == "table") and options["type"]) then
|
|
nType = tonumber(options["type"]);
|
|
end
|
|
end
|
|
if (not nLang) then
|
|
local options = deserializeDataElement(v2, "lang");
|
|
-- module:log("debug", "PDLang: %s => %s", userName, json.encode(options));
|
|
if (options) and (type(options) == "string") then
|
|
nLang = options;
|
|
end;
|
|
-- module:log("debug", "type of options: %s", type(options));
|
|
end
|
|
end
|
|
break; -- we can stop after the documents:stanza:io:json element
|
|
end
|
|
end
|
|
--module:log("debug", "getNotifyOptionsForUser("..userName..") = "..tostring(tokens).." => "..tostring(nType));
|
|
|
|
local map_res = fcm_token_store:get(userName);
|
|
|
|
-- module:log("debug", "result from map store for %s is: %s", userName, dumpTable(map_res));
|
|
|
|
if (map_res) then
|
|
for _device, _tkr in pairs(map_res) do
|
|
-- module:log("debug", "got for %s device %s => %s", userName, _device, dumpTable(_tkr));
|
|
-- module:log("debug", "got for %s device %s => token: %s - os: %s", userName, _device, _tkr.token, _tkr.os);
|
|
local sessions = prosody.bare_sessions;
|
|
local ubjid = userName.."@"..storage_host;
|
|
local u_sessions = sessions[ubjid] or nil;
|
|
local deviceonline = false;
|
|
if (u_sessions) then
|
|
local u_sessions_device = u_sessions["sessions"] or nil;
|
|
if (u_sessions_device) then
|
|
-- module:log("info", "devise is %s", _device);
|
|
-- module:log("debug", "u_sessions_device %s", dumpTable(u_sessions_device));
|
|
local dsession = u_sessions_device[_device] or nil;
|
|
-- module:log("debug", "dsession %s", dumpTable(dsession));
|
|
if (dsession) then
|
|
local hibernated = dsession["hibernated"] or nil;
|
|
local hibernating = dsession["hibernating"] or nil;
|
|
local awaiting_ack = dsession["awaiting_ack"] or nil;
|
|
module:log("info", "found session for _device %s - hibernating: %s, hibernated %s", _device, hibernating, hibernated);
|
|
if not ((hibernated) or (hibernating)) then
|
|
local dev_in_background = inactive_devices[_device] or nil;
|
|
if dev_in_background then
|
|
if awaiting_ack then
|
|
module:log("debug", "device %s is still connected, but inactive and awaiting_ack", _device);
|
|
-- module:log("info", "handling1: %s", _tkr.token.."@".._tkr.os);
|
|
else
|
|
module:log("debug", "device %s is still connected, but inactive", _device);
|
|
-- module:log("info", "handling2: %s", _tkr.token.."@".._tkr.os);
|
|
if (_tkr.os ~= "ios") then
|
|
deviceonline = true;
|
|
end
|
|
end
|
|
else
|
|
if awaiting_ack then
|
|
module:log("debug", "device %s is connected and active, but awaiting_ack", _device);
|
|
-- module:log("info", "handling3: %s", _tkr.token.."@".._tkr.os);
|
|
else
|
|
module:log("debug", "device %s is connected and active", _device);
|
|
-- module:log("info", "handling4: %s", _tkr.token.."@".._tkr.os);
|
|
if (_tkr.os ~= "ios") then
|
|
deviceonline = true;
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
if not(deviceonline) then
|
|
local already_added = contains(tokens, _tkr.token.."@".._tkr.os);
|
|
module:log("debug","already_added: %s", _tkr.token.."@".._tkr.os);
|
|
if not(tokens) then
|
|
tokens = {};
|
|
end
|
|
if not(already_added) then
|
|
table.insert(tokens, _tkr.token.."@".._tkr.os);
|
|
end
|
|
end
|
|
-- module:log("debug","tokens table is now: %s", dumpTable(tokens));
|
|
end
|
|
end
|
|
|
|
if (not tokens) then tokens = {}; end;
|
|
if (not nType) then nType = 0; end;
|
|
local sessions = prosody.bare_sessions;
|
|
local ubjid = userName.."@"..ThisDomain;
|
|
for _user, _resdetails in pairs(sessions) do
|
|
if (_user == ubjid) then
|
|
for _res, _detail1 in pairs(_resdetails["sessions"]) do
|
|
local hibernated = _detail1["hibernated"] or _detail1["hibernating"] or nil;
|
|
if (hibernated) then
|
|
module:log("info", "for _user: %s and _res: %s got hibernated since: %s", _user, _res, hibernated);
|
|
else
|
|
module:log("info", "for _user: %s and _res: %s got active session?", _user, _res);
|
|
--module:log("debug", "for _user: %s and _res: %s got detail: %s", _user, _res, dumpTable(_detail1));
|
|
end
|
|
end
|
|
-- module:log("debug", "session for _res %s is: %s", _res, dumpTable(_resdetails));
|
|
end
|
|
end
|
|
-- module:log("debug", "sessions: %s", dumpTable(sessions[ubjid]));
|
|
return nType, tokens, nLang;
|
|
end
|
|
end
|
|
|
|
local function fcm_notify(userName, title, body, type, _senderName, _groupTopic, vnc_attachment_type, msgid, vncTalkConferenceEtype, vncTalkConferenceId, _nFrom)
|
|
if (not moduleIsActive) then module:log("info", "module not active - bailung out"); return end;
|
|
module:log("info", "getting notify opts for %s", userName);
|
|
local uname, uhost = jid_split(userName);
|
|
if (uhost ~= storage_host) then return end;
|
|
local nType, tokens, lang = getNotifyOptionsForUser(uname);
|
|
if (tokens and (#tokens) > 0) and ((nType == 1) or (nType == 2))
|
|
then
|
|
-- module:log(
|
|
-- "info", "in fcm_notify(%s, %s, %s) => type=%s, %s tokens",
|
|
-- userName, title, body, tostring(nType), tostring((#tokens))
|
|
--);
|
|
local sName = _senderName;
|
|
local gTopic = _groupTopic;
|
|
sName = "Neue Nachricht";
|
|
gTopic = "Neue Nachricht";
|
|
|
|
if (lang == "en") then
|
|
sName = "new message";
|
|
gTopic = "new message";
|
|
end;
|
|
|
|
if (lang == "fr") then
|
|
sName = "Nouveau message";
|
|
gTopic = "Nouveau message";
|
|
end;
|
|
|
|
body = "";
|
|
|
|
for i,token in pairs(tokens) do
|
|
if (token)
|
|
then
|
|
local rtoken, ros = jid_split(token);
|
|
-- module:log("debug","got rtoken: %s - os: %s ", rtoken, ros);
|
|
if (ros == "ios") then
|
|
-- module:log("debug", "postFCMIOS with (%s, %s, %s, %s, %s, %s, %s, %s, %s)", userName, rtoken, title, body, type, _senderName, _groupTopic, vnc_attachment_type, lang);
|
|
postFCMIOS(userName, rtoken, title, body, type, sName, gTopic, vnc_attachment_type, lang, msgid, vncTalkConferenceEtype, vncTalkConferenceId, _nFrom);
|
|
else
|
|
-- module:log("info", "postFCM with (%s, %s, %s, %s, %s, %s, %s, %s, %s)", userName, rtoken, title, body, type, _senderName, _groupTopic, vnc_attachment_type, lang, _nFrom);
|
|
postFCM(userName, rtoken, title, body, type, sName, gTopic, vnc_attachment_type, lang, msgid, vncTalkConferenceEtype, vncTalkConferenceId, _nFrom);
|
|
end
|
|
end
|
|
end
|
|
else
|
|
module:log("debug", "fcm_notify(%s, %s, %s) => type=%s, no tokens", userName, title, body, tostring(nType));
|
|
end
|
|
end
|
|
|
|
|
|
local function handle_muc_message(event)
|
|
-- event.room and event.stanza are available
|
|
local room = event.room
|
|
local stanza = event.stanza
|
|
-- module:log("info", "handling stanza %s", stanza);
|
|
-- module:log("info", "room: %s", dumpTable(room));
|
|
|
|
local message_id = event.stanza.attr.id;
|
|
-- module:log("info","message id: %s", event.stanza.attr.id);
|
|
local type = stanza.attr.type or "normal";
|
|
local from = jid_bare(stanza.attr.from);
|
|
local to = jid_bare(stanza.attr.to) or from;
|
|
|
|
local vncTalkConferenceEtype = stanza:find("{xmpp:vnctalk}vncTalkConference/eventType#") or nil;
|
|
|
|
-- module:log("info", "handling message from=%s, to=%s", stanza.attr.from, to);
|
|
|
|
|
|
local content = trim(stanza:find("body#"));
|
|
local delayedDelivery = stanza:get_child("delay", "urn:xmpp:delay");
|
|
|
|
-- if we have a vncTalk incoming or whiteboard element, it overrides the type
|
|
local vncTalkIncomingType = stanza:find("{xmpp:vnctalk}vncTalkConference/conferenceType#");
|
|
local vncTalkConferenceId = stanza:find("{xmpp:vnctalk}vncTalkConference/conferenceId#") or nil;
|
|
local jitsiURL = stanza:find("{xmpp:vnctalk}vncTalkConference/jitsiURL#") or nil;
|
|
local jitsiRoom = stanza:find("{xmpp:vnctalk}vncTalkConference/jitsiRoom#") or nil;
|
|
local vncTalkWhiteboard = stanza:find("{xmpp:vnctalk}whiteboard");
|
|
local isSentCarbonMessage = stanza:get_child("sent", "urn:xmpp:carbons:2");
|
|
local vnc_attachment_type = stanza:find("{xmpp:vnctalk}attachment/fileType#");
|
|
|
|
local vnctalk_broadcast = stanza:get_child("vncTalkBroadcast", "xmpp:vnctalk");
|
|
local vnctalk_broadcast_childid = nil;
|
|
if vnctalk_broadcast then
|
|
if starts_with(to, "broadcast") then
|
|
-- module:log("message is to broadcast - bailing out");
|
|
return nil;
|
|
end
|
|
vnctalk_broadcast_childid = vnctalk_broadcast.attr.id;
|
|
local vnctalk_broadcast_title = vnctalk_broadcast.attr.title;
|
|
local vnctalk_broadcast_target = vnctalk_broadcast.attr.origtarget;
|
|
local body = stanza:get_child("body");
|
|
-- module:log("debug", "broadcast body: %s", content);
|
|
-- module:log("debug", "jid_split(to): %s", jid_split(to));
|
|
-- fcm_notify(jid_split(to), vnctalk_broadcast_target, content, type, getDisplayName(jid_split(from)), "Broadcast: "..vnctalk_broadcast_title, vnc_attachment_type, message_id, vncTalkConferenceEtype, vncTalkConferenceId);
|
|
return nil;
|
|
end
|
|
|
|
local auxType = vncTalkIncomingType or (vncTalkWhiteboard and "whiteboard");
|
|
|
|
if (auxType)
|
|
then
|
|
content = auxType;
|
|
type = auxType;
|
|
end;
|
|
|
|
local doNotify = content and (content ~= " ") and (content ~= "") and (delayedDelivery == nil) and (isSentCarbonMessage == nil) and (
|
|
(type == "chat") or (type == "groupchat") or (type == "audio") or (type == "video") or (type == "whiteboard") or (type == "screen")
|
|
);
|
|
|
|
if (doNotify) then
|
|
local sender = "";
|
|
for _, occupant in pairs(room._occupants) do
|
|
if (stanza.attr.from == occupant.nick) then sender=occupant.bare_jid; end;
|
|
end
|
|
-- module:log("info","sender is %s", sender);
|
|
local roomTopic = room._data.subject or nil;
|
|
for jid, aff in pairs(room._affiliations) do
|
|
if aff ~= "outcast" then
|
|
-- module:log("info", "found jid: %s as aff: %s", jid, aff);
|
|
local roomJid = to;
|
|
if (sender ~= jid) then
|
|
module:log("info", "from is: %s", from);
|
|
fcm_notify(jid, roomJid, content, type, getDisplayName(jid_split(sender)), roomTopic, vnc_attachment_type, message_id, vncTalkConferenceEtype, vncTalkConferenceId, from, jitsiURL, jitsiRoom);
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
module:hook("muc-broadcast-message", handle_muc_message)
|
|
|
|
module:hook("host-activated", function(host)
|
|
module:log("info", "got activated event for host %s", host);
|
|
end);
|
|
|
|
module:log("debug", "Module loaded")
|