From 4c9b7d505d268e541e13a642523e5c0b8ef266d4 Mon Sep 17 00:00:00 2001 From: Ben McDowell Date: Fri, 17 Jul 2026 09:45:17 -0400 Subject: [PATCH] Added a function for the Janus moderation event --- src/plugins/videoroom-plugin.js | 59 ++++++++++++++++++++++++++++++++- 1 file changed, 58 insertions(+), 1 deletion(-) diff --git a/src/plugins/videoroom-plugin.js b/src/plugins/videoroom-plugin.js index a9ebd48..d3148b7 100644 --- a/src/plugins/videoroom-plugin.js +++ b/src/plugins/videoroom-plugin.js @@ -17,6 +17,7 @@ const REQUEST_JOIN_CONFIGURE = 'joinandconfigure'; const REQUEST_LIST_PARTICIPANTS = 'listparticipants'; const REQUEST_ENABLE_RECORDING = 'enable_recording'; const REQUEST_KICK = 'kick'; +const REQUEST_MODERATE = 'moderate'; const REQUEST_START = 'start'; const REQUEST_PAUSE = 'pause'; const REQUEST_SWITCH = 'switch'; @@ -56,6 +57,7 @@ const PLUGIN_EVENT = { LEAVING: 'videoroom_leaving', UPDATED: 'videoroom_updated', KICKED: 'videoroom_kicked', + MODERATED: 'videoroom_moderated', RECORDING_ENABLED_STATE: 'videoroom_recording_enabled_state', TALKING: 'videoroom_talking', SC_SUBSTREAM_LAYER: 'videoroom_sc_substream_layer', @@ -590,6 +592,15 @@ class VideoRoomHandle extends Handle { janode_event.data.sc_temporal_layers = message_data.temporal; break; } + /* Publisher moderated, i.e. a track has been muted or unmuted */ + if (typeof message_data.moderation !== 'undefined') { + janode_event.event = PLUGIN_EVENT.MODERATED; + janode_event.data.feed = message_data.id; + janode_event.data.mid = message_data.mid; + janode_event.data.moderation = message_data.moderation; + break; + } + } /* The event has been handled */ @@ -1187,6 +1198,29 @@ class VideoRoomHandle extends Handle { throw (error); } + async moderate({ room, feed, mID, mute, secret }) { + const body = { + request: REQUEST_MODERATE, + room, + id: feed, + mid: mID, + mute + }; + if (typeof secret === 'string') body.secret = secret; + + const response = await this.message(body); + const { event, data: evtdata } = this._getPluginEvent(response); + if (event === PLUGIN_EVENT.SUCCESS) { + evtdata.room = body.room; + evtdata.feed = body.id; + evtdata.mid = body.mid; + evtdata.mute = body.mute + return evtdata; + } + const error = new Error(`unexpected response to ${body.request} request`); + throw (error); + } + /** * Check if a room exists. * @@ -1479,7 +1513,7 @@ class VideoRoomHandle extends Handle { * @typedef {Object} VIDEOROOM_EVENT_PUB_JOINED * @property {number|string} room - The involved room * @property {number|string} feed - The feed identifier - * @property {string} [display] - The dsplay name, if available + * @property {string} [display] - The display name, if available * @property {string} description - A description of the room, if available * @property {number} private_id - The private id that can be used when subscribing * @property {object[]} publishers - The list of active publishers @@ -1676,6 +1710,16 @@ class VideoRoomHandle extends Handle { * @property {number|string} feed - The feed that has been kicked */ +/** + * A publisher has been moderated (muted or unmuted) + * + * @typedef {Object} VIDEOROOM_EVENT_MODERATED + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that has been moderated + * @property {string} mid - The mid of the moderated track + * @property {'muted'|'unmuted' } moderation - The moderation action taken +*/ + /** * The response event for the recording enabled request. * @@ -1710,6 +1754,7 @@ class VideoRoomHandle extends Handle { * @property {string} EVENT.VIDEOROOM_SLOWLINK {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SLOWLINK VIDEOROOM_SLOWLINK} * @property {string} EVENT.VIDEOROOM_TALKING {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_TALKING VIDEOROOM_TALKING} * @property {string} EVENT.VIDEOROOM_KICKED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_KICKED VIDEOROOM_KICKED} + * @property {string} EVENT.VIDEOROOM_MODERATED {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_MODERATED VIDEOROOM_MODERATED} * @property {string} EVENT.VIDEOROOM_RECORDING_ENABLED_STATE {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_RECORDING_ENABLED_STATE VIDEOROOM_RECORDING_ENABLED_STATE} * @property {string} EVENT.VIDEOROOM_SC_SUBSTREAM_LAYER {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_SUBSTREAM_LAYER VIDEOROOM_SC_SUBSTREAM_LAYER} * @property {string} EVENT.VIDEOROOM_SC_TEMPORAL_LAYERS {@link module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_SC_TEMPORAL_LAYERS VIDEOROOM_SC_TEMPORAL_LAYERS} @@ -1841,6 +1886,18 @@ export default { */ VIDEOROOM_KICKED: PLUGIN_EVENT.KICKED, + /** + * A publisher has been moderated (muted or unmuted) + * + * @event module:videoroom-plugin~VideoRoomHandle#event:VIDEOROOM_MODERATED + * @type {Object} + * @property {number|string} room - The involved room + * @property {number|string} feed - The feed that has been moderated + * @property {string} mid - The mid of the moderated track + * @property {'muted'|'unmuted' } moderation - The moderation action taken + */ + VIDEOROOM_MODERATED: PLUGIN_EVENT.MODERATED, + /** * Conference recording has been enabled or disabled. *