Skip to content

Instantly share code, notes, and snippets.

@jeansf
Last active November 22, 2023 14:14
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeansf/b596b3d8d334802f50d2df5fe272acf2 to your computer and use it in GitHub Desktop.
Save jeansf/b596b3d8d334802f50d2df5fe272acf2 to your computer and use it in GitHub Desktop.
Jitsi Token Moderation
#!/bin/bash -e
PATH=${PATH}:/usr/local/bin
# Configure Recordings
RECORDINGS_DIR=$1
ROOM=`jq -r ".meeting_url" ${RECORDINGS_DIR}/metadata.json | sed -e 's|^[^/]*//.*/||'`
# Get Recording Information
RECORDINGS_FILE_NAME=`find ${RECORDINGS_DIR} -type f -name \*.mp4 | sed -e "s|${RECORDINGS_DIR}/||g"`
RECORDINGS_SIZE_HUMAN_READABLE=`du -sh ${RECORDINGS_DIR} | awk -F' ' '{print $1}'`
# Upload Recording Files to MinIO
#mv ${RECORDINGS_DIR}/metadata.json ${RECORDINGS_DIR}/${RECORDINGS_FILE_NAME}.json
mkdir -p ${RECORDINGS_DIR}/../${ROOM}/
mv ${RECORDINGS_DIR}/*.mp4* ${RECORDINGS_DIR}/../
#mkdir -p ${RECORDINGS_DIR}/../processados
#cp ${RECORDINGS_DIR}/*.mp4* ${RECORDINGS_DIR}/../processados
# Remove Recording Directory
rm -rf ${RECORDINGS_DIR}/
curl --location --request POST "$WEBHOOK_URL" \
--header 'Content-Type: application/json' \
--data-raw '{
"room": "'"$ROOM"'",
"file": "'"$RECORDINGS_FILE_NAME"'",
"secret": "'"$WEBHOOK_SECRET"'",
"event": "recording_published"
}'
# Done
exit 0
-- Token moderation
-- this module looks for a field on incoming JWT tokens called "moderator".
-- If it is true the user is added to the room as a moderator, otherwise they are set to a normal user.
-- Note this may well break other affiliation based features like banning or login-based admins
local log = module._log;
local jid_bare = require "util.jid".bare;
local json = require "cjson";
local basexx = require "basexx";
local um_is_admin = require "core.usermanager".is_admin;
local function is_admin(jid)
return um_is_admin(jid, module.host);
end
log('info', 'Loaded token moderation plugin');
-- Hook into room creation to add this wrapper to every new room
module:hook("muc-room-created", function(event)
log('info', 'room created, adding token moderation code');
local room = event.room
local _set_affiliation = room.set_affiliation;
room.set_affiliation = function(room, actor, jid, affiliation, reason);
if actor == "token_plugin" then
return _set_affiliation(room, true, jid, affiliation, reason);
elseif affiliation == "owner" then
log('debug', 'set_affiliation: room=%s, actor=%s, jid=%s, affiliation=%s, reason=%s', room, actor, jid, affiliation, reason);
if string.match(tostring(actor), "focus@") then
log('debug', 'set_affiliation not acceptable, focus user');
return nil, "modify", "not-acceptable";
else
return _set_affiliation(room, actor, jid, affiliation, reason);
end;
else
return _set_affiliation(room, actor, jid, affiliation, reason);
end;
end;
end);
module:hook("muc-occupant-joined", function(event)
log('info', 'occupant joined, checking token for ownership');
setupAffiliation(event.room, event.origin, event.stanza);
end);
function setupAffiliation(room, origin, stanza)
if origin.auth_token then
-- Extract token body and decode it
local dotFirst = origin.auth_token:find("%.");
if dotFirst then
local dotSecond = origin.auth_token:sub(dotFirst + 1):find("%.");
if dotSecond then
local bodyB64 = origin.auth_token:sub(dotFirst + 1, dotFirst + dotSecond - 1);
local body = json.decode(basexx.from_url64(bodyB64));
local jid = jid_bare(stanza.attr.from);
-- If user is a moderator or an admin, set their affiliation to be an owner
if body["moderator"] == true or is_admin(jid) then
room:set_affiliation("token_plugin", jid, "owner");
else
room:set_affiliation("token_plugin", jid, "member");
end;
end;
end;
end;
end;
local log = module._log;
local http = require "net.http";
local json = require "util.json";
local is_healthcheck_room = module:require "util".is_healthcheck_room;
local jid_split = require "util.jid".split;
local pre_jibri_user = os.getenv("JIBRI_RECORDER_USER")
local pre_jibri_domain = os.getenv("XMPP_RECORDER_DOMAIN")
local webhook_url = os.getenv("WEBHOOK_URL")
local webhook_token = os.getenv("WEBHOOK_TOKEN")
log('info', 'Loaded webhook plugin');
function make_http_request(params)
params.token=webhook_token;
http.request(webhook_url,{
body = json.encode(params);
}, function (response_text, code, response)
if code == 200 or code == 204 then
log('info', 'Webhook: Request response (%s)', code);
else
log('error', 'Webhook: Request error (%s) - %s', code, response_text);
end
return ;
end);
end;
-- Hook to assign meetingId for new rooms
module:hook("muc-room-created", function(event)
local room = event.room;
local roomId = jid_split(room.jid);
if is_healthcheck_room(room.jid) then
return;
end
log('info', 'Webhook: Sala %s criada!', roomId);
local params = {
room = roomId,
event = "room_created"
};
make_http_request(params);
end);
-- Hook to assign meetingId for destroyed rooms
module:hook("muc-room-destroyed", function(event)
local room = event.room;
local roomId = jid_split(room.jid);
if is_healthcheck_room(room.jid) then
return;
end
log('info', 'Webhook: Sala %s removida!', roomId);
local params = {
room = roomId,
event = "room_closed"
};
make_http_request(params);
end);
-- Hook to assign meetingId for recordings rooms
module:hook("muc-occupant-joined", function (event)
local occupant, room, stanza = event.occupant, event.room, event.stanza;
if is_healthcheck_room(room.jid) then
return;
end
local roomId = jid_split(room.jid);
local user, domain, res = jid_split(stanza.attr.from);
if ( user == pre_jibri_user and domain == pre_jibri_domain ) then
log('info', 'Webhook: Gravação da sala %s - Iniciada', roomId);
local params = {
room = roomId,
event = "recording_started"
};
make_http_request(params);
else
-- local userId = getUserId(origin);
local presence = occupant:get_presence();
if presence and presence:get_child("identity") and presence:get_child("identity"):get_child("user") then
local userId = presence:get_child("identity"):get_child("user"):get_child_text("id");
log('info', 'Webhook: Usuário %s entrou na sala', userId);
local params = {
room = roomId,
user = userId,
event = "user_joined"
};
make_http_request(params);
end
end;
end);
-- Hook to assign meetingId for recordings rooms
module:hook("muc-occupant-left", function (event)
local occupant, room, stanza = event.occupant, event.room, event.stanza;
if is_healthcheck_room(room.jid) then
return;
end
local roomId = jid_split(room.jid);
local user, domain, res = jid_split(stanza.attr.from);
if ( user == pre_jibri_user and domain == pre_jibri_domain ) then
log('info', 'Webhook: Gravação da sala %s - Encerrada', roomId);
local params = {
room = roomId,
event = "recording_ended"
};
make_http_request(params);
else
-- local userId = getUserId(origin);
local presence = occupant:get_presence();
if presence and presence:get_child("identity") and presence:get_child("identity"):get_child("user") then
local userId = presence:get_child("identity"):get_child("user"):get_child_text("id");
log('info', 'Webhook: Usuário %s saiu da sala', userId);
local params = {
room = roomId,
user = userId,
event = "user_left"
};
make_http_request(params);
end
end;
end);
module:hook('muc-set-affiliation', function (event)
local affiliation, previous_affiliation, actor, room, jid = event.affiliation, event.previous_affiliation, event.actor, event.room, event.jid;
if actor and previous_affiliation ~= 'owner' and affiliation == 'owner' then
local roomId = jid_split(room.jid);
local occupant = nil;
for _, occupant_r in room:each_occupant() do
if occupant_r.bare_jid == jid then
occupant = occupant_r;
break
end
end
if occupant then
local presence = occupant:get_presence();
local userId = presence:get_child("identity"):get_child("user"):get_child_text("id");
log('info', 'Webhook: Moderador atribuído para %s', userId);
local params = {
room = roomId,
user = userId,
event = "grant_permission"
};
make_http_request(params);
end
end
end)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment