From acf22177ae0be58fd270f7444df14e7668912b8a Mon Sep 17 00:00:00 2001 From: Felipe Cecagno <fcecagno@gmail.com> Date: Wed, 24 Oct 2018 23:49:56 -0300 Subject: [PATCH] add compatibility with old messaging format --- bbb-webhooks/config.js | 5 +- bbb-webhooks/messageMapping.js | 129 ++++++++++++++++++++++++++++++++- bbb-webhooks/userMapping.js | 14 +++- bbb-webhooks/web_hooks.js | 2 +- 4 files changed, 143 insertions(+), 7 deletions(-) diff --git a/bbb-webhooks/config.js b/bbb-webhooks/config.js index cfc7ccda07..4c06a78fbb 100644 --- a/bbb-webhooks/config.js +++ b/bbb-webhooks/config.js @@ -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) diff --git a/bbb-webhooks/messageMapping.js b/bbb-webhooks/messageMapping.js index 7ea2062c8a..8bd3edef19 100644 --- a/bbb-webhooks/messageMapping.js +++ b/bbb-webhooks/messageMapping.js @@ -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; @@ -183,13 +292,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 +331,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 === "true" ? "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; } diff --git a/bbb-webhooks/userMapping.js b/bbb-webhooks/userMapping.js index 185e2fc9a4..1177071904 100644 --- a/bbb-webhooks/userMapping.js +++ b/bbb-webhooks/userMapping.js @@ -32,6 +32,7 @@ module.exports = class UserMapping { this.externalUserID = null; this.internalUserID = null; this.meetingId = null; + this.user = null; this.redisClient = config.redis.client; } @@ -68,7 +69,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 +80,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 +135,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; diff --git a/bbb-webhooks/web_hooks.js b/bbb-webhooks/web_hooks.js index c00a2cf0b1..787027787a 100644 --- a/bbb-webhooks/web_hooks.js +++ b/bbb-webhooks/web_hooks.js @@ -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; -- GitLab