This module destroys the room if the last moderator left (secure domain)
Timeout is configurable (in seconds).
If the moderator (re)joins within the specified timeout, the room will not be closed.
Make a new script file “mod_disconnect.lua” in the Prosody plugins folder (/usr/share/jitsi-meet/prosody-plugins/)
local LOGLEVEL = "debug"
local MIN = module:get_option_number("conference_timeout", 10)
local TIMEOUT = MIN
local is_healthcheck_room = module:require "util".is_healthcheck_room
local st = require "util.stanza"
local timer = require "util.timer"
module:log(LOGLEVEL, "loaded")
module:hook("muc-occupant-left", function (event)
local room = event.room
local mods = room:each_affiliation("owner");
local leaver = event.occupant.bare_jid;
local a = 0;
local b = 0;
for mod in mods do
a = a + 1;
if mod == leaver then
room:set_affiliation(true, leaver, "outcast");
a = a - 1;
end
end
for mod in mods do
module:log("info", "mods: %s", a);
if a == 1 then
if is_healthcheck_room(room.jid) then
module:log(LOGLEVEL, "skip restriction")
return
end
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("body")
:text("The conference will be terminated in "..MIN.." sec"))
module:log(LOGLEVEL, "set timeout for conference, %s secs, %s",
TIMEOUT, room.jid)
timer.add_task(TIMEOUT, function()
if is_healthcheck_room(room.jid) then
return
end
for mod in mods do
b = b + 1;
end
if b == 1 then
for _, p in room:each_occupant() do
room:set_affiliation(true, p.jid, "outcast")
module:log("info", "kick the occupant, %s", p.jid)
module:log("info", "the conference terminated")
end
else
module:log("info", "still a moderator present");
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("body")
:text("The moderator has joined. The termination of the conference was canceled."))
end
end)
end
end
end)
update:
after destroying the room, users will receive a message
local LOGLEVEL = "debug"
local MIN = module:get_option_number("conference_timeout", 10)
local TIMEOUT = MIN
local is_healthcheck_room = module:require "util".is_healthcheck_room
local st = require "util.stanza"
local timer = require "util.timer"
module:log(LOGLEVEL, "loaded")
module:hook("muc-occupant-left", function (event)
local room = event.room
local mods = room:each_affiliation("owner");
local leaver = event.occupant.bare_jid;
local a = 0;
local b = 0;
for mod in mods do
a = a + 1;
if mod == leaver then
room:set_affiliation(true, leaver, "outcast");
module:log("info", "still a moderator present");
a = a - 1;
end
end
for mod in mods do
module:log("info", "mods: %s", a);
if a == 1 then
if is_healthcheck_room(room.jid) then
module:log(LOGLEVEL, "skip restriction")
return
end
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("body")
:text("The conference will be terminated in "..MIN.." sec"))
module:log(LOGLEVEL, "set timeout for conference, %s secs, %s",
TIMEOUT, room.jid)
timer.add_task(TIMEOUT, function()
if is_healthcheck_room(room.jid) then
return
end
for mod in mods do
b = b + 1;
end
if b == 1 then
event.room:destroy();
for _, p in room:each_occupant() do
room:set_affiliation(true, p.jid, "outcast")
module:log("info", "kick the occupant, %s", p.jid)
module:log("info", "the conference terminated")
end
else
module:log("info", "still a moderator present");
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("body")
:text("A moderator has joined. The termination of the conference was canceled."))
end
end)
end
end
end)
This updated lua does not seem to work in my testing. The call terminated message is received, but the room is never destroyed. If the moderator tries to create/join the same room again, there is a “connection failed” error with no obvious error logs in prosody even in jicofo and jvb.
I don’t have such a problem.
after receiving the call terminated message, the conference time continues to run. but the conference is destroyed. and the moderator can create a new conference with the same name.
and if the moderator reconnects to the same conference before receiving the message, everything is ok too …
try updating prosody to the latest version.
I have 0.11.10-1
Hi. Thanks for the reply.
I upgraded prosody as recommended and now using the same version you posted but it’s the same.
Does it matter if I am using unstable?
Still, the 1st lua script you posted, the one without the “event.room:destroy()” function works.
I confirm that in the latest version of jitsi meet “event.room:destroy()” does not work as expected…
I’ll see what I can do.
The first version in the header (without “event.room:destroy()”) works without any problems.
local LOGLEVEL = "debug"
local MIN = module:get_option_number("conference_timeout", 10)
local TIMEOUT = MIN
local is_healthcheck_room = module:require "util".is_healthcheck_room
local st = require "util.stanza"
local timer = require "util.timer"
module:log(LOGLEVEL, "loaded")
module:hook("muc-occupant-left", function (event)
local room = event.room
local mods = room:each_affiliation("owner");
local leaver = event.occupant.bare_jid;
local a = 0;
local b = 0;
for mod in mods do
a = a + 1;
if mod == leaver then
room:set_affiliation(true, leaver, "outcast");
module:log("info", "still a moderator present");
a = a - 1;
end
end
for mod in mods do
module:log("info", "mods: %s", a);
if a == 1 then
if is_healthcheck_room(room.jid) then
module:log(LOGLEVEL, "skip restriction")
return
end
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text("The conference will be terminated in "..MIN.." sec"))
module:log(LOGLEVEL, "set timeout for conference, %s secs, %s",
TIMEOUT, room.jid)
timer.add_task(TIMEOUT, function()
if is_healthcheck_room(room.jid) then
return
end
for mod in mods do
b = b + 1;
end
if b == 1 then
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text("THE CONFERENCE IS OVER"))
local start = os.clock()
while os.clock() - start < 3 do end
for _, p in room:each_occupant() do
room:set_affiliation(true, p.jid, "outcast")
module:log("info", "kick the occupant, %s", p.jid)
module:log("info", "the conference terminated")
end
else
module:log("info", "still a moderator present");
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text(roomName))
end
end)
end
end
end)
slightly corrected the code in the previous post.
if the moderator has rejoined, the upper message about the termination of the conference is changed to the name of the room.
fixed:
for some users the message “conference is over” was replaced by the previous one about the end of the conference after 15 seconds
updated code:
local LOGLEVEL = "debug"
local MIN = module:get_option_number("conference_timeout", 10)
local TIMEOUT = MIN
local is_healthcheck_room = module:require "util".is_healthcheck_room
local st = require "util.stanza"
local timer = require "util.timer"
module:log(LOGLEVEL, "loaded")
module:hook("muc-occupant-left", function (event)
local room = event.room
local mods = room:each_affiliation("owner");
local leaver = event.occupant.bare_jid;
local a = 0;
local b = 0;
for mod in mods do
a = a + 1;
if mod == leaver then
room:set_affiliation(true, leaver, "outcast");
module:log("info", "still a moderator present");
a = a - 1;
end
end
for mod in mods do
module:log("info", "mods: %s", a);
if a == 1 then
if is_healthcheck_room(room.jid) then
module:log(LOGLEVEL, "skip restriction")
return
end
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text("The conference will end in "..MIN.." sec"))
module:log(LOGLEVEL, "set timeout for conference, %s secs, %s",
TIMEOUT, room.jid)
timer.add_task(TIMEOUT, function()
if is_healthcheck_room(room.jid) then
return
end
for mod in mods do
b = b + 1;
end
if b == 1 then
for _, p in room:each_occupant() do
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text("THE CONFERENCE IS OVER"))
room:set_affiliation(true, p.jid, "outcast")
module:log("info", "kick the occupant, %s", p.jid)
module:log("info", "the conference terminated")
end
else
module:log("info", "still a moderator present");
room:broadcast_message(
st.message({ type="groupchat", from=room.jid })
:tag("subject")
:text(roomName))
end
end)
end
end
end)
Hi,
I’m hooking up to this post to ask you something.
If I wanted to send a broadcast message, which comes to me from prosody, to all the participants in the lobby room, what could I do?
I have a version of Jisti without the ConferenceInfo class …
Hi @DmDS@damencho and everyone else, I use mod_reservations.lua and mod_disconnect.lua
with a secure domain mechanism and I can guarantee both that the room is opened by an authorized person (owner of that room name) and that when it is closed, the timeout is started (60sec for us) and at the end of this all the participants are expelled from the room.
The timeout system allows the moderator to re-enter his room and keep it alive in case of a mistaken exit.
But there is a problem:
“A” tries to start a room that is not hers. The system blocks it. CORRECT
“A” enters his room. CORRECT
“B” joins "A "'s room. CORRECT
“A” leaves her room and “B” stays inside until the timeout has elapsed. CORRECT
“A” starts another room that is not hers and manages to do so by becoming its moderator. NOT CORRECT
After step 2. “A” in console receives an exception: onConferenceFaild Authentication Require
After point 5. “A” doesn’t get that exception and I think it’s because Prosody sees it authenticated (reservation active until her room is destroyed) and then lets her start the new room …
Does he go back there?
While maintaining the timeout system, I would like moderator “A” once he leaves his room to be able to enter another as a participant without becoming a moderator. Should I destroy the reservation of his previous room? Do you have any suggestions for me?
Sounds like it could be related to this issue, where mod_reservation is bypassed if user joins on guest domain but is recognised by jicofo as a previously logged in user and gets granted moderator rights:
That would be tricky if you use Secure Domain since by design Jicofo will give moderator rights to all authenticated users. You’ll need a custom prosody module if want finer grained control over that.