bigbluebutton-api-ruby 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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