jiti-meet/resources/prosody-plugins/mod_muc_call.lua

119 lines
4.0 KiB
Lua

local ext_events = module:require "ext_events"
local jid = require "util.jid"
-- Options and configuration
local poltergeist_component = module:get_option_string(
"poltergeist_component",
module.host
);
local muc_domain_base = module:get_option_string("muc_mapper_domain_base");
if not muc_domain_base then
module:log(
"warn",
"No 'muc_domain_base' option set, unable to send call events."
);
return
end
-- Status strings that trigger call events.
local calling_status = "calling"
local busy_status = "busy"
local rejected_status = "rejected"
local connected_status = "connected"
local expired_status = "expired"
-- url_from_room_jid will determine the url for a conference
-- provided a room jid. It is required that muc domain mapping
-- is enabled and configured. There are two url formats that are supported.
-- The following urls are examples of the supported formats.
-- https://meet.jit.si/jitsi/ProductiveMeeting
-- https://meet.jit.si/MoreProductiveMeeting
-- The urls are derived from portions of the room jid.
local function url_from_room_jid(room_jid)
local node, _, _ = jid.split(room_jid)
if not node then return nil end
local target_subdomain, target_node = node:match("^%[([^%]]+)%](.+)$")
if not(target_node or target_subdomain) then
return "https://"..muc_domain_base.."/"..node
else
return "https://"..muc_domain_base.."/"..target_subdomain.."/"..target_node
end
end
-- Listening for all muc presences stanza events. If a presence stanza is from
-- a poltergeist then it will be further processed to determine if a call
-- event should be triggered. Call events are triggered by status strings
-- the status strings supported are:
-- -------------------------
-- Status | Event Type
-- _________________________
-- "calling" | INVITE
-- "busy" | CANCEL
-- "rejected" | CANCEL
-- "connected" | CANCEL
module:hook(
"muc-broadcast-presence",
function (event)
-- Detect if the presence is for a poltergeist or not.
if not (jid.bare(event.occupant.jid) == poltergeist_component) then
return
end
-- A presence stanza is needed in order to trigger any calls.
if not event.stanza then
return
end
local call_id = event.stanza:get_child_text("call_id")
if not call_id then
module:log("info", "A call id was not provided in the status.")
return
end
local invite = function()
local url = assert(url_from_room_jid(event.stanza.attr.from))
ext_events.invite(event.stanza, url, call_id)
end
local cancel = function()
local url = assert(url_from_room_jid(event.stanza.attr.from))
local status = event.stanza:get_child_text("status")
ext_events.cancel(event.stanza, url, string.lower(status), call_id)
end
-- If for any reason call_cancel is set to true then a cancel
-- is sent regardless of the rest of the presence info.
local should_cancel = event.stanza:get_child_text("call_cancel")
if should_cancel == "true" then
cancel()
return
end
local missed = function()
cancel()
ext_events.missed(event.stanza, call_id)
end
-- All other call flow actions will require a status.
if event.stanza:get_child_text("status") == nil then
return
end
local switch = function(status)
case = {
[calling_status] = function() invite() end,
[busy_status] = function() cancel() end,
[rejected_status] = function() missed() end,
[expired_status] = function() missed() end,
[connected_status] = function() cancel() end
}
if case[status] then case[status]() end
end
switch(event.stanza:get_child_text("status"))
end,
-101
);