167 lines
6.9 KiB
Lua
167 lines
6.9 KiB
Lua
-- Prosody IM
|
|
-- Copyright (C) 2008-2017 Matthew Wild
|
|
-- Copyright (C) 2008-2017 Waqas Hussain
|
|
-- Copyright (C) 2011-2017 Kim Alvefur
|
|
-- Copyright (C) 2011-2017 Stefan Sänger
|
|
--
|
|
-- This project is MIT/X11 licensed. Please see the
|
|
-- COPYING file in the source package for more information.
|
|
--
|
|
-- store groupchat messages from / to remote hosts based on mod_mam
|
|
--
|
|
|
|
local um = require "core.usermanager";
|
|
local st = require "util.stanza";
|
|
local rsm = require "util.rsm";
|
|
local jid_bare = require "util.jid".bare;
|
|
local jid_split = require "util.jid".split;
|
|
local jid_prepped_split = require "util.jid".prepped_split;
|
|
local host = module.host;
|
|
|
|
module:log("running on host: %s", host);
|
|
|
|
local archive_store = "muc_remote";
|
|
local archive = module:open_store(archive_store, "archive");
|
|
local mr_store = module:open_store("muc_remote", "map");
|
|
|
|
|
|
local time_now = os.time;
|
|
local m_min = math.min;
|
|
local timestamp, timestamp_parse = require "util.datetime".datetime, require "util.datetime".parse;
|
|
|
|
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 presence_handler(event,c2s)
|
|
local origin, stanza = event.origin, event.stanza;
|
|
local muc_child = (stanza:get_child("x", "http://jabber.org/protocol/muc#user") or nil);
|
|
local item_child = nil;
|
|
local presence_type = (stanza.attr.type or nil);
|
|
local from_node, from_host, from_res = jid_split(stanza.attr.from);
|
|
local to_node, to_host = jid_split(stanza.attr.to);
|
|
if not (prosody.hosts[from_host]) then
|
|
if (muc_child and not(presence_type)) then
|
|
item_child = muc_child:get_child("item");
|
|
if (item_child) then
|
|
-- module:log("info", "got muc presence from: %s - to: %s, jid: %s || raw: %s", stanza.attr.from, stanza.attr.to, jid_bare(item_child.attr.jid), tostring(stanza));
|
|
if (item_child.attr.jid) then
|
|
local fjid = stanza.attr.from;
|
|
if (stanza.attr.from == jid_bare(stanza.attr.from)) then
|
|
fjid = stanza.attr.from .. "/" .. jid_bare(item_child.attr.jid);
|
|
end
|
|
-- module:log("info", "got item... from= %s item.attr.jid= %s", fjid, jid_bare(item_child.attr.jid));
|
|
mr_store:set(to_node, fjid, jid_bare(item_child.attr.jid));
|
|
end
|
|
if (from_res) then
|
|
mr_store:set(to_node,stanza.attr.from, from_res);
|
|
-- module:log("info", "got muc presence from_res: %s - to: %s, jid: %s || raw: %s", stanza.attr.from, stanza.attr.to, from_res, tostring(stanza));
|
|
end
|
|
end
|
|
-- mr_store:set(to_node,stanza.attr.from, );
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Handle messages
|
|
local function message_handler(event, c2s)
|
|
local origin, stanza = event.origin, event.stanza;
|
|
|
|
if stanza.attr.type == "groupchat" then
|
|
local from_node, from_host, from_res = jid_split(stanza.attr.from);
|
|
local remote_muc = from_node.."@"..from_host;
|
|
local to_node, to_host, to_res = jid_split(stanza.attr.to);
|
|
-- module:log("info", "seen from_host: %s", from_host);
|
|
-- module:log("info", "seen to_res: %s", to_res);
|
|
if prosody.hosts[from_host] then
|
|
-- message is from a local host, no further action required
|
|
module:log("debug", "seen stanza from local host - from: %s", stanza.attr.from);
|
|
-- return nil;
|
|
else
|
|
-- message is from remote host, going to handle...
|
|
-- module:log("info", "seen stanza with muc %s@%s - raw: %s - to %s with type %s with id %s", from_node, from_host, stanza.attr.from, stanza.attr.to, stanza.attr.type, stanza.attr.id);
|
|
local mkey = stanza.attr.id;
|
|
local muc_with = from_node.."@"..from_host;
|
|
local content = (stanza and stanza:get_child("body") and stanza:get_child("body")[1] or nil)
|
|
-- module:log("info","got content: %s", content);
|
|
local delayedDelivery = stanza:get_child("delay", "urn:xmpp:delay");
|
|
if (delayedDelivery) then
|
|
-- module:log("info","got delay: %s", delayedDelivery);
|
|
end
|
|
local muc_subject = (stanza:get_child_text("subject") or nil);
|
|
if (muc_subject) then
|
|
-- module:log("info","subject for %s: %s", stanza.attr.from, muc_subject);
|
|
mr_store:set(to_node, remote_muc, muc_subject);
|
|
end
|
|
local nick = (stanza:get_child_text("nick", "http://jabber.org/protocol/nick") or nil);
|
|
local muc_child = (stanza:get_child("x", "http://jabber.org/protocol/muc#user") or nil);
|
|
local item_child = nil;
|
|
if (muc_child) then
|
|
-- module:log("info","got muc_child: %s", muc_child);
|
|
item_child = muc_child:get_child("item");
|
|
if (item_child and nick) then
|
|
-- module:log("info","got sender jid nick: %s: %s => %s", stanza.attr.from, nick, item_child.attr.jid);
|
|
mr_store:set(to_node,stanza.attr.from, item_child.attr.jid);
|
|
end
|
|
end
|
|
|
|
if (mkey and content and not(delayedDelivery)) then
|
|
-- module:log("info", "seen stanza with muc %s@%s - raw: %s - to %s with type %s with id %s", from_node, from_host, stanza.attr.from, stanza.attr.to, stanza.attr.type, stanza.attr.id);
|
|
-- module:log("info", "going to store - to: %s, conten: %s", to_node, content);
|
|
local storeok = archive:append(to_node, mkey, stanza, time_now(), muc_with);
|
|
-- prevent further processing for messages to offline user (to bare jid)
|
|
if (to_res == nil) then
|
|
-- module:log("info", "going prevent stanza processing to bare from muc - to: %s, conten: %s", to_node, content);
|
|
return true;
|
|
end
|
|
end
|
|
end
|
|
else
|
|
-- module:log("info","seen stanza.attr.type: %s", stanza.attr.type);
|
|
local from_node, from_host, from_res = jid_split(stanza.attr.from);
|
|
local to_node, to_host, to_res = jid_split(stanza.attr.to);
|
|
local muc_child = (stanza:get_child("x", "http://jabber.org/protocol/muc#user") or nil);
|
|
local invite_child = nil;
|
|
local invite_from = nil;
|
|
if (muc_child) then
|
|
invite_child = (muc_child:get_child("invite") or nil);
|
|
if (invite_child) then
|
|
module:log("info", "got invite_child: %s", dumpTable(invite_child));
|
|
invite_from = (invite_child.attr.from or nil);
|
|
if (invite_from) then
|
|
local invite_from_node, invite_from_host = jid_split(invite_from);
|
|
module:log("info","got invite from %s to muc %s for %s", invite_from_node.."@"..invite_from_host, stanza.attr.from, to_node.."@"..to_host );
|
|
local store_key = stanza.attr.from.."/"..invite_from_node.."@"..invite_from_host;
|
|
local store_value = invite_from_node.."@"..invite_from_host;
|
|
-- module:log("debug","storing: %s -> %s -> %s", to_node, stanza.attr.from.."/"..invite_from_node.."@"..invite_from_host, invite_from_node.."@"..invite_from_host);
|
|
mr_store:set(to_node, store_key, store_value);
|
|
else
|
|
module:log("info","found empty part - check %s", invite_from);
|
|
end
|
|
end
|
|
|
|
|
|
end
|
|
end
|
|
end
|
|
|
|
-- Stanzas to local clients
|
|
module:hook("message/bare", message_handler, 0);
|
|
module:hook("message/full", message_handler, 0);
|
|
module:hook("presence/full", presence_handler, 10);
|
|
module:hook("presence/bare", presence_handler, 10);
|