Get the list of rooms

now i have update to JVB2 i get this in the log (tried to update prosody to 11.5 but no effect)

Apr 01 08:47:27 http.server     error   Traceback[httpserver]: /usr/share/jitsi-meet/prosody-plugins/mod_muc_size.lua:259: attempt to call upvalue 'wrap_async_run' (a nil value)
stack traceback:
        /usr/share/jitsi-meet/prosody-plugins/mod_muc_size.lua:259: in function '?'
        /usr/lib/prosody/util/events.lua:79: in function </usr/lib/prosody/util/events.lua:75>
        (...tail calls...)
        /usr/lib/prosody/net/http/server.lua:248: in function </usr/lib/prosody/net/http/server.lua:176>
        [C]: in function 'xpcall'
        /usr/lib/prosody/net/http/server.lua:108: in function 'process_next'
        /usr/lib/prosody/net/http/server.lua:124: in function 'success_cb'
        /usr/lib/prosody/net/http/parser.lua:177: in function 'feed'
        /usr/lib/prosody/net/http/server.lua:155: in function </usr/lib/prosody/net/http/server.lua:154>
        (...tail calls...)
        /usr/lib/prosody/net/server_select.lua:915: in function </usr/lib/prosody/net/server_select.lua:899>
        [C]: in function 'xpcall'
        /usr/bin/prosody:76: in function 'loop'
        /usr/bin/prosody:86: in main chunk
        [C]: in ?

There seems to be some changes, replace the following code.

function tablelength(T)
        local hash = {}
        local res = {}

        for _,v in ipairs(T) do
           if (not hash[v]) then
               res[#res+1] = v
               hash[v] = true
           end
        end

        local count = 0
        for _ in pairs(res) do count = count + 1 end
        return count
end

local function has_value (tab, val)
    for index, value in ipairs(tab) do
        if value == val then
            return true
        end
    end

    return false
end

function getNbConfPart(event) 
	
	local params = parse(event.request.url.query);
	
    local tab={};
	local jitsi_meet_room = "";
	local nbPart = 0
	local roomscount = 0;
	
	
	if not verify_token_getrooms(params["token"]) then
        return 403;
    end
    
    
    --conference rooms count (with eliminating duplicates )
    for key, value in pairs(prosody.full_sessions) do
            if (tostring(value["username"]:lower()) ~= "focus" and tostring(value["username"]:lower()) ~= "jibri" and value["jitsi_meet_room"] ~= nil) then
	            log("info", "room %s", tostring(value));
	            
--	            for k,v in pairs(value) do
--		            log("info", "key %s", tostring(k));
--		            log("info", "value %s", tostring(v));
--		        end
		        jitsi_meet_room = tostring(value["jitsi_meet_room"]:lower());
		        nbPart = nbPart + 1;
		        
		        if (tab[tostring(jitsi_meet_room)]  ~= nil) then
					tab[tostring(jitsi_meet_room)] = tab[tostring(jitsi_meet_room)] + 1;
			    	log("info", "room %s already in table", tostring(jitsi_meet_room));
			        
			    else
                    
			        tab[tostring(jitsi_meet_room)] = 1
					roomscount = roomscount + 1;
                end
            end
    end

 

    

     --create result as json
    local result_json={
                    participants= nbPart,
                    roomscount = roomscount,
                    rooms = tab
                    
            };

    -- create json response 
    return { status_code = 200; body = json.encode(result_json); };
end

function module.load()
    module:depends("http");
	module:provides("http", {
		default_path = "/";
		route = {
			["GET room-size"] = function (event) return async_handler_wrapper(event,handle_get_room_size) end;
			["GET sessions"] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
			["GET room"] = function (event) return async_handler_wrapper(event,handle_get_room) end;
			["GET nbConfPart"] = function (event) return async_handler_wrapper(event,getNbConfPart) end;
		};
	});
end
1 Like

Hi rubenm,

I tried your code, and I think value["jitsi_meet_room"] is not used anymore.
I might be wrong, but `/sessions’ give the right amount of users (off by 2) but nbConfPart gives none.

You are right, value[“jitsi_bosh_query_room”] seems to be correct.

1 Like

Any updates here? It doesnt work for me!
This is my setup:

  • Ubuntu 18.04.4 LTS.
  • Prosody 0.11.5
  • Lua 5.2
  • LuaRocks 2.4.2

Installed rocks:
basexx
0.4.1-1 (installed) - /usr/local/lib/luarocks/rocks
lbase64
20120807-3 (installed) - /usr/local/lib/luarocks/rocks
lua-cjson
2.1.0-1 (installed) - /usr/local/lib/luarocks/rocks
luacrypto
0.3.2-2 (installed) - /usr/local/lib/luarocks/rocks
luajwtjitsi
1.3-7 (installed) - /usr/local/lib/luarocks/rocks
net-url
0.9-1 (installed) - /usr/local/lib/luarocks/rocks

Everything works fine in muc_size. But with the lates posted version of getNbConfPart I am not able to fetch the data. I always get:

{“rooms”:{},“participants”:0,“roomscount”:0}

I tried to uncomment the commented logging part:

			for k,v in pairs(value) do
				log("info", "key %s", tostring(k));
				log("info", "value %s", tostring(v));
			end

If i look in my logs and grab for my roomname i got no match.
Many keys and values are logged but no roomname.

There is no key like “jitsi_bosh_query_room” or “jitsi_meet_room” although there should be atleast one. The outputs of all other endpoints in muc_size are fine. The room endpoint and the room-size endpoint are working well. So the internal call get_room_from_jid(room_address); returns the correct room.

How is the roomname addressed in full_sessions object?

Ok, I solved it on my own but took a different approach.

I inspected the folowing files:
https://github.com/jitsi/jitsi-meet/blob/master/resources/prosody-plugins/util.lib.lua
https://github.com/bjc/prosody/blob/master/plugins/muc/mod_muc.lua

I saw that get_room_from_jid in jitsi-meets util.lib.lua was implmented by calling get_room_from_jid from MUC API (>0.10). So i opened prosodys mod_muc.lua and found this method. But I found another method, too. It was all_rooms! And it returns a list of all rooms. Each room object in this list is holding an occupants object and this what the builtin method handle_get_room is inspecting. (Take a look the orignial muc_size module)

So I tried a little bit and got it:

	function get_raw_rooms(ahost)
		local component = hosts[ahost];
		if component then
			local muc = component.modules.muc
			if muc and rawget(muc,"all_rooms") then
				return muc.all_rooms();
			end
		end
	end
	
	function handle_get_all_rooms(event)
		if (not event.request.url.query) then
			return { status_code = 400; };
		end
	
		local params = parse(event.request.url.query);
		local domain_name = params["domain"];
	
		local raw_rooms = get_raw_rooms(domain_name);
	
		local rooms_json = array();
	
		for room in raw_rooms do
	
			local room_jid = room.jid;
			local participant_count = 0;
			local occupants_json = array();
			local occupants = room._occupants;
			if occupants then
				for _, occupant in room:each_occupant() do
					-- filter focus as we keep it as hidden participant
					if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
						for _, pr in occupant:each_session() do
							participant_count = participant_count + 1;
							local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "";
							local email = pr:get_child_text("email") or "";
							occupants_json:push({
								jid = tostring(occupant.nick),
								email = tostring(email),
								display_name = tostring(nick)});
						end
					end
				end
			end
	
			rooms_json:push({
				jid = room_jid,
				participant_count = participant_count,
				participants = occupants_json
			});
	
		end
	
		local result_json={
			rooms = rooms_json;
		};
		-- create json response
		return { status_code = 200; body = json.encode(result_json); };
	end

Now the new method needs to be routed:

function module.load()
	module:depends("http");
	module:provides("http", {
		default_path = "/";
		route = {
			["GET room-size"] = function (event) return async_handler_wrapper(event,handle_get_room_size) end;
			["GET sessions"] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
			["GET room"] = function (event) return async_handler_wrapper(event,handle_get_room) end;
			["GET all-rooms"] = function (event) return async_handler_wrapper(event,handle_get_all_rooms) end;
		};
	});
end

I am able to receive the list of all rooms by curl request:

curl 'http://localhost:5280/all-rooms?domain=conference.jitsi-meet.example.com' -i

Be careful! Although my domain is jitsi-meet.example… I need to request conference.jitsi-meet.example… because my get_raw_rooms function is not respecting the muc_mapper_domain_prefix. This needs to be implemented like jitsi-meets util.lib.lua did.

I hope this helps anybody and maybe it will find its way into the jitsi source code or maybe we can offer a module by ourself.

5 Likes

Great job tmaass, i have open a new post with some improvment

next step, finding a dump of prosody.full_session…

Please add full tutorial step by step, how to make this thing work.

2 Likes

New Error When I try to install: luajwtjitsi

Error: Failed installing dependency: http://rocks.moonscript.org/luacrypto-0.3.2-2.src.rock - Build error: Failed compiling object src/lcrypto.o

And when i try to install luacrypto:
Error: Build error: Failed compiling object src/lcrypto.o

luacrypto 0.3.2-2 depends on lua >= 5.1 (5.2-1 provided by VM)

Please look at my setup. I struggled around with that, too. Finally I had success with that setup above.

I edited the code a bit. If someone has use for this, here it is. Comments welcome.

local log = module._log;
local async_handler_wrapper = module:require "util".async_handler_wrapper;
local json = require "util.json";

function getNbConfPart()
    local result={};

    for key, value in pairs(prosody.full_sessions) do
            if value["jitsi_bosh_query_room"] then
                if result[value["jitsi_bosh_query_room"]] then
                        result[value["jitsi_bosh_query_room"]] = result[value["jitsi_bosh_query_room"]] + 1;
                else
                        result[value["jitsi_bosh_query_room"]] = 1;
                end
            end
    end

    return { status_code = 200; body = json.encode(result); };
end

function module.load()
    module:depends("http");
        module:provides("http", {
                default_path = "/";
                route = {
                        ["GET nbConfPart"] = function (event) return async_handler_wrapper(event,getNbConfPart) end;
                };
        });
end
2 Likes

Hi, I also installed JVB2 and enabled jwt auth, got the same problem

with prosody err :Apr 01 08:47:27 http.server error Traceback[httpserver]: /usr/share/jitsi-meet/prosody-plugins/mod_muc_size.lua:259: attempt to call upvalue ‘wrap_async_run’ (a nil value)
stack traceback:

How do you solve it?

https://example.com/sessions (it’s OK ,and return 2)
https://example.com/room-info?room=123 (return 500 Internal Server Error)

Is there a way to get this info from command line on the server where it’s running? Sounds like a lot of hassle to go through to get this info.

Yes, you can execute a curl from command line on your local machine:

 # curl 'http://localhost:5280/all-rooms?domain=conference.your.domain.com'

But you need to activate your module with the posted modifications before.
If you want just to use it like this you need not to route your ngix to make the request accessable from outside.

Ya, I get that… but I am sure the developers must have added ways to monitor things! Basic monitoring shouldn’t need additional code. It sounds more like a hack to me.

Sorry, i am not familar with that. I searched a lot and i found no other solution.

1 Like

I found this: https://github.com/jitsi/jitsi-videobridge/blob/master/doc/statistics.md

Any one knows how to query a room to see if it is password protected or not ?

As per the code you mentioned I created mod_muc_test.lua in /usr/share/jitsi-meet/prosody-plugins

local log = module._log;
local async_handler_wrapper = module:require “util”.async_handler_wrapper;
local json = require “util.json”;

function get_raw_rooms(ahost)
	local component = hosts[ahost];
	if component then
		local muc = component.modules.muc
		if muc and rawget(muc,"all_rooms") then
			return muc.all_rooms();
		end
	end
end

function handle_get_all_rooms(event)
	if (not event.request.url.query) then
		return { status_code = 400; };
	end

	local params = parse(event.request.url.query);
	local domain_name = params["domain"];

	local raw_rooms = get_raw_rooms(domain_name);

	local rooms_json = array();

	for room in raw_rooms do

		local room_jid = room.jid;
		local participant_count = 0;
		local occupants_json = array();
		local occupants = room._occupants;
		if occupants then
			for _, occupant in room:each_occupant() do
				-- filter focus as we keep it as hidden participant
				if string.sub(occupant.nick,-string.len("/focus"))~="/focus" then
					for _, pr in occupant:each_session() do
						participant_count = participant_count + 1;
						local nick = pr:get_child_text("nick", "http://jabber.org/protocol/nick") or "";
						local email = pr:get_child_text("email") or "";
						occupants_json:push({
							jid = tostring(occupant.nick),
							email = tostring(email),
							display_name = tostring(nick)});
					end
				end
			end
		end

		rooms_json:push({
			jid = room_jid,
			participant_count = participant_count,
			participants = occupants_json
		});

	end

	local result_json={
		rooms = rooms_json;
	};
	-- create json response
	return { status_code = 200; body = json.encode(result_json); };
end

function module.load()
module:depends(“http”);
module:provides(“http”, {
default_path = “/”;
route = {
[“GET room-size”] = function (event) return async_handler_wrapper(event,handle_get_room_size) end;
[“GET sessions”] = function () return tostring(it.count(it.keys(prosody.full_sessions))); end;
[“GET room”] = function (event) return async_handler_wrapper(event,handle_get_room) end;
[“GET all-rooms”] = function (event) return async_handler_wrapper(event,handle_get_all_rooms) end;
};
});
end

Then added “muc_test” in prosody config as below

Component “conference.vc.test” “muc”
storage = “memory”
modules_enabled = {
“muc_meeting_id”;
“muc_domain_mapper”;
“muc_test”;

}
admins = { "focus@auth.vc.test" }
muc_room_locking = false
muc_room_default_public_jids = true

Restarted prosody service. except for SSL error it starts success
ay 16 22:54:57 vc.test prosody[14161]: portmanager: Error binding encrypted port for https: No certificate present in SSL/TLS con
May 16 22:54:57 vc.test prosody[14161]: portmanager: Error binding encrypted port for https: No certificate present in SSL/TLS con

but when querying http://localhost:5280/all-rooms?domain=conference.vc.test i get 404 error.
Similarly if i try to load existing “mod_muc_size.lua” then also 404 error.

Please suggest where am I doing wrong?

Where (which file) did you add this new method? And where(which file) did you load this module? Thanks