bigbluebutton-api-ruby 0.0.4 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ pkg
3
+ *.*~
4
+ test/config.yml
5
+ doc/rdoc
data/CHANGELOG.rdoc ADDED
@@ -0,0 +1,23 @@
1
+ == 0.0.5
2
+
3
+ * New method test_connection.
4
+ * Added comparison method for APIs.
5
+ * Methods attendee_url and moderator_url deprecated. Use join_meeting_url.
6
+ * Better exception throwing when the user is unreachable or the response is incorrect.
7
+ * BigBlueButtonException has now a "key" attribute to store the "messageKey" returned by BBB in failures.
8
+
9
+ == 0.0.4
10
+
11
+ * Added support for BigBlueButton 0.7.
12
+ * Gem renamed from 'bigbluebutton' to 'bigbluebutton-api-ruby'.
13
+ * API functions now return a hash and instead of the XML returned by BBB. The XML is converted to a hash that uses symbols as keys and groups keys with the same name.
14
+
15
+ == 0.0.3
16
+
17
+ * Fixes module issue preventing proper throwing of exceptions.
18
+
19
+ == 0.0.1
20
+
21
+ * This is the first version of this gem. It provides an implementation of the 0.64 bbb API, with the following exceptions:
22
+ * Does not implement meeting token, and instead relies on meeting id as the unique identifier for a meeting.
23
+ * Documentation suggests there is way to call join_meeting as API call (instead of browser URL). This call currently does not work as documented.
data/LICENSE CHANGED
@@ -1,6 +1,9 @@
1
1
  == bigbluebutton-api-ruby
2
2
 
3
3
  Copyright (c) 2011 Leonardo Crauss Daronco
4
+ GT-Mconf: Multiconference system for interoperable web and mobile
5
+ * http://www.inf.ufrgs.br/prav/gtmconf
6
+ * PRAV Labs - UFRGS
4
7
 
5
8
  Copyright (c) 2010 Joe Kinsella
6
9
 
data/README.rdoc ADDED
@@ -0,0 +1,32 @@
1
+ = Project: bigbluebutton-api-ruby
2
+
3
+ == Goal
4
+
5
+ Provide access to the BigBlueButton web conferencing API.
6
+
7
+ == Dependencies
8
+
9
+ Tested in Ruby 1.8.7 and Ruby 1.9.2.
10
+
11
+ Needs: rake, rubygems, nokogiri
12
+
13
+ == Releases
14
+
15
+ See CHANGELOG.rdoc
16
+
17
+ == Contact
18
+
19
+ === Version 0.0.4+
20
+
21
+ Author:: Leonardo Crauss Daronco
22
+ Email:: leonardodaronco@gmail.com
23
+ Project:: GT-Mconf: Multiconference system for interoperable web and mobile @ PRAV Labs - UFRGS
24
+ Home Page:: http://www.inf.ufrgs.br/prav/gtmconf/
25
+ License:: Distributed under same terms as Ruby
26
+
27
+ === Version 0.0.3 and below
28
+
29
+ Author:: Joe Kinsella
30
+ Email:: joe.kinsella@gmail.com
31
+ Home Page:: http://www.brownbaglunch.com/bigbluebutton
32
+ License:: Distributes under same terms as Ruby
data/Rakefile CHANGED
@@ -1,45 +1,28 @@
1
- #
2
- # To change this template, choose Tools | Templates
3
- # and open the template in the editor.
4
-
5
1
  require 'rubygems'
6
2
  require 'rake'
7
3
  require 'rake/clean'
8
- require 'rake/gempackagetask'
9
4
  require 'rake/rdoctask'
10
5
  require 'rake/testtask'
6
+ require 'rake/gempackagetask'
11
7
 
12
- spec = Gem::Specification.new do |s|
13
- s.name = 'bigbluebutton-api-ruby'
14
- s.version = '0.0.4'
15
- s.has_rdoc = true
16
- s.extra_rdoc_files = ['README', 'LICENSE']
17
- s.summary = 'Provides an interface to the BigBlueButton web meeting API (https://github.com/mconf/bigbluebutton-api-ruby)'
18
- s.description = s.summary
19
- s.author = 'Leonardo Crauss Daronco'
20
- s.email = 'leonardodaronco@gmail.com'
21
- s.homepage = "https://github.com/mconf/bigbluebutton-api-ruby/"
22
- # s.executables = ['your_executable_here']
23
- s.files = %w(LICENSE README Rakefile) + Dir.glob("{bin,lib,doc,test,spec}/**/*")
24
- s.require_path = "lib"
25
- s.bindir = "bin"
26
- end
27
-
28
- Rake::GemPackageTask.new(spec) do |p|
29
- p.gem_spec = spec
30
- p.need_tar = true
31
- p.need_zip = true
32
- end
8
+ desc 'Default: run tests.'
9
+ task :default => :test
33
10
 
34
11
  Rake::RDocTask.new do |rdoc|
35
- files =['README', 'LICENSE', 'lib/**/*.rb']
12
+ files = ['README.rdoc', 'LICENSE', 'CHANGELOG.rdoc', 'lib/**/*.rb']
36
13
  rdoc.rdoc_files.add(files)
37
14
  rdoc.main = "README" # page to start on
38
15
  rdoc.title = "bigbluebutton-api-ruby Docs"
39
- rdoc.rdoc_dir = 'doc/' # rdoc output folder
16
+ rdoc.rdoc_dir = 'doc' # rdoc output folder
40
17
  rdoc.options << '--line-numbers'
41
18
  end
42
19
 
20
+ eval("$specification = begin; #{ IO.read('bigbluebutton-api-ruby.gemspec')}; end")
21
+ Rake::GemPackageTask.new $specification do |pkg|
22
+ pkg.need_tar = true
23
+ pkg.need_zip = true
24
+ end
25
+
43
26
  desc 'Test the gem.'
44
27
  Rake::TestTask.new(:test) do |t|
45
28
  t.pattern = 'test/**/*test.rb'
@@ -0,0 +1,18 @@
1
+ $:.push File.expand_path("../lib", __FILE__)
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = 'bigbluebutton-api-ruby'
5
+ s.version = '0.0.6'
6
+ s.has_rdoc = true
7
+ s.extra_rdoc_files = ['README.rdoc', 'LICENSE', 'CHANGELOG.rdoc']
8
+ s.summary = 'Provides an interface to the BigBlueButton web meeting API (https://github.com/mconf/bigbluebutton-api-ruby)'
9
+ s.description = s.summary
10
+ s.authors = ['Leonardo Crauss Daronco', 'Joe Kinsella']
11
+ s.email = ['leonardodaronco@gmail.com', 'joe.kinsella@gmail.com']
12
+ s.homepage = "https://github.com/mconf/bigbluebutton-api-ruby/"
13
+ s.bindir = "bin"
14
+ s.files = `git ls-files`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_runtime_dependency('nokogiri', '~> 1.4.0')
18
+ end
@@ -9,22 +9,32 @@ require 'hash_to_xml'
9
9
  module BigBlueButton
10
10
 
11
11
  class BigBlueButtonException < Exception
12
+ attr_accessor :key
13
+
14
+ def to_s
15
+ unless key.blank?
16
+ super.to_s + ", messageKey: #{key}"
17
+ else
18
+ super
19
+ end
20
+ end
12
21
 
13
22
  end
14
23
 
15
- # This class provides access to the BigBlueButton API. BigBlueButton
24
+ # This class provides access to the BigBlueButton API. BigBlueButton
16
25
  # is an open source project that provides web conferencing for distance
17
26
  # education (http://code.google.com/p/bigbluebutton/wiki/API). This API
18
- # was developed to support the following version of bbb: 0.64, 0.7
19
- #
27
+ # was developed to support the following version of BBB: 0.64, 0.7
28
+ #
20
29
  # Sample usage of the API is as follows:
21
30
  # 1) Create a meeting with the create_meeting call
22
- # 2) Direct a user to either moderator_url or attendee_url
31
+ # 2) Direct a user to either join_meeting_url
23
32
  # 3) To force meeting to end, call end_meeting
24
33
  #
25
34
  # 0.0.4+:
26
35
  # Author:: Leonardo Crauss Daronco (mailto:leonardodaronco@gmail.com)
27
36
  # Copyright:: Copyright (c) 2011 Leonardo Crauss Daronco
37
+ # Project:: GT-Mconf: Multiconference system for interoperable web and mobile @ PRAV Labs - UFRGS
28
38
  # License:: Distributes under same terms as Ruby
29
39
  #
30
40
  # 0.0.3 and below:
@@ -32,45 +42,54 @@ module BigBlueButton
32
42
  # Copyright:: Copyright (c) 2010 Joe Kinsella
33
43
  # License:: Distributes under same terms as Ruby
34
44
  #
35
- # TODO: api version returned on index - added in 0.7
45
+ # TODO: Automatically detect API version using request to index - added in 0.7
36
46
  #
37
47
  class BigBlueButtonApi
38
48
 
49
+ attr_accessor :url, :supported_versions, :salt, :version, :debug
50
+
39
51
  # Initializes an instance
40
- # base_url:: URL to a BigBlueButton server (e.g. http://demo.bigbluebutton.org/bigbluebutton/api)
52
+ # url:: URL to a BigBlueButton server (e.g. http://demo.bigbluebutton.org/bigbluebutton/api)
41
53
  # salt:: Secret salt for this server
42
54
  # version:: API version: 0.64 or 0.7
43
- def initialize(base_url, salt, version='0.7', debug=false)
55
+ def initialize(url, salt, version='0.7', debug=false)
44
56
  @supported_versions = ['0.7', '0.64']
45
57
  unless @supported_versions.include?(version)
46
58
  raise BigBlueButtonException.new("BigBlueButton error: Invalid API version #{version}. Supported versions: #{@supported_versions.join(', ')}")
47
59
  end
48
- @session = {}
49
- @base_url = base_url
60
+ @url = url
50
61
  @salt = salt
51
62
  @debug = debug
52
63
  @version = version
53
64
  puts "BigBlueButtonAPI: Using version #{@version}" if @debug
54
65
  end
55
66
 
56
- # Returns url to login as moderator
57
- # meeting_id:: Unique identifier for the meeting
58
- # user_name:: Name of the user
59
- # password:: Moderator password for this meeting
60
- def moderator_url(meeting_id, user_name, password)
61
- attendee_url(meeting_id, user_name, password)
67
+ # DEPRECATED
68
+ # Use join_meeting_url
69
+ def moderator_url(meeting_id, user_name, password,
70
+ user_id = nil, web_voice_conf = nil)
71
+ warn "#{caller[0]}: moderator_url is deprecated and will soon be removed, please use join_meeting_url instead."
72
+ join_meeting_url_url(meeting_id, user_name, password, user_id, web_voice_conf)
62
73
  end
63
74
 
64
- # Returns url to login as attendee
75
+ # DEPRECATED
76
+ # Use join_meeting_url
77
+ def attendee_url(meeting_id, user_name, password,
78
+ user_id = nil, web_voice_conf = nil)
79
+ warn "#{caller[0]}: attendee_url is deprecated and will soon be removed, please use join_meeting_url instead."
80
+ join_meeting_url(meeting_id, user_name, password, user_id, web_voice_conf)
81
+ end
82
+
83
+ # Returns the url used to join the meeting
65
84
  # meeting_id:: Unique identifier for the meeting
66
85
  # user_name:: Name of the user
67
- # password:: Attendee password for this meeting
68
- # user_id:: Unique identifier for this user (>=0.7)
69
- # web_voice_conf:: Custom voice-extension for users using VoIP (>=0.7)
70
- def attendee_url(meeting_id, user_name, attendee_password,
71
- user_id = nil, web_voice_conf = nil)
86
+ # password:: Password for this meeting - used to set the user as moderator or attendee
87
+ # user_id:: Unique identifier for this user (>= 0.7)
88
+ # web_voice_conf:: Custom voice-extension for users using VoIP (>= 0.7)
89
+ def join_meeting_url(meeting_id, user_name, password,
90
+ user_id = nil, web_voice_conf = nil)
72
91
 
73
- params = { :meetingID => meeting_id, :password => attendee_password, :fullName => user_name }
92
+ params = { :meetingID => meeting_id, :password => password, :fullName => user_name }
74
93
  if @version == '0.7'
75
94
  params[:userID] = user_id
76
95
  params[:webVoiceConf] = web_voice_conf
@@ -89,7 +108,7 @@ module BigBlueButton
89
108
  # logout_url:: URL to return user to after exiting meeting
90
109
  # voice_bridge:: Voice conference number (>=0.7)
91
110
  # TODO check if voice_bridge exists in 0.64
92
- def create_meeting(meeting_name, meeting_id, moderator_password, attendee_password,
111
+ def create_meeting(meeting_name, meeting_id, moderator_password, attendee_password,
93
112
  welcome_message = nil, dial_number = nil, logout_url = nil,
94
113
  max_participants = nil, voice_bridge = nil)
95
114
 
@@ -131,7 +150,7 @@ module BigBlueButton
131
150
  def join_meeting(meeting_id, user_name, password, user_id = nil, web_voice_conf = nil)
132
151
  params = { :meetingID => meeting_id, :password => password, :fullName => user_name }
133
152
  if @version == '0.64'
134
- params[:redirectImmediately] = 0
153
+ params[:redirectImmediately] = 0
135
154
  elsif @version == '0.7'
136
155
  params[:userID] = user_id
137
156
  params[:webVoiceConf] = web_voice_conf
@@ -152,47 +171,81 @@ module BigBlueButton
152
171
  # Returns a hash object containing the meeting information.
153
172
  # See the API documentation for details on the return XML
154
173
  # (http://code.google.com/p/bigbluebutton/wiki/API).
155
- # >= 0.7
156
- #
157
- # TODO check if getMeetings exists in 0.64
158
174
  def get_meetings
175
+ send_api_request(:getMeetings, { :random => rand(9999999999) } )
176
+ end
177
+
178
+ # Make a simple request to the server to test the connection
179
+ # TODO implement test for version 0.64
180
+ def test_connection
159
181
  if @version == '0.7'
160
- send_api_request(:getMeetings, { :random => rand(9999999999) } )
182
+ response = send_api_request(:index)
183
+ response[:returncode] == "SUCCESS"
161
184
  else
162
- {}
185
+ true
186
+ end
187
+ end
188
+
189
+ # API's are equal if all the following attributes are equal
190
+ def == other
191
+ r = true
192
+ [:url, :supported_versions, :salt, :version, :debug].each do |param|
193
+ r = r and self.send(param) == other.send(param)
163
194
  end
195
+ r
164
196
  end
165
197
 
166
198
  protected
167
199
 
168
200
  def get_url(method, data)
169
- base_url = "#{@base_url}/#{method}?"
201
+ if method == :index
202
+ return @url
203
+ end
204
+
205
+ url = "#{@url}/#{method}?"
206
+
207
+ data.delete_if { |k, v| v.nil? } unless data.nil?
170
208
  params = ""
171
209
  params = data.map{ |k,v| "#{k}=" + CGI::escape(v.to_s) unless k.nil? || v.nil? }.join("&")
210
+
172
211
  checksum_param = params + @salt
173
212
  checksum_param = method.to_s + checksum_param if @version == '0.7'
174
213
  checksum = Digest::SHA1.hexdigest(checksum_param)
175
- "#{base_url}#{params}&checksum=#{checksum}"
214
+
215
+ "#{url}#{params}&checksum=#{checksum}"
176
216
  end
177
217
 
178
218
  def send_api_request(method, data = {})
179
219
  url = get_url(method, data)
180
- res = Net::HTTP.get_response(URI.parse(url))
181
- puts "BigBlueButtonAPI: URL request = #{url}" if @debug
182
- puts "BigBlueButtonAPI: URL response = #{res.body}" if @debug
220
+ begin
221
+ res = Net::HTTP.get_response(URI.parse(url))
222
+ puts "BigBlueButtonAPI: URL request = #{url}" if @debug
223
+ puts "BigBlueButtonAPI: URL response = #{res.body}" if @debug
224
+ rescue Exception => socketerror
225
+ raise BigBlueButtonException.new("Connection error. Your URL is probably incorrect: \"#{@url}\"")
226
+ end
183
227
 
184
228
  if res.body.empty?
185
- raise BigBlueButtonException.new("BigBlueButton error: No XML in the response body")
229
+ raise BigBlueButtonException.new("No response body")
186
230
  end
187
231
 
188
- # 'Hashfy' the XML and remove the "response" node
232
+ # 'Hashify' the XML
189
233
  hash = Hash.from_xml res.body
234
+
235
+ # simple validation of the xml body
236
+ unless hash.has_key?(:response) and hash[:response].has_key?(:returncode)
237
+ raise BigBlueButtonException.new("Invalid response body. Is the API URL correct? \"#{@url}\", version #{@version}")
238
+ end
239
+
240
+ # and remove the "response" node
190
241
  hash = Hash[hash[:response]].inject({}){|h,(k,v)| h[k] = v; h}
191
242
  puts "BigBlueButtonAPI: URL response hash = #{hash.inspect}" if @debug
192
243
 
193
244
  return_code = hash[:returncode]
194
245
  unless return_code == "SUCCESS"
195
- raise BigBlueButtonException.new("BigBlueButton error: #{hash[:message]}")
246
+ exception = BigBlueButtonException.new(hash[:message])
247
+ exception.key = hash.has_key?(:messageKey) ? hash[:messageKey] : ""
248
+ raise exception
196
249
  end
197
250
  hash
198
251
  end
data/lib/hash_to_xml.rb CHANGED
@@ -9,7 +9,7 @@ class Hash
9
9
  result = Nokogiri::XML(xml_io)
10
10
  return { result.root.name.to_sym => xml_node_to_hash(result.root)}
11
11
  rescue Exception => e
12
- raise BigBlueButton::BigBlueButtonException.new("BigBlueButton error: Impossible to convert XML to hash. Error: #{e.message}")
12
+ raise BigBlueButton::BigBlueButtonException.new("Impossible to convert XML to hash. Error: #{e.message}")
13
13
  end
14
14
  end
15
15
 
data/test/test.rb CHANGED
@@ -24,6 +24,15 @@ end
24
24
 
25
25
  def general_test
26
26
 
27
+ puts
28
+ puts "---------------------------------------------------"
29
+ if @api.test_connection
30
+ puts "Connection success! continuing..."
31
+ else
32
+ puts "Connection failed! The server might be unreachable. Exiting..."
33
+ Kernel.exit!
34
+ end
35
+
27
36
  puts
28
37
  puts "---------------------------------------------------"
29
38
  response = @api.get_meetings
@@ -45,14 +54,14 @@ def general_test
45
54
  puts "---------------------------------------------------"
46
55
  @api.create_meeting(@config['meeting_name'], @config['meeting_id'], @config['moderator_password'], @config['attendee_password'],
47
56
  'Welcome to my meeting', '1-800-000-0000x00000#', 'https://github.com/mconf/bigbluebutton-api-ruby', 10)
48
- puts "The meeting has been created. Please open a web browser and enter the meeting using either of the below URLs."
57
+ puts "The meeting has been created. Please open a web browser and enter the meeting using either of the URLs below."
49
58
 
50
59
  puts
51
60
  puts "---------------------------------------------------"
52
- url = @api.moderator_url(@config['meeting_id'], @config['moderator_name'], @config['moderator_password'])
61
+ url = @api.join_meeting_url(@config['meeting_id'], @config['moderator_name'], @config['moderator_password'])
53
62
  puts "1) Moderator URL = #{url}"
54
63
  puts ""
55
- url = @api.attendee_url(@config['meeting_id'], @config['attendee_name'], @config['attendee_password'])
64
+ url = @api.join_meeting_url(@config['meeting_id'], @config['attendee_name'], @config['attendee_password'])
56
65
  puts "2) Attendee URL = #{url}"
57
66
 
58
67
  puts
@@ -88,12 +97,12 @@ def join_test
88
97
  @api.create_meeting(@config['meeting_name'], @config['meeting_id'], @config['moderator_password'], @config['attendee_password'],
89
98
  'Welcome to my meeting', '1-800-000-0000x00000#', 'https://github.com/mconf/bigbluebutton-api-ruby', 10)
90
99
  puts "The meeting has been created. Please open a web browser and enter the meeting as moderator."
91
-
100
+
92
101
  puts
93
102
  puts "---------------------------------------------------"
94
- url = @api.moderator_url(@config['meeting_id'], @config['moderator_name'], @config['moderator_password'])
103
+ url = @api.join_meeting_url(@config['meeting_id'], @config['moderator_name'], @config['moderator_password'])
95
104
  puts "1) Moderator URL = #{url}"
96
-
105
+
97
106
  puts
98
107
  puts "---------------------------------------------------"
99
108
  puts "Waiting 30 seconds for you to enter via browser"
@@ -105,7 +114,7 @@ def join_test
105
114
  Kernel.exit!
106
115
  end
107
116
  puts "You have successfully entered the meeting"
108
-
117
+
109
118
  puts
110
119
  puts "---------------------------------------------------"
111
120
  response = @api.get_meeting_info(@config['meeting_id'], @config['moderator_password'])
@@ -119,7 +128,7 @@ def join_test
119
128
  response = @api.join_meeting(@config['meeting_id'], @config['attendee_name'], @config['attendee_password'])
120
129
  puts "Join meeting response:"
121
130
  puts response.inspect
122
-
131
+
123
132
  end
124
133
 
125
134
  begin