From 09c30bb5bdab8739f9ebe3b8e7dd20b963e9ae3d Mon Sep 17 00:00:00 2001 From: Leonardo Crauss Daronco Date: Thu, 8 Dec 2016 14:01:57 -0200 Subject: [PATCH] Add flag to use webhooks and API call to register a hook It almost works with webhooks now. Still TODO is: * Remove the hook after the recording is published * To process the publish_ended event from the webhooks either the webhook needs to include the metadata (currently it doesn't) or GreenLight has find out the meeting token without reading it from the metadata. --- app/controllers/bbb_controller.rb | 31 ++++++++++++++++++++++--------- app/lib/bbb_api.rb | 30 +++++++++++++++++++++++++++--- sample.env | 10 ++++++++++ 3 files changed, 59 insertions(+), 12 deletions(-) diff --git a/app/controllers/bbb_controller.rb b/app/controllers/bbb_controller.rb index 1bf33933..b837ced2 100644 --- a/app/controllers/bbb_controller.rb +++ b/app/controllers/bbb_controller.rb @@ -155,18 +155,31 @@ class BbbController < ApplicationController end def treat_callback_event(event) + eventName = (event.present? && event['header'].present?) ? event['header']['name'] : nil # a recording is ready - if event['header']['name'] == "publish_ended" - token = event['payload']['metadata'][META_TOKEN] - record_id = event['payload']['meeting_id'] + if eventName == "publish_ended" + if event['payload'] && event['payload']['metadata'] && event['payload']['meeting_id'] + token = event['payload']['metadata'][META_TOKEN] + record_id = event['payload']['meeting_id'] - # the webhook event doesn't have all the data we need, so we need - # to send a getRecordings anyway - # TODO: if the webhooks included all data we wouldn't need this - rec_info = bbb_get_recordings(token, record_id) - rec_info = rec_info[:recordings].first - RecordingCreatedJob.perform_later(token, parse_recording_for_view(rec_info)) + # the webhook event doesn't have all the data we need, so we need + # to send a getRecordings anyway + # TODO: if the webhooks included all data in the event we wouldn't need this + rec_info = bbb_get_recordings(token, record_id) + rec_info = rec_info[:recordings].first + RecordingCreatedJob.perform_later(token, parse_recording_for_view(rec_info)) + + # TODO: remove the webhook now that the meeting and recording are done + # remove only if the meeting is not running, otherwise the hook is needed + # if ENV['GREENLIGHT_USE_WEBHOOKS'] + # webhook_remove("#{base_url}/callback") + # end + else + logger.error "Bad format for event #{event}, won't process" + end + else + logger.info "Callback event will not be treated. Event name: #{eventName}" end render head(:ok) && return diff --git a/app/lib/bbb_api.rb b/app/lib/bbb_api.rb index e1690485..2f0d923b 100644 --- a/app/lib/bbb_api.rb +++ b/app/lib/bbb_api.rb @@ -78,9 +78,13 @@ module BbbApi "meta_#{BbbApi::META_TOKEN}": meeting_token } - meeting_options.merge!( - { "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] } - ) if options[:hook_url] + if ENV['GREENLIGHT_USE_WEBHOOKS'] + webhook_register(options[:hook_url], meeting_id) + else + meeting_options.merge!( + { "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] } + ) if options[:hook_url] + end # Create the meeting bbb.create_meeting(options[:meeting_name], meeting_id, meeting_options) @@ -253,6 +257,26 @@ module BbbApi } end + def webhook_register(url, meeting_id=nil) + params = { callbackURL: url } + params.merge!({ meetingID: meeting_id }) if meeting_id.present? + bbb_safe_execute :send_api_request, "hooks/create", params + end + + def webhook_remove(url) + res = bbb_safe_execute :send_api_request, "hooks/list" + if res && res[:hooks] && res[:hooks][:hook] + res[:hooks][:hook] = [res[:hooks][:hook]] unless res[:hooks][:hook].is_a?(Array) + hook = res[:hooks][:hook].select{ |h| + h[:callbackURL] == url + }.first + if hook.present? + params = { hookID: hook[:hookID] } + bbb_safe_execute :send_api_request, "hooks/destroy", params + end + end + end + def success_join_res(join_url) { returncode: true, diff --git a/sample.env b/sample.env index d9dbc21f..1485f639 100644 --- a/sample.env +++ b/sample.env @@ -7,6 +7,16 @@ RAILS_ENV=development BIGBLUEBUTTON_ENDPOINT=http://test-install.blindsidenetworks.com/bigbluebutton/ BIGBLUEBUTTON_SECRET=8cd8ef52e8e101574e400365b55e11a6 +# If "true", GreenLight will register a webhook callback for each meeting +# created. This callback is called for all events that happen in the meeting, +# including the processing of its recording. These events are used to update +# the web page dynamically as things happen in the server. +# If not "true", the application will add a metadata to the meetings with this same +# callback URL. Scripts can then be added to BigBlueButton to call this callback +# URL and send specific events to GreenLight (e.g. a post publish script to warn +# the application when recordings are done). +GREENLIGHT_USE_WEBHOOKS=false + # OmniAuth TWITTER_ID= TWITTER_SECRET=