commit
18c3836886
1
bbb-webhooks/.dockerignore
Normal file
1
bbb-webhooks/.dockerignore
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
@ -21,7 +21,10 @@ if (!config.hooks.channels) {
|
||||
config.hooks.channels = {
|
||||
mainChannel: 'from-akka-apps-redis-channel',
|
||||
rapChannel: 'bigbluebutton:from-rap',
|
||||
chatChannel: 'from-akka-apps-chat-redis-channel'
|
||||
chatChannel: 'from-akka-apps-chat-redis-channel',
|
||||
compMeetingChannel: 'bigbluebutton:from-bbb-apps:meeting',
|
||||
compUserChannel: 'bigbluebutton:from-bbb-apps:users',
|
||||
compChatChannel: 'bigbluebutton:from-bbb-apps:chat'
|
||||
}
|
||||
}
|
||||
// IP where permanent hook will post data (more than 1 URL means more than 1 permanent hook)
|
||||
|
@ -11,6 +11,9 @@ module.exports = class MessageMapping {
|
||||
this.userEvents = ["UserJoinedMeetingEvtMsg","UserLeftMeetingEvtMsg","UserJoinedVoiceConfToClientEvtMsg","UserLeftVoiceConfToClientEvtMsg","PresenterAssignedEvtMsg", "PresenterUnassignedEvtMsg", "UserBroadcastCamStartedEvtMsg", "UserBroadcastCamStoppedEvtMsg", "UserEmojiChangedEvtMsg"];
|
||||
this.chatEvents = ["SendPublicMessageEvtMsg","SendPrivateMessageEvtMsg"];
|
||||
this.rapEvents = ["archive_started","archive_ended","sanity_started","sanity_ended","post_archive_started","post_archive_ended","process_started","process_ended","post_process_started","post_process_ended","publish_started","publish_ended","post_publish_started","post_publish_ended"];
|
||||
|
||||
this.compMeetingEvents = ["meeting_created_message","meeting_destroyed_event"];
|
||||
this.compUserEvents = ["user_joined_message","user_left_message","user_listening_only","user_joined_voice_message","user_left_voice_message","user_shared_webcam_message","user_unshared_webcam_message","user_status_changed_message"];
|
||||
}
|
||||
|
||||
// Map internal message based on it's type
|
||||
@ -23,6 +26,10 @@ module.exports = class MessageMapping {
|
||||
this.chatTemplate(messageObj);
|
||||
} else if (this.mappedEvent(messageObj,this.rapEvents)) {
|
||||
this.rapTemplate(messageObj);
|
||||
} else if (this.mappedEvent(messageObj,this.compMeetingEvents)) {
|
||||
this.compMeetingTemplate(messageObj);
|
||||
} else if (this.mappedEvent(messageObj,this.compUserEvents)) {
|
||||
this.compUserTemplate(messageObj);
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,6 +86,46 @@ module.exports = class MessageMapping {
|
||||
Logger.info("[MessageMapping] Mapped message:", this.mappedMessage);
|
||||
}
|
||||
|
||||
compMeetingTemplate(messageObj) {
|
||||
const props = messageObj.payload;
|
||||
const meetingId = props.meeting_id;
|
||||
this.mappedObject.data = {
|
||||
"type": "event",
|
||||
"id": this.mapInternalMessage(messageObj),
|
||||
"attributes":{
|
||||
"meeting":{
|
||||
"internal-meeting-id": meetingId,
|
||||
"external-meeting-id": IDMapping.getExternalMeetingID(meetingId)
|
||||
}
|
||||
},
|
||||
"event":{
|
||||
"ts": Date.now()
|
||||
}
|
||||
};
|
||||
if (messageObj.header.name === "meeting_created_message") {
|
||||
this.mappedObject.data.attributes = {
|
||||
"meeting":{
|
||||
"internal-meeting-id": meetingId,
|
||||
"external-meeting-id": props.external_meeting_id,
|
||||
"name": props.name,
|
||||
"is-breakout": props.is_breakout,
|
||||
"duration": props.duration,
|
||||
"create-time": props.create_time,
|
||||
"create-date": props.create_date,
|
||||
"moderator-pass": props.moderator_pass,
|
||||
"viewer-pass": props.viewer_pass,
|
||||
"record": props.recorded,
|
||||
"voice-conf": props.voice_conf,
|
||||
"dial-number": props.dial_number,
|
||||
"max-users": props.max_users,
|
||||
"metadata": props.metadata
|
||||
}
|
||||
};
|
||||
}
|
||||
this.mappedMessage = JSON.stringify(this.mappedObject);
|
||||
Logger.info("[MessageMapping] Mapped message:", this.mappedMessage);
|
||||
}
|
||||
|
||||
// Map internal to external message for user information
|
||||
userTemplate(messageObj) {
|
||||
const msgBody = messageObj.core.body;
|
||||
@ -111,6 +158,68 @@ module.exports = class MessageMapping {
|
||||
Logger.info("[MessageMapping] Mapped message:", this.mappedMessage);
|
||||
}
|
||||
|
||||
// Map internal to external message for user information
|
||||
compUserTemplate(messageObj) {
|
||||
const msgBody = messageObj.payload;
|
||||
const msgHeader = messageObj.header;
|
||||
|
||||
let user;
|
||||
if (msgHeader.name === "user_joined_message") {
|
||||
user = {
|
||||
"internal-user-id": msgBody.user.userid,
|
||||
"external-user-id": msgBody.user.extern_userid,
|
||||
"sharing-mic": msgBody.user.voiceUser.joined,
|
||||
"name": msgBody.user.name,
|
||||
"role": msgBody.user.role,
|
||||
"presenter": msgBody.user.presenter,
|
||||
"stream": msgBody.user.webcam_stream,
|
||||
"listening-only": msgBody.user.listenOnly
|
||||
}
|
||||
}
|
||||
else {
|
||||
user = UserMapping.getUser(msgBody.userid) || { "internal-user-id": msgBody.userid || msgBody.user.userid };
|
||||
if (msgHeader.name === "user_status_changed_message") {
|
||||
if (msgBody.status === "presenter") {
|
||||
user["presenter"] = msgBody.value;
|
||||
}
|
||||
}
|
||||
else if (msgHeader.name === "user_listening_only") {
|
||||
user["listening-only"] = msgBody.listen_only;
|
||||
}
|
||||
else if (msgHeader.name === "user_joined_voice_message" || msgHeader.name === "user_left_voice_message") {
|
||||
user["sharing-mic"] = msgBody.user.voiceUser.joined;
|
||||
}
|
||||
else if (msgHeader.name === "user_shared_webcam_message") {
|
||||
user["stream"].push(msgBody.stream);
|
||||
}
|
||||
else if (msgHeader.name === "user_unshared_webcam_message") {
|
||||
let streams = user["stream"];
|
||||
let index = streams.indexOf(msgBody.stream);
|
||||
if (index != -1) {
|
||||
streams.splice(index,1);
|
||||
}
|
||||
user["stream"] = streams;
|
||||
}
|
||||
}
|
||||
|
||||
this.mappedObject.data = {
|
||||
"type": "event",
|
||||
"id": this.mapInternalMessage(messageObj),
|
||||
"attributes":{
|
||||
"meeting":{
|
||||
"internal-meeting-id": msgBody.meeting_id,
|
||||
"external-meeting-id": IDMapping.getExternalMeetingID(msgBody.meeting_id)
|
||||
},
|
||||
"user": user
|
||||
},
|
||||
"event":{
|
||||
"ts": Date.now()
|
||||
}
|
||||
};
|
||||
this.mappedMessage = JSON.stringify(this.mappedObject);
|
||||
Logger.info("[MessageMapping] Mapped message:", this.mappedMessage);
|
||||
}
|
||||
|
||||
// Map internal to external message for chat information
|
||||
chatTemplate(messageObj) {
|
||||
const message = messageObj.core.body.message;
|
||||
@ -150,12 +259,13 @@ module.exports = class MessageMapping {
|
||||
const data = messageObj.payload;
|
||||
this.mappedObject.data = {
|
||||
"type": "event",
|
||||
"id": this.mapInternalMessage(messageObj.header.name),
|
||||
"id": this.mapInternalMessage(messageObj),
|
||||
"attributes": {
|
||||
"meeting": {
|
||||
"internal-meeting-id": data.meeting_id,
|
||||
"external-meeting-id": data.external_meeting_id
|
||||
"external-meeting-id": data.external_meeting_id || IDMapping.getExternalMeetingID(data.meeting_id)
|
||||
},
|
||||
"record-id": data.record_id,
|
||||
"success": data.success,
|
||||
"step-time": data.step_time
|
||||
},
|
||||
@ -164,14 +274,18 @@ module.exports = class MessageMapping {
|
||||
}
|
||||
};
|
||||
|
||||
if (this.mappedObject.data["id"] == "rap-publish-ended") {
|
||||
this.mappedObject.data["attributes"]["recording"] = {
|
||||
if (data.workflow) {
|
||||
this.mappedObject.data.attributes.workflow = data.workflow;
|
||||
}
|
||||
|
||||
if (this.mappedObject.data.id === "rap-publish-ended") {
|
||||
this.mappedObject.data.attributes.recording = {
|
||||
"name": data.metadata.meetingName,
|
||||
"isBreakout": data.metadata.isBreakout,
|
||||
"startTime": data.startTime,
|
||||
"endTime": data.endTime,
|
||||
"is-breakout": data.metadata.isBreakout,
|
||||
"start-time": data.startTime,
|
||||
"end-time": data.endTime,
|
||||
"size": data.playback.size,
|
||||
"rawSize": data.rawSize,
|
||||
"raw-size": data.rawSize,
|
||||
"metadata": data.metadata,
|
||||
"playback": data.playback,
|
||||
"download": data.download
|
||||
@ -183,13 +297,14 @@ module.exports = class MessageMapping {
|
||||
|
||||
|
||||
mapInternalMessage(message) {
|
||||
let name;
|
||||
if (message.envelope) {
|
||||
message = message.envelope.name
|
||||
name = message.envelope.name
|
||||
}
|
||||
else if (message.header) {
|
||||
message = message.header.name
|
||||
name = message.header.name
|
||||
}
|
||||
const mappedMsg = (() => { switch (message) {
|
||||
const mappedMsg = (() => { switch (name) {
|
||||
case "MeetingCreatedEvtMsg": return "meeting-created";
|
||||
case "MeetingDestroyedEvtMsg": return "meeting-ended";
|
||||
case "RecordingStatusChangedEvtMsg": return "meeting-recording-changed";
|
||||
@ -221,6 +336,19 @@ module.exports = class MessageMapping {
|
||||
case "publish_ended": return "rap-publish-ended";
|
||||
case "post_publish_started": return "rap-post-publish-started";
|
||||
case "post_publish_ended": return "rap-post-publish-ended";
|
||||
case "meeting_created_message": return "meeting-created";
|
||||
case "meeting_destroyed_event": return "meeting-ended";
|
||||
case "user_joined_message": return "user-joined";
|
||||
case "user_left_message": return "user-left";
|
||||
case "user_listening_only": return (message.payload.listen_only ? "user-audio-listen-only-enabled" : "user-audio-listen-only-disabled");
|
||||
case "user_joined_voice_message": return "user-audio-voice-enabled";
|
||||
case "user_left_voice_message": return "user-audio-voice-disabled";
|
||||
case "user_shared_webcam_message": return "user-cam-broadcast-start";
|
||||
case "video_stream_unpublished": return "user-cam-broadcast-end";
|
||||
case "user_status_changed_message":
|
||||
if (message.payload.status === "presenter") {
|
||||
return (message.payload.value === "true" ? "user-presenter-assigned" : "user-presenter-unassigned" );
|
||||
}
|
||||
} })();
|
||||
return mappedMsg;
|
||||
}
|
||||
|
@ -32,16 +32,18 @@ module.exports = class UserMapping {
|
||||
this.externalUserID = null;
|
||||
this.internalUserID = null;
|
||||
this.meetingId = null;
|
||||
this.user = null;
|
||||
this.redisClient = config.redis.client;
|
||||
}
|
||||
|
||||
save(callback) {
|
||||
db[this.internalUserID] = this;
|
||||
|
||||
this.redisClient.hmset(config.redis.keys.userMap(this.id), this.toRedis(), (error, reply) => {
|
||||
if (error != null) { Logger.error("[UserMapping] error saving mapping to redis:", error, reply); }
|
||||
this.redisClient.sadd(config.redis.keys.userMaps, this.id, (error, reply) => {
|
||||
if (error != null) { Logger.error("[UserMapping] error saving mapping ID to the list of mappings:", error, reply); }
|
||||
|
||||
db[this.internalUserID] = this;
|
||||
(typeof callback === 'function' ? callback(error, db[this.internalUserID]) : undefined);
|
||||
});
|
||||
});
|
||||
@ -68,7 +70,8 @@ module.exports = class UserMapping {
|
||||
"id": this.id,
|
||||
"internalUserID": this.internalUserID,
|
||||
"externalUserID": this.externalUserID,
|
||||
"meetingId": this.meetingId
|
||||
"meetingId": this.meetingId,
|
||||
"user": this.user
|
||||
};
|
||||
return r;
|
||||
}
|
||||
@ -78,18 +81,20 @@ module.exports = class UserMapping {
|
||||
this.externalUserID = redisData.externalUserID;
|
||||
this.internalUserID = redisData.internalUserID;
|
||||
this.meetingId = redisData.meetingId;
|
||||
this.user = redisData.user;
|
||||
}
|
||||
|
||||
print() {
|
||||
return JSON.stringify(this.toRedis());
|
||||
}
|
||||
|
||||
static addMapping(internalUserID, externalUserID, meetingId, callback) {
|
||||
static addOrUpdateMapping(internalUserID, externalUserID, meetingId, user, callback) {
|
||||
let mapping = new UserMapping();
|
||||
mapping.id = nextID++;
|
||||
mapping.internalUserID = internalUserID;
|
||||
mapping.externalUserID = externalUserID;
|
||||
mapping.meetingId = meetingId;
|
||||
mapping.user = user;
|
||||
mapping.save(function(error, result) {
|
||||
Logger.info(`[UserMapping] added user mapping to the list ${internalUserID}:`, mapping.print());
|
||||
(typeof callback === 'function' ? callback(error, result) : undefined);
|
||||
@ -131,6 +136,12 @@ module.exports = class UserMapping {
|
||||
})();
|
||||
}
|
||||
|
||||
static getUser(internalUserID) {
|
||||
if (db[internalUserID]){
|
||||
return db[internalUserID].user;
|
||||
}
|
||||
}
|
||||
|
||||
static getExternalUserID(internalUserID) {
|
||||
if (db[internalUserID]){
|
||||
return db[internalUserID].externalUserID;
|
||||
|
@ -54,7 +54,7 @@ module.exports = class WebHooks {
|
||||
});
|
||||
break;
|
||||
case "user-joined":
|
||||
UserMapping.addMapping(message.data.attributes.user["internal-user-id"],message.data.attributes.user["external-user-id"], intId, () => {
|
||||
UserMapping.addOrUpdateMapping(message.data.attributes.user["internal-user-id"],message.data.attributes.user["external-user-id"], intId, message.data.attributes.user, () => {
|
||||
processMessage();
|
||||
});
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user