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.
-
#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).
-
#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
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 def attendees @attendees end |
#end_time ⇒ Object
Note: these params need to be fetched from the server before being accessed
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 def end_time @end_time end |
#full_logout_url ⇒ Object
the full logout_url used when logout_url is a relative path
72 73 74 |
# File 'app/models/bigbluebutton_room.rb', line 72 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
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 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
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 def moderator_count @moderator_count end |
#participant_count ⇒ Object
Note: these params need to be fetched from the server before being accessed
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 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.
77 78 79 |
# File 'app/models/bigbluebutton_room.rb', line 77 def request_headers @request_headers end |
#running ⇒ Object
Note: these params need to be fetched from the server before being accessed
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 def running @running end |
#start_time ⇒ Object
Note: these params need to be fetched from the server before being accessed
63 64 65 |
# File 'app/models/bigbluebutton_room.rb', line 63 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
296 297 298 299 300 301 302 303 304 305 306 307 |
# File 'app/models/bigbluebutton_room.rb', line 296 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
266 267 268 269 270 |
# File 'app/models/bigbluebutton_room.rb', line 266 def attr_equal?(o) self == o and self.instance_variables_compare(o).empty? and self.attributes == o.attributes end |
#available_layouts ⇒ Object
437 438 439 |
# File 'app/models/bigbluebutton_room.rb', line 437 def available_layouts server.present? ? server.available_layouts : [] end |
#available_layouts_for_select ⇒ Object
445 446 447 |
# File 'app/models/bigbluebutton_room.rb', line 445 def available_layouts_for_select server.present? ? server.available_layouts_for_select : [] end |
#available_layouts_names ⇒ Object
441 442 443 |
# File 'app/models/bigbluebutton_room.rb', line 441 def available_layouts_names 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.
279 280 281 282 283 284 285 286 287 288 289 290 291 292 |
# File 'app/models/bigbluebutton_room.rb', line 279 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
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 386 387 388 |
# File 'app/models/bigbluebutton_room.rb', line 351 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 attrs = { room: self, server: self.server, server_url: self.server.url, server_secret: self.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.].to_i attrs[:creator_name] = [BigbluebuttonRails.] 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.
149 150 151 152 |
# File 'app/models/bigbluebutton_room.rb', line 149 def fetch_is_running? require_server :is_meeting_running @running = self.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.
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 142 143 144 |
# File 'app/models/bigbluebutton_room.rb', line 107 def fetch_meeting_info require_server :get_meeting_info begin response = self.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.
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 |
# File 'app/models/bigbluebutton_room.rb', line 416 def fetch_new_token if self..is_modified? # get the default XML we will use to create a new one config_xml = self.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 self.server.update_config(config_xml) # get the new token for the room, and return it self.server.api.set_config_xml(self.meetingid, config_xml) else nil end else nil end end |
#finish_meetings ⇒ Object
Sets all meetings related to this room as not running
391 392 393 394 395 396 397 398 399 400 401 |
# File 'app/models/bigbluebutton_room.rb', line 391 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.
453 454 455 456 457 458 459 460 461 462 |
# File 'app/models/bigbluebutton_room.rb', line 453 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.
317 318 319 320 321 322 323 |
# File 'app/models/bigbluebutton_room.rb', line 317 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
256 257 258 259 260 261 262 |
# File 'app/models/bigbluebutton_room.rb', line 256 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
87 88 89 |
# File 'app/models/bigbluebutton_room.rb', line 87 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.
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 |
# File 'app/models/bigbluebutton_room.rb', line 219 def join_url(username, role, key=nil, ={}) require_server :join_meeting_url case role when :moderator r = self.server.api.join_meeting_url(self.meetingid, username, self.moderator_api_password, ) when :attendee r = self.server.api.join_meeting_url(self.meetingid, username, self.attendee_api_password, ) else r = self.server.api.join_meeting_url(self.meetingid, username, map_key_to_internal_password(key), ) end 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).
81 82 83 |
# File 'app/models/bigbluebutton_room.rb', line 81 def || 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.
Will trigger ‘select_server’ to select a server where the meeting will be created. If a server is selected, the model is saved.
With the response, updates the following attributes:
-
attendee_api_password -
moderator_api_password
Triggers API call: create.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 |
# File 'app/models/bigbluebutton_room.rb', line 181 def send_create(user=nil, user_opts={}) # updates the server whenever a meeting will be created and guarantees it has a meetingid require_server :create 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.
157 158 159 160 161 162 163 164 165 |
# File 'app/models/bigbluebutton_room.rb', line 157 def send_end require_server :end response = self.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
272 273 274 |
# File 'app/models/bigbluebutton_room.rb', line 272 def to_param self.param end |
#unique_meetingid ⇒ Object
309 310 311 312 313 314 |
# File 'app/models/bigbluebutton_room.rb', line 309 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
326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 |
# File 'app/models/bigbluebutton_room.rb', line 326 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.].to_i attrs[:creator_name] = [BigbluebuttonRails.] 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
240 241 242 243 244 245 246 247 248 249 250 |
# File 'app/models/bigbluebutton_room.rb', line 240 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 |