Merge pull request #6222 from fcecagno/webhooks-on-1.1

Fix webhooks
This commit is contained in:
Fred Dixon 2018-11-03 23:42:58 -04:00 committed by GitHub
commit 18c3836886
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 159 additions and 16 deletions

View File

@ -0,0 +1 @@
node_modules/

View File

@ -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)

View File

@ -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;
}

View File

@ -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;

View File

@ -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;