Class: BigbluebuttonRoom
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- BigbluebuttonRoom
- Includes:
- ActiveModel::ForbiddenAttributesProtection
- Defined in:
- app/models/bigbluebutton_room.rb
Instance Attribute Summary collapse
-
#attendees ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#end_time ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#full_logout_url ⇒ Object
the full logout_url used when logout_url is a relative path.
-
#has_been_forcibly_ended ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#moderator_count ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#participant_count ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#request_headers ⇒ Object
HTTP headers that will be passed to the BigBlueButtonApi object to send in all GET/POST requests to a webconf server.
-
#running ⇒ Object
Note: these params need to be fetched from the server before being accessed.
-
#start_time ⇒ Object
Note: these params need to be fetched from the server before being accessed.
Instance Method Summary collapse
-
#add_domain_to_logout_url(protocol, host) ⇒ Object
add a domain name and/or protocol to the logout_url if needed it doesn’t save in the db, just updates the instance.
-
#attr_equal?(o) ⇒ Boolean
A more complete equal? method, comparing also the attibutes and the instance variables.
- #available_layouts ⇒ Object
- #available_layouts_for_select ⇒ Object
- #available_layouts_names ⇒ Object
-
#create_meeting(user = nil, request = nil, user_opts = {}) ⇒ Object
The create logic.
- #create_meeting_record(metadata = nil) ⇒ Object
-
#fetch_is_running? ⇒ Boolean
Fetches the BBB server to see if the meeting is running.
-
#fetch_meeting_info ⇒ Object
Fetches info from BBB about this room.
-
#fetch_new_token ⇒ Object
Gets a ‘configToken’ to use when joining the room.
- #fetch_recordings(filter = {}) ⇒ Object
-
#finish_meetings ⇒ Object
Sets all meetings related to this room as not running.
-
#generate_dial_number!(pattern = nil) ⇒ Object
Generates a new dial number following ‘pattern` and saves it in the room, returning the results of `update_attributes`.
-
#get_current_meeting ⇒ Object
Returns the current meeting running on this room, if any.
-
#instance_variables_compare(o) ⇒ Object
Compare the instance variables of two models to define if they are equal Returns a hash with the variables with different values or an empty hash if they are have all equal values.
-
#is_running? ⇒ Boolean
Convenience method to access the attribute
running
. -
#join_url(username, role, key = nil, options = {}) ⇒ Object
Returns the URL to join this room.
-
#room_options_with_initialize ⇒ Object
In case there’s no room_options created yet, build one (happens usually when an old database is migrated).
- #select_server(api_method = nil) ⇒ Object
-
#send_create(user = nil, user_opts = {}) ⇒ Object
Sends a call to the BBB server to create the meeting.
-
#send_end ⇒ Object
Sends a call to the BBB server to end the meeting.
- #to_param ⇒ Object
- #unique_meetingid ⇒ Object
-
#update_current_meeting_record(metadata = nil, force_not_ended = false) ⇒ Object
Updates the current meeting associated with this room.
-
#user_role(params) ⇒ Object
Returns the role of the user based on the key given.
Instance Attribute Details
#attendees ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def attendees @attendees end |
#end_time ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def end_time @end_time end |
#full_logout_url ⇒ Object
the full logout_url used when logout_url is a relative path
70 71 72 |
# File 'app/models/bigbluebutton_room.rb', line 70 def full_logout_url @full_logout_url end |
#has_been_forcibly_ended ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def has_been_forcibly_ended @has_been_forcibly_ended end |
#moderator_count ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def moderator_count @moderator_count end |
#participant_count ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def participant_count @participant_count end |
#request_headers ⇒ Object
HTTP headers that will be passed to the BigBlueButtonApi object to send in all GET/POST requests to a webconf server. Currently used to send the client’s IP to the load balancer.
75 76 77 |
# File 'app/models/bigbluebutton_room.rb', line 75 def request_headers @request_headers end |
#running ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def running @running end |
#start_time ⇒ Object
Note: these params need to be fetched from the server before being accessed
61 62 63 |
# File 'app/models/bigbluebutton_room.rb', line 61 def start_time @start_time end |
Instance Method Details
#add_domain_to_logout_url(protocol, host) ⇒ Object
add a domain name and/or protocol to the logout_url if needed it doesn’t save in the db, just updates the instance
293 294 295 296 297 298 299 300 301 302 303 304 |
# File 'app/models/bigbluebutton_room.rb', line 293 def add_domain_to_logout_url(protocol, host) unless logout_url.nil? url = logout_url.downcase unless url.nil? or url =~ /^[a-z]+:\/\// # matches the protocol unless url =~ /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*/ # matches the host domain url = host + url end url = protocol + url end self.full_logout_url = url.downcase end end |
#attr_equal?(o) ⇒ Boolean
A more complete equal? method, comparing also the attibutes and the instance variables
263 264 265 266 267 |
# File 'app/models/bigbluebutton_room.rb', line 263 def attr_equal?(o) self == o and self.instance_variables_compare(o).empty? and self.attributes == o.attributes end |
#available_layouts ⇒ Object
435 436 437 438 |
# File 'app/models/bigbluebutton_room.rb', line 435 def available_layouts server = BigbluebuttonRails.configuration.select_server.call(self) server.present? ? server.available_layouts : [] end |
#available_layouts_for_select ⇒ Object
445 446 447 448 |
# File 'app/models/bigbluebutton_room.rb', line 445 def available_layouts_for_select server = BigbluebuttonRails.configuration.select_server.call(self) server.present? ? server.available_layouts_for_select : [] end |
#available_layouts_names ⇒ Object
440 441 442 443 |
# File 'app/models/bigbluebutton_room.rb', line 440 def available_layouts_names server = BigbluebuttonRails.configuration.select_server.call(self) server.present? ? server.available_layouts_names : [] end |
#create_meeting(user = nil, request = nil, user_opts = {}) ⇒ Object
The create logic. Will create the meeting in this room unless it is already running. Returns true if the meeting was created.
276 277 278 279 280 281 282 283 284 285 286 287 288 289 |
# File 'app/models/bigbluebutton_room.rb', line 276 def create_meeting(user=nil, request=nil, user_opts={}) fetch_is_running? unless is_running? # in case the meeting is not running but it's still in memory suppress(BigBlueButton::BigBlueButtonException) { send_end } add_domain_to_logout_url(request.protocol, request.host_with_port) unless request.nil? send_create(user, user_opts) true else false end end |
#create_meeting_record(metadata = nil) ⇒ Object
348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 |
# File 'app/models/bigbluebutton_room.rb', line 348 def create_meeting_record(=nil) unless get_current_meeting.present? if self.create_time.present? # to make sure there's no other meeting related to this room that # has not yet been set as ended self.finish_meetings server = BigbluebuttonRails.configuration.select_server.call(self) attrs = { room: self, server_url: server.url, server_secret: server.secret, meetingid: self.meetingid, name: self.name, recorded: self.record_meeting, create_time: self.create_time, running: self.running, ended: false, start_time: self.start_time.try(:utc) } unless .nil? begin attrs[:creator_id] = [BigbluebuttonRails.configuration.].to_i attrs[:creator_name] = [BigbluebuttonRails.configuration.] rescue attrs[:creator_id] = nil attrs[:creator_name] = nil end end BigbluebuttonMeeting.create(attrs) Rails.logger.error "Did not create a current meeting because there was no create_time on room #{self.meetingid}" else Rails.logger.error "Did not create a current meeting because there was no create_time on room #{self.meetingid}" end end end |
#fetch_is_running? ⇒ Boolean
Fetches the BBB server to see if the meeting is running. Sets running
Triggers API call: isMeetingRunning
.
146 147 148 149 |
# File 'app/models/bigbluebutton_room.rb', line 146 def fetch_is_running? server = BigbluebuttonRails.configuration.select_server.call(self, :is_meeting_running) @running = server.api.is_meeting_running?(self.meetingid) end |
#fetch_meeting_info ⇒ Object
Fetches info from BBB about this room. The response is parsed and stored in the model. You can access it using attributes such as:
room.participant_count
room.attendees[0].full_name
The attributes changed are:
-
participant_count
-
moderator_count
-
running
-
has_been_forcibly_ended
-
start_time
-
end_time
-
attendees
(array ofBigbluebuttonAttendee
)
Triggers API call: getMeetingInfo
.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'app/models/bigbluebutton_room.rb', line 105 def fetch_meeting_info begin server = BigbluebuttonRails.configuration.select_server.call(self, :get_meeting_info) response = server.api.get_meeting_info(self.meetingid, self.moderator_api_password) @participant_count = response[:participantCount] @moderator_count = response[:moderatorCount] @running = response[:running] @has_been_forcibly_ended = response[:hasBeenForciblyEnded] @start_time = response[:startTime] @end_time = response[:endTime] @attendees = [] if response[:attendees].present? response[:attendees].each do |att| attendee = BigbluebuttonAttendee.new attendee.from_hash(att) @attendees << attendee end end # a 'shortcut' to update meetings since we have all information we need # if we got here, it means the meeting is still in the server, so it's not ended self.update_attributes(create_time: response[:createTime]) unless self.new_record? self.update_current_meeting_record(response[:metadata], true) rescue BigBlueButton::BigBlueButtonException => e # note: we could catch only the 'notFound' error, but there are complications, so # it's better to end the meeting prematurely and open it again if needed than to # not end it at all (e.g. in case the server stops responding) Rails.logger.info "BigbluebuttonRoom: detected that a meeting ended in the room #{self.meetingid} after the error #{e.inspect}" self.update_attributes(create_time: nil) unless self.new_record? self.finish_meetings end response end |
#fetch_new_token ⇒ Object
Gets a ‘configToken’ to use when joining the room. Returns a string with the token generated or nil if there’s no need for a token (the options set in the room are the default options or there are no options set in the room) or if an error occurred.
The entire process consists in these steps:
-
Go to the server get the default config.xml;
-
Modify the config.xml based on the room options set in the room;
-
Go to the server set the new config.xml;
-
Get the token identifier and return it.
Triggers API call: getDefaultConfigXML
. Triggers API call: setConfigXML
.
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
# File 'app/models/bigbluebutton_room.rb', line 413 def fetch_new_token if self..is_modified? server = BigbluebuttonRails.configuration.select_server.call(self, :set_config_xml) # get the default XML we will use to create a new one config_xml = server.api.get_default_config_xml # set the options on the XML # returns true if something was changed config_xml = self..set_on_config_xml(config_xml) if config_xml server.update_config(config_xml) # get the new token for the room, and return it server.api.set_config_xml(self.meetingid, config_xml) else nil end else nil end end |
#fetch_recordings(filter = {}) ⇒ Object
465 466 467 468 469 470 471 472 473 |
# File 'app/models/bigbluebutton_room.rb', line 465 def fetch_recordings(filter={}) server = BigbluebuttonRails.configuration.select_server.call(self, :get_recordings) if server.present? server.fetch_recordings(filter.merge({ meetingID: self.meetingid })) true else false end end |
#finish_meetings ⇒ Object
Sets all meetings related to this room as not running
388 389 390 391 392 393 394 395 396 397 398 |
# File 'app/models/bigbluebutton_room.rb', line 388 def finish_meetings BigbluebuttonMeeting.where(ended: false) .where(room_id: self.id) .update_all(running: false, ended: true) # in case there are inconsistent meetings marked as running # but that already ended BigbluebuttonMeeting.where(running: true, ended: true) .where(room_id: self.id) .update_all(running: false, ended: true) end |
#generate_dial_number!(pattern = nil) ⇒ Object
Generates a new dial number following ‘pattern` and saves it in the room, returning the results of `update_attributes`. Will always generate a unique number. Tries several times if the number already exists and returns `nil` in case it wasn’t possible to generate a unique value.
454 455 456 457 458 459 460 461 462 463 |
# File 'app/models/bigbluebutton_room.rb', line 454 def generate_dial_number!(pattern=nil) pattern ||= 'xxxx-xxxx' 20.times do dn = BigbluebuttonRails::DialNumber.randomize(pattern) if BigbluebuttonRoom.where(dial_number: dn).empty? return self.update_attributes(dial_number: dn) end end nil end |
#get_current_meeting ⇒ Object
Returns the current meeting running on this room, if any.
314 315 316 317 318 319 320 |
# File 'app/models/bigbluebutton_room.rb', line 314 def get_current_meeting unless self.create_time.nil? BigbluebuttonMeeting.find_by(room_id: self.id, create_time: self.create_time) else nil end end |
#instance_variables_compare(o) ⇒ Object
Compare the instance variables of two models to define if they are equal Returns a hash with the variables with different values or an empty hash if they are have all equal values. From: alicebobandmallory.com/articles/2009/11/02/comparing-instance-variables-in-ruby
253 254 255 256 257 258 259 |
# File 'app/models/bigbluebutton_room.rb', line 253 def instance_variables_compare(o) vars = [ :@running, :@participant_count, :@moderator_count, :@attendees, :@has_been_forcibly_ended, :@start_time, :@end_time ] Hash[*vars.map { |v| self.instance_variable_get(v)!=o.instance_variable_get(v) ? [v,o.instance_variable_get(v)] : []}.flatten] end |
#is_running? ⇒ Boolean
Convenience method to access the attribute running
85 86 87 |
# File 'app/models/bigbluebutton_room.rb', line 85 def is_running? @running end |
#join_url(username, role, key = nil, options = {}) ⇒ Object
Returns the URL to join this room.
- username
-
Name of the user
- role
-
Role of the user in this room. Can be
[:moderator, :attendee]
- key
-
Key to be use (in case role == nil)
- options
-
Additional options to use when generating the URL
Uses the API but does not require a request to the server.
210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'app/models/bigbluebutton_room.rb', line 210 def join_url(username, role, key=nil, ={}) server = BigbluebuttonRails.configuration.select_server.call(self, :join_meeting_url) pass = case role when :moderator self.moderator_api_password when :attendee self.attendee_api_password when :guest if BigbluebuttonRails.configuration.guest_support = { guest: true }.merge() end self.attendee_api_password else map_key_to_internal_password(key) end r = server.api.join_meeting_url(self.meetingid, username, pass, ) r.strip! unless r.nil? r end |
#room_options_with_initialize ⇒ Object
In case there’s no room_options created yet, build one (happens usually when an old database is migrated).
79 80 81 |
# File 'app/models/bigbluebutton_room.rb', line 79 def || end |
#select_server(api_method = nil) ⇒ Object
475 476 477 478 479 480 481 482 |
# File 'app/models/bigbluebutton_room.rb', line 475 def select_server(api_method=nil) server = BigbluebuttonServer.first if server.nil? msg = I18n.t('bigbluebutton_rails.rooms.errors.server.nil') raise BigbluebuttonRails::ServerRequired.new(msg) end server end |
#send_create(user = nil, user_opts = {}) ⇒ Object
Sends a call to the BBB server to create the meeting. ‘user’ is the object that represents the user that is creating the meeting. ‘user_opts’ is a hash of parameters to override the parameters sent in the create
request. Can be passed by the application to enforce some values over the values
that are taken from the database.
With the response, updates the following attributes:
-
attendee_api_password
-
moderator_api_password
Triggers API call: create
.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'app/models/bigbluebutton_room.rb', line 175 def send_create(user=nil, user_opts={}) self.meetingid = unique_meetingid() if self.meetingid.blank? self.moderator_api_password = internal_password() if self.moderator_api_password.blank? self.attendee_api_password = internal_password() if self.attendee_api_password.blank? self.save unless self.new_record? response = internal_create_meeting(user, user_opts) unless response.nil? self.attendee_api_password = response[:attendeePW] self.moderator_api_password = response[:moderatorPW] self.create_time = response[:createTime] self.voice_bridge = response[:voiceBridge] if response.has_key?(:voiceBridge) unless self.new_record? self.save # creates the meeting object since the create was successful create_meeting_record(response[:metadata]) # enqueue an update in the meeting with a small delay we assume to be # enough for the user to fully join the meeting Resque.enqueue(::BigbluebuttonMeetingUpdater, self.id, 10.seconds) end end response end |
#send_end ⇒ Object
Sends a call to the BBB server to end the meeting.
Triggers API call: end
.
154 155 156 157 158 159 160 161 162 |
# File 'app/models/bigbluebutton_room.rb', line 154 def send_end server = BigbluebuttonRails.configuration.select_server.call(self, :end) response = server.api.end_meeting(self.meetingid, self.moderator_api_password) # enqueue an update in the meeting to end it faster Resque.enqueue(::BigbluebuttonMeetingUpdater, self.id) response end |
#to_param ⇒ Object
269 270 271 |
# File 'app/models/bigbluebutton_room.rb', line 269 def to_param self.param end |
#unique_meetingid ⇒ Object
306 307 308 309 310 311 |
# File 'app/models/bigbluebutton_room.rb', line 306 def unique_meetingid # GUID # Has to be globally unique in case more that one bigbluebutton_rails application is using # the same web conference server. "#{SecureRandom.uuid}-#{Time.now.to_i}" end |
#update_current_meeting_record(metadata = nil, force_not_ended = false) ⇒ Object
Updates the current meeting associated with this room
323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 |
# File 'app/models/bigbluebutton_room.rb', line 323 def update_current_meeting_record(=nil, force_not_ended=false) unless self.create_time.nil? attrs = { :running => self.running, :start_time => self.start_time.try(:utc) } # note: it's important to update the 'ended' attr so the meeting is # reopened in case it was mistakenly considered as ended attrs[:ended] = false if force_not_ended unless .nil? begin attrs[:creator_id] = [BigbluebuttonRails.configuration.].to_i attrs[:creator_name] = [BigbluebuttonRails.configuration.] rescue attrs[:creator_id] = nil attrs[:creator_name] = nil end end meeting = self.get_current_meeting meeting.update_attributes(attrs) if meeting.present? end end |
#user_role(params) ⇒ Object
Returns the role of the user based on the key given. The return value can be :moderator
, :attendee
, or nil if the key given does not match any of the room keys.
- params
-
Hash with a key :key
237 238 239 240 241 242 243 244 245 246 247 |
# File 'app/models/bigbluebutton_room.rb', line 237 def user_role(params) role = nil if params && params.has_key?(:key) if self.moderator_key == params[:key] role = :moderator elsif self.attendee_key == params[:key] role = :attendee end end role end |