bigbluebutton-Github/bbb-webhooks/web_hooks.coffee

89 lines
3.4 KiB
CoffeeScript

_ = require("lodash")
async = require("async")
redis = require("redis")
request = require("request")
config = require("./config")
Hook = require("./hook")
IDMapping = require("./id_mapping")
Logger = require("./logger")
# Web hooks will listen for events on redis coming from BigBlueButton and
# perform HTTP calls with them to all registered hooks.
module.exports = class WebHooks
constructor: ->
@subscriberEvents = redis.createClient()
start: ->
@_subscribeToEvents()
# Subscribe to the events on pubsub that might need to be sent in callback calls.
_subscribeToEvents: ->
@subscriberEvents.on "psubscribe", (channel, count) ->
Logger.info "WebHooks: subscribed to " + channel
@subscriberEvents.on "pmessage", (pattern, channel, message) =>
processMessage = =>
if @_filterMessage(channel, message)
Logger.info "WebHooks: processing message on [#{channel}]:", JSON.stringify(message)
@_processEvent(message)
try
message = JSON.parse(message)
if message?
id = message.payload?.meeting_id
IDMapping.reportActivity(id)
# First treat meeting events to add/remove ID mappings
if message.header?.name is "meeting_created_message"
Logger.info "WebHooks: got create message on meetings channel [#{channel}]", message
IDMapping.addOrUpdateMapping message.payload?.meeting_id, message.payload?.external_meeting_id, (error, result) ->
# has to be here, after the meeting was created, otherwise create calls won't generate
# callback calls for meeting hooks
processMessage()
# TODO: Temporarily commented because we still need the mapping for recording events,
# after the meeting ended.
# else if message.header?.name is "meeting_destroyed_event"
# Logger.info "WebHooks: got destroy message on meetings channel [#{channel}]", message
# IDMapping.removeMapping message.payload?.meeting_id, (error, result) ->
# processMessage()
else
processMessage()
catch e
Logger.error "WebHooks: error processing the message", message, ":", e
@subscriberEvents.psubscribe config.hooks.pchannel
# Returns whether the message read from redis should generate a callback
# call or not.
_filterMessage: (channel, message) ->
for event in config.hooks.events
if channel? and message.header?.name? and
event.channel.match(channel) and event.name.match(message.header?.name)
return true
false
# Processes an event received from redis. Will get all hook URLs that
# should receive this event and start the process to perform the callback.
_processEvent: (message) ->
hooks = Hook.allGlobalSync()
# TODO: events that happen after the meeting ended will never trigger the hooks
# below, since the mapping is removed when the meeting ends
# filter the hooks that need to receive this event
# only global hooks or hooks for this specific meeting
idFromMessage = message.payload?.meeting_id
if idFromMessage?
eMeetingID = IDMapping.getExternalMeetingID(idFromMessage)
hooks = hooks.concat(Hook.findByExternalMeetingIDSync(eMeetingID))
hooks.forEach (hook) ->
Logger.info "WebHooks: enqueueing a message in the hook:", hook.callbackURL
hook.enqueue message