Close room properly (prosody custom module)

I didn’t check in detail but the prosody devs have created an util.async to work around such limitations, see https://prosody.im/doc/developers/util/async
Maybe this can help to delay the room destruction?

So here is a prosody module that will destroy the conference room after 30 seconds if a moderator leaves the room and no other moderator is present (or rejoins before the 30 seconds are up). Prerequisite is of course that authentication is setup and working.

local async = require "util.async";
local timer = require "util.timer"; 

local delay = module:get_option_number("close_room_delay", 30);
local focus_jid = module:get_option_string("focus_user_jid", "focus@auth.meet.jitsi");

module:log("info","module loaded");

local async_destroy = async.runner(function (event)
	local leaver = event.occupant.bare_jid;
	local room = event.room;
    local wait, done = async.waiter();


    timer.add_task(delay, function ()
       done();
    end);
    wait(); -- Wait here until done() is called
    
    local mods = room:each_affiliation("owner");
    for mod in mods do
        module:log("debug", "owner found: %s", tostring(mod));
 	    if mod ~= leaver and mod ~= focus_jid then
            -- there is still a moderator in this room, dont kick participants
            module:log("info", "still a moderator present: %s", mod);
	        return
        end
    end
    event.room:clear();
    event.room:destroy();
    module:log("info", "room destroyed.");
end);

module:hook("muc-occupant-left", function(event)
    local barejid = event.occupant.bare_jid;
    local role =  event.room:get_affiliation(barejid);
    module:log("debug", "occupant with role %s left: %s", role, barejid);
    if role == "owner" and barejid ~= "focus@auth.meet.jitsi" then
        async_destroy:run(event);
    end
end,150)

It would probably be a good idea to make a config option out of the delay interval and the focus user’s JID. You’ll need to adjust the focus user focus@auth.meet.jitsi to match your configuration, check for the admin user in your prosody config.
EDIT: I updated the code above to make the delay interval and the focus user configurable. To make use of this, add to your prosody config the options:

close_room_delay = 30;  -- seconds until conference is destroyed after last moderator left
focus_user_jid = "focus@meet.jitsi";  -- JID of your focus/jicofo user. Should be same as in 'admins' array 

Does anybody have a good idea how to add the UI redirect posted above by @hkhait if Jitsi is not used in an iFrame?

Hey @serelsnauw ,
I also used this code snippet from @plokta plotka and saved it in /usr/share/jitsi-meet/prosody-plugins/mod_quit.lua

module:hook("muc-occupant-left", function(event)
    local barejid = event.occupant.bare_jid;
    local role =  event.room:get_affiliation(barejid);
    if role == "owner" and barejid ~= "focus@auth.meet.jitsi" then
        --FIRE OTHER PARTICIPANTS FIRST
        module:log("info", "kick");
        event.room:clear();
        --Destroy Room
        module:log("info", "kill");
        event.room:destroy();
    end
end,150)

I enabled it in /etc/prosody/conf.d/“domain”.cfg.lua in the conference component:

Component "conference.domain" "muc"
    storage = "memory"
    modules_enabled = {
        "muc_meeting_id";
        "muc_domain_mapper";
        "force_room_password";
        "quit";
        -- "token_verification";
    }
    admins = { "focus@auth.domain" }
    muc_room_locking = false
    muc_room_default_public_jids = true

In the prosody logs:
“kill” and “kick”
are shown. But the room is not destroyed when the moderator leaves…

Does anyone have an idea?

Bests!

Make sure to adjust the code by replacing "focus@auth.meet.jitsi" with "focus@auth.domain" as in your admins = { } configuration. Or use the updated code from this post and add the config options accordingly.

Can you be more specific about what happens and what you expected to happen? Did you test for p2p conferences only or also with multiple participants? Are there any errors in you prosody error log?

Furthermore, note that the participants will not be redirected to another page unless you implement that in the frontend. This module just kills the prosody conference, so participants will lose connection to each other but still remain on the same website.

Hey thanks for the quick response!

I already did, i just copied the snippet you posted earlier.

Furthermore, note that the participants will not be redirected to another page unless you implement that in the frontend. This module just kills the prosody conference, so participants will lose connection to each other but still remain on the same website.

I just tested with this p2p. I have tested it know with multiple participants and the room is destroyed. I thought the others in the conference would be redirected.
So it works! Thanks again.

Is there a way to redirect the participants when the room is destroyed via prosody!

I trided to setup normal jitsi setup on ununtu but i had problems with token several times, so this time i installed docker jitsi. How can i install “Close room module” on docker system?

And second question, is it possible to show countdown popup to users like “Moderator left room will be closed in XXX seconds”, when moderator left room?

In your docker-jitsi-meet configuration folder (defaults to ~/.jitsi-meet-config/) under the prosody subfolder create a new folder prosody-plugins-custom and in this folder create a new file called mod_close_rooms.lua. Paste the code posted above into this file and save.

In the prosody config conf.d/meet.your-domain.cfg look for the MUC component of your server, probably something like Component "conference.your-domain.com" "muc" and add "close_rooms"; to the modules_enabled array.

Component "conference.your-domain.com" "muc"
    storage = "memory"
    modules_enabled = {
        "close_rooms";
    }

Also add the lines

close_room_delay = 30;  -- seconds until conference is destroyed after last moderator left
focus_user_jid = "focus@meet.your-domain.com";  -- JID of your focus/jicofo user. Should be same as in 'admins' array 

to the prosody config, right below of the modules_enabled array (actually, it should not matter, where in the file these options are placed).

To restart prosody run sudo docker-compose restart prosody from your docker-jitsi-meet folder

This would require additional and probably non-trivial changes in the frontend. Of course, as the code is open source anything is possible if you find someone who implements it :wink:

EDIT: Just noted that I mixed up the configuration folder with the docker-jitsi-meet folder in the first sentence.

1 Like

Thank you plokta for your answer, but i have also same error as fellow12312

it is closing connection, but not closing conferance room gui/not returning to lobby
only closing p2p connection

I just used the util.timer that you referenced instead of both async and timer to get the job done. It looks like the timer is executing in an async mode, ie:
Function …

timer.add_task(60, function () log(“debug”, “Hello1!”) end);
timer.add_task(30, function () log(“debug”, “Hello2!”) end);
End
Hello2 will execute first at 30 secs and then Hello1 at 60 secs but both will occur after the calling function has exited so no operations are blocked. Thus I did not see the need for util.async if I am using timer. Please let me know if I am mistaken. And thank you for your code it was very helpful.

Great finding! I have to admit that I did not even try to only use timer.add(). After skimming through the prosody documentation I presumed using the async functions was required.

Have you been able to catch any client side events about the destroyed conference, i.e. CONFERENCE_FAILED? I’ve tried using addConferenceListener() as posted by @hkhait above but I never seem to receive any event at all…

I did finish my client side implementation and it works cleanly. Much better that the room.clear() and room.destroy(). I did not need to use the listener. Before I show you how I implemented let me explain what my goal was.

Goal: I wanted to limit my duration of call to a max time and also limit the amount of time we have less than the required number of occupants for a given time. The easiest way to limit was to disconnect every one individually client side.

Implementation: (I will list for someone who is getting mixed up with which code where)

  • In /usr/share/jitsi-meet/ create a file myname_conf.js
  • In /usr/share/jitsi-meet/index.html add this line … -#include virtual="/myname_conf_q.js" … and also add the myname_conf.js to the var critical files (not sure if this last one needs to be done).
  • In myname_conf.js add code to use a timer
    var timer;
    var ms = 60000; // this is one minute
    var occCount = 0;
    var mins = 0;
    … add what ever vars you need
    function startCounting(){…
    min = min +1;
    occCount = APP.conference.membersCount; // this is working

    // Do whatever you want with the time and members count
    // To redirect to home page from here is simple
    document.location.href="/";
    setTimeout(startCounting, ms); // the function calls itself before exiting
    }
    // you should be able to APP.conference.addConferenceListener in this file - i have not tired
    timer = setTimeout(startCounting, ms);
  • You do not need to restart anything when you do this just go straight to testing after you save the js file.

Hope this helps.

1 Like

Please see my post above this should help you redirect to home page.
document.location.href="/";

Can someone please tell me why I keep getting this error on my prososdy.log when I try to clear room. Is it because the occupants are all owners and moderators?
timer error Traceback[timer]: /usr/share/jitsi-meet/prosody-plugins/mod_quit.lua:63: attempt to index local ‘stanza’ (a nil value)
/usr/share/jitsi-meet/prosody-plugins/mod_quit.lua:63: in function ‘?’
/usr/lib/prosody/util/events.lua:79: in function </usr/lib/prosody/util/events.lua:75>
(…tail calls…)
/usr/lib/prosody/modules/muc/muc.lib.lua:882: in function ‘clear’
/usr/share/jitsi-meet/prosody-plugins/mod_quit.lua:27: in function ‘delayedCounter’
/usr/share/jitsi-meet/prosody-plugins/mod_quit.lua:25: in function </usr/share/jitsi-meet/prosody-plugins/mod_quit.lua:25>
[C]: in function ‘xpcall’
/usr/lib/prosody/util/timer.lua:39: in function ‘callback’
/usr/lib/prosody/net/server_select.lua:876: in function ‘?’
/usr/lib/prosody/net/server_select.lua:907: in function </usr/lib/prosody/net/server_select.lua:899>
[C]: in function ‘xpcall’
/usr/bin/prosody:80: in function ‘loop’
/usr/bin/prosody:90: in main chunk
[C]: in ?

Hey.
I tried to add clientside javascript to do the redirection.
I created the file: /usr/share/jitsi-meet/quit_conf.js with the following code:

In index.html I added the script
<script><!--#include virtual="/quit_conf.js" --></script><!-- add quit conference script -->

And I also added it to the var critical files.

Via console.log… I confirmed that the module is loaded.
But I get an error

script loaded

TypeError: H is undefined[conference.js:2512:8](webpack:///conference.js)

addConferenceListener conference.js:2512

<anonym>

Do you have any idea why the “APP.conference.addConferenceListener…”-part is not working?
I destroy the room when the moderator leaves as descriped in Close room properly (prosody custom module) and Close room properly (prosody custom module)

Bests!