forked from External/greenlight
		
	Merge pull request #99 from zach-chai/recording_updates
Recording updates
This commit is contained in:
		| @@ -62,13 +62,13 @@ | ||||
|   }; | ||||
|  | ||||
|   $(document).on("turbolinks:load", function() { | ||||
|     // disable meeting updates if enabled from a previous page | ||||
|     if (App.meeting_update) { | ||||
|       disableMeetingUpdates(); | ||||
|     } | ||||
|     if ($("body[data-controller=landing]").get(0)) { | ||||
|       if ($("body[data-action=rooms]").get(0)) { | ||||
|         // disable meeting updates if enabled from a previous page | ||||
|         if (App.meeting_update) { | ||||
|           disableMeetingUpdates(); | ||||
|         } | ||||
|         if ($(".page-wrapper.rooms").data('main-room') === false) { | ||||
|         if (!$(".page-wrapper.rooms").data('main-room')) { | ||||
|           enableMeetingUpdates(); | ||||
|         } | ||||
|       } | ||||
|   | ||||
| @@ -16,10 +16,11 @@ | ||||
|  | ||||
| (function() { | ||||
|  | ||||
|   var initRooms = function() { | ||||
|     App.messages = App.cable.subscriptions.create({ | ||||
|   var enableRecordingUpdates = function() { | ||||
|     App.recording_update = App.cable.subscriptions.create({ | ||||
|       channel: 'RecordingUpdatesChannel', | ||||
|       encrypted_id: $(".page-wrapper").data('id') | ||||
|       admin_id: $(".page-wrapper.rooms").data('admin-id'), | ||||
|       meeting_id: $(".page-wrapper.rooms").data('id') | ||||
|     }, | ||||
|     { | ||||
|       received: function(data) { | ||||
| @@ -57,10 +58,19 @@ | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
|   var disableRecordingUpdates = function() { | ||||
|     App.recording_update.unsubscribe(); | ||||
|     delete App.recording_update | ||||
|   }; | ||||
|  | ||||
|   $(document).on("turbolinks:load", function() { | ||||
|     // disable recording updates if enabled from a previous page | ||||
|     if (App.recording_update) { | ||||
|       disableRecordingUpdates(); | ||||
|     } | ||||
|     if ($("body[data-controller=landing]").get(0)) { | ||||
|       if ($("body[data-action=rooms]").get(0)) { | ||||
|         initRooms(); | ||||
|         enableRecordingUpdates(); | ||||
|       } | ||||
|     } | ||||
|   }); | ||||
|   | ||||
| @@ -34,6 +34,7 @@ class @Recordings | ||||
|       }, | ||||
|       columns: [ | ||||
|         { data: "start_time" }, | ||||
|         { data: "name", visible: $(".page-wrapper.rooms").data('main-room') }, | ||||
|         { data: "previews", orderable: false }, | ||||
|         { data: "duration", orderable: false }, | ||||
|         { data: "playbacks", orderable: false }, | ||||
| @@ -55,7 +56,7 @@ class @Recordings | ||||
|             return data | ||||
|         }, | ||||
|         { | ||||
|           targets: 1, | ||||
|           targets: 2, | ||||
|           render: (data, type, row) -> | ||||
|             if type == 'display' | ||||
|               str = '' | ||||
| @@ -66,7 +67,7 @@ class @Recordings | ||||
|             return data | ||||
|         }, | ||||
|         { | ||||
|           targets: 3, | ||||
|           targets: 4, | ||||
|           render: (data, type, row) -> | ||||
|             if type == 'display' | ||||
|               str = '' | ||||
| @@ -157,7 +158,7 @@ class @Recordings | ||||
|   # refresh the recordings from the server | ||||
|   refresh: -> | ||||
|     table_api = this.table.api() | ||||
|     $.get "/rooms/"+Meeting.getInstance().getAdminId()+"/recordings", (data) => | ||||
|     $.get @getRecordingsURL(), (data) => | ||||
|       @setOwner(data.is_owner) | ||||
|       if !@owner | ||||
|         table_api.column(-1).visible(false) | ||||
| @@ -172,11 +173,12 @@ class @Recordings | ||||
|   # setup click handlers for the action buttons | ||||
|   setupActionHandlers: -> | ||||
|     table_api = this.table.api() | ||||
|     recordingsObject = this | ||||
|  | ||||
|     @getTable().on 'click', '.recording-update', (event) -> | ||||
|       btn = $(this) | ||||
|       row = table_api.row($(this).closest('tr')).data() | ||||
|       url = $('.meeting-url').val() | ||||
|       url = recordingsObject.getRecordingsURL() | ||||
|       id = row.id | ||||
|  | ||||
|       published = btn.data('visibility') == "unlisted" || | ||||
| @@ -189,7 +191,7 @@ class @Recordings | ||||
|       data["meta_" + GreenLight.META_LISTED] = listed.toString(); | ||||
|       $.ajax({ | ||||
|         method: 'PATCH', | ||||
|         url: url+'/recordings/'+id, | ||||
|         url: url+'/'+id, | ||||
|         data: data | ||||
|       }).done((data) -> | ||||
|  | ||||
| @@ -200,12 +202,12 @@ class @Recordings | ||||
|     @getTable().on 'click', '.recording-delete', (event) -> | ||||
|       btn = $(this) | ||||
|       row = table_api.row($(this).closest('tr')).data() | ||||
|       url = $('.meeting-url').val() | ||||
|       url = recordingsObject.getRecordingsURL() | ||||
|       id = row.id | ||||
|       btn.prop('disabled', true) | ||||
|       $.ajax({ | ||||
|         method: 'DELETE', | ||||
|         url: url+'/recordings/'+id | ||||
|         url: url+'/'+id | ||||
|       }).done((data) -> | ||||
|  | ||||
|       ).fail((data) -> | ||||
| @@ -218,6 +220,13 @@ class @Recordings | ||||
|   getTable: -> | ||||
|     @table | ||||
|  | ||||
|   getRecordingsURL: -> | ||||
|     if $(".page-wrapper.rooms").data('main-room') | ||||
|       base_url = '/rooms/'+Meeting.getInstance().getAdminId() | ||||
|     else | ||||
|       base_url = $('.meeting-url').val() | ||||
|     base_url+'/recordings' | ||||
|  | ||||
|   isOwner: -> | ||||
|     @owner | ||||
|  | ||||
|   | ||||
| @@ -16,6 +16,11 @@ | ||||
|  | ||||
| class RecordingUpdatesChannel < ApplicationCable::Channel | ||||
|   def subscribed | ||||
|     stream_from "#{params[:encrypted_id]}_recording_updates_channel" | ||||
|     full_id = if params[:meeting_id].present? | ||||
|       "#{params[:admin_id]}-#{params[:meeting_id]}" | ||||
|     else | ||||
|       params[:admin_id] | ||||
|     end | ||||
|     stream_from "#{full_id}_recording_updates_channel" | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -24,6 +24,7 @@ class BbbController < ApplicationController | ||||
|   before_action :validate_checksum, only: :callback | ||||
|  | ||||
|   # GET /:resource/:id/join | ||||
|   # GET /:resource/:room_id/:id/join | ||||
|   def join | ||||
|     if params[:name].blank? | ||||
|       return render_bbb_response( | ||||
| @@ -56,6 +57,7 @@ class BbbController < ApplicationController | ||||
|           wait_for_moderator: true, | ||||
|           meeting_recorded: true, | ||||
|           meeting_name: meeting_name, | ||||
|           room_owner: params[:room_id], | ||||
|           user_is_moderator: current_user == user | ||||
|         } | ||||
|       else | ||||
| @@ -102,6 +104,7 @@ class BbbController < ApplicationController | ||||
|   end | ||||
|  | ||||
|   # DELETE /rooms/:id/end | ||||
|   # DELETE /rooms/:room_id/:id/end | ||||
|   def end | ||||
|     load_and_authorize_room_owner! | ||||
|  | ||||
| @@ -113,30 +116,37 @@ class BbbController < ApplicationController | ||||
|   end | ||||
|  | ||||
|   # GET /rooms/:id/recordings | ||||
|   # GET /rooms/:room_id/:id/recordings | ||||
|   def recordings | ||||
|     load_room! | ||||
|  | ||||
|     # bbb_res = bbb_get_recordings "#{@user.encrypted_id}-#{params[:id]}" | ||||
|     bbb_res = bbb_get_recordings "#{@user.encrypted_id}" | ||||
|     options = { "meta_room-id": @user.encrypted_id } | ||||
|     if params[:id] | ||||
|       options["meta_meeting-name"] = params[:id] | ||||
|     end | ||||
|     bbb_res = bbb_get_recordings(options) | ||||
|     render_bbb_response bbb_res, bbb_res[:recordings] | ||||
|   end | ||||
|  | ||||
|   # PATCH /rooms/:id/recordings/:record_id | ||||
|   # PATCH /rooms/:room_id/:id/recordings/:record_id | ||||
|   def update_recordings | ||||
|     published = params[:published] == 'true' | ||||
|     metadata = params.select{ |k, v| k.match(/^meta_/) } | ||||
|     bbb_res = bbb_update_recordings(params[:record_id], published, metadata) | ||||
|     if bbb_res[:returncode] | ||||
|       RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id]) | ||||
|       RecordingUpdatesJob.perform_later(@user.encrypted_id, params[:record_id], params[:id]) | ||||
|     end | ||||
|     render_bbb_response bbb_res | ||||
|   end | ||||
|  | ||||
|   # DELETE /rooms/:id/recordings/:record_id | ||||
|   # DELETE /rooms/:room_id/:id/recordings/:record_id | ||||
|   def delete_recordings | ||||
|     bbb_res = bbb_delete_recordings(params[:record_id]) | ||||
|     if bbb_res[:returncode] | ||||
|       RecordingDeletesJob.perform_later(@user.encrypted_id, params[:record_id]) | ||||
|       RecordingDeletesJob.perform_later(@user.encrypted_id, params[:record_id], params[:id]) | ||||
|     end | ||||
|     render_bbb_response bbb_res | ||||
|   end | ||||
| @@ -161,7 +171,7 @@ class BbbController < ApplicationController | ||||
|   def authorize_recording_owner! | ||||
|     load_and_authorize_room_owner! | ||||
|  | ||||
|     recordings = bbb_get_recordings(params[:room_id])[:recordings] | ||||
|     recordings = bbb_get_recordings({recordID: params[:record_id]})[:recordings] | ||||
|     recordings.each do |recording| | ||||
|       if recording[:recordID] == params[:record_id] | ||||
|         return true | ||||
| @@ -194,7 +204,7 @@ class BbbController < ApplicationController | ||||
|         # 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 = bbb_get_recordings({recordID: record_id}) | ||||
|         rec_info = rec_info[:recordings].first | ||||
|         RecordingCreatedJob.perform_later(token, parse_recording_for_view(rec_info)) | ||||
|  | ||||
|   | ||||
| @@ -19,16 +19,21 @@ class RecordingDeletesJob < ApplicationJob | ||||
|  | ||||
|   queue_as :default | ||||
|  | ||||
|   def perform(room, record_id) | ||||
|   def perform(room, record_id, meeting=nil) | ||||
|     tries = 0 | ||||
|     sleep_time = 2 | ||||
|  | ||||
|     while tries < 4 | ||||
|       bbb_res = bbb_get_recordings(nil, record_id) | ||||
|       bbb_res = bbb_get_recordings({recordID: record_id}) | ||||
|       if !bbb_res[:recordings] || bbb_res[:messageKey] == 'noRecordings' | ||||
|         full_id = room | ||||
|         full_id += "-#{recording[:metadata][:"meeting-name"]}" | ||||
|         ActionCable.server.broadcast "#{room}_recording_updates_channel", | ||||
|           action: 'delete', | ||||
|           id: record_id | ||||
|         ActionCable.server.broadcast "#{full_id}_recording_updates_channel", | ||||
|           action: 'delete', | ||||
|           id: record_id | ||||
|         break | ||||
|       end | ||||
|       sleep sleep_time | ||||
|   | ||||
| @@ -19,13 +19,20 @@ class RecordingUpdatesJob < ApplicationJob | ||||
|  | ||||
|   queue_as :default | ||||
|  | ||||
|   def perform(room, record_id) | ||||
|     bbb_res = bbb_get_recordings(nil, record_id) | ||||
|   def perform(room, record_id, meeting=nil) | ||||
|     bbb_res = bbb_get_recordings({recordID: record_id}) | ||||
|     recording = bbb_res[:recordings].first | ||||
|     full_id = room | ||||
|     full_id += "-#{recording[:metadata][:"meeting-name"]}" | ||||
|     ActionCable.server.broadcast "#{room}_recording_updates_channel", | ||||
|       action: 'update', | ||||
|       id: record_id, | ||||
|       published: recording[:published], | ||||
|       listed: bbb_is_recording_listed(recording) | ||||
|     ActionCable.server.broadcast "#{full_id}_recording_updates_channel", | ||||
|       action: 'update', | ||||
|       id: record_id, | ||||
|       published: recording[:published], | ||||
|       listed: bbb_is_recording_listed(recording) | ||||
|   end | ||||
| end | ||||
|   | ||||
| @@ -47,6 +47,7 @@ module BbbApi | ||||
|     options[:wait_for_moderator] ||= false | ||||
|     options[:meeting_logout_url] ||= nil | ||||
|     options[:meeting_name] ||= meeting_token | ||||
|     options[:room_owner] ||= nil | ||||
|  | ||||
|     if !bbb | ||||
|       return call_invalid_res | ||||
| @@ -81,6 +82,12 @@ module BbbApi | ||||
|           { "meta_#{BbbApi::META_HOOK_URL}": options[:hook_url] } | ||||
|         ) if options[:hook_url] | ||||
|  | ||||
|         # these parameters are used to filter recordings by room and meeting | ||||
|         meeting_options.merge!( | ||||
|           { "meta_room-id": options[:room_owner], | ||||
|             "meta_meeting-name": options[:meeting_name]} | ||||
|         ) if options[:room_owner] | ||||
|  | ||||
|         if Rails.configuration.use_webhooks | ||||
|           webhook_register(options[:hook_url], meeting_id) | ||||
|         end | ||||
| @@ -114,13 +121,9 @@ module BbbApi | ||||
|     response_data = bbb_exception_res exc | ||||
|   end | ||||
|  | ||||
|   def bbb_get_recordings(meeting_id, record_id=nil) | ||||
|     options={} | ||||
|     if record_id | ||||
|       options[:recordID] = record_id | ||||
|     end | ||||
|     if meeting_id | ||||
|       options[:meetingID] = bbb_meeting_id(meeting_id) | ||||
|   def bbb_get_recordings(options={}) | ||||
|     if options[:meetingID] | ||||
|       options[:meetingID] = bbb_meeting_id(options[:meetingID]) | ||||
|     end | ||||
|     res = bbb_safe_execute :get_recordings, options | ||||
|  | ||||
|   | ||||
| @@ -36,6 +36,7 @@ with BigBlueButton; if not, see <http://www.gnu.org/licenses/>. | ||||
|       <table id="recordings" class="table" width="100%"> | ||||
|         <thead> | ||||
|           <th><%= t('date_recorded') %></th> | ||||
|           <th><%= t('name') %></th> | ||||
|           <th><%= t('thumbnails') %></th> | ||||
|           <th><%= t('duration') %></th> | ||||
|           <th><%= t('views') %></th> | ||||
|   | ||||
| @@ -88,6 +88,7 @@ en-US: | ||||
|       body: "You have been invited by %{user} to a meeting.\n\nPlease open the following page in your web browser: &&URL&&" | ||||
|       subject: "%{user} invited you to a meeting" | ||||
|   my_room: my room | ||||
|   name: Name | ||||
|   no: No | ||||
|   notification_mailer: | ||||
|     recording_ready_email: | ||||
|   | ||||
| @@ -28,18 +28,28 @@ Rails.application.routes.draw do | ||||
|   # There are two resources [meetings|rooms] | ||||
|   # meetings offer a landing page for NON authenticated users to create and join session in BigBlueButton | ||||
|   # rooms offer a customized landing page for authenticated users to create and join session in BigBlueButton | ||||
|  | ||||
|   # recording routes for updating, deleting and viewing recordings | ||||
|   get '/rooms/:room_id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} | ||||
|   patch '/rooms/:room_id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} | ||||
|   delete '/rooms/:room_id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} | ||||
|   get '/rooms/:room_id/:id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} | ||||
|   patch '/rooms/:room_id/:id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} | ||||
|   delete '/rooms/:room_id/:id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} | ||||
|  | ||||
|   # room routes for joining, ending, waiting and refreshing authenticated meetings | ||||
|   get '/rooms/:room_id',  to: 'landing#resource', resource: 'rooms' | ||||
|   get '/rooms/:room_id/:id', to: 'landing#resource', resource: 'rooms' | ||||
|   get '/rooms/:room_id/:id/join', to: 'bbb#join', resource: 'rooms', defaults: {format: 'json'} | ||||
|   delete '/rooms/:room_id/:id/end', to: 'bbb#end', defaults: {format: 'json'} | ||||
|  | ||||
|   # routes shared between meetings and rooms | ||||
|   get '/:resource/:id', to: 'landing#resource', as: :resource | ||||
|   get '/:resource/:id/join', to: 'bbb#join', as: :bbb_join, defaults: {format: 'json'} | ||||
|  | ||||
|   get '/rooms/:room_id/recordings', to: 'bbb#recordings', defaults: {format: 'json'} | ||||
|   post '/:resource/:id/callback', to: 'bbb#callback' #, defaults: {format: 'json'} | ||||
|   patch '/rooms/:id/recordings/:record_id', to: 'bbb#update_recordings', defaults: {format: 'json'} | ||||
|   delete '/rooms/:id/recordings/:record_id', to: 'bbb#delete_recordings', defaults: {format: 'json'} | ||||
|  | ||||
|   get '/:resource/:room_id/:id/wait', to: 'landing#wait_for_moderator' | ||||
|   get '/:resource/:room_id/:id/session_status_refresh', to: 'landing#session_status_refresh' | ||||
|   delete '/rooms/:room_id/:id/end', to: 'bbb#end', defaults: {format: 'json'} | ||||
|   get '/rooms/:room_id/:id', to: 'landing#resource', resource: 'rooms' | ||||
|   get '/:resource/:room_id/:id/join', to: 'bbb#join', defaults: {format: 'json'} | ||||
|  | ||||
|  | ||||
|   root to: 'landing#index', :resource => 'meetings' | ||||
|   | ||||
		Reference in New Issue
	
	Block a user