bigbluebutton-api-ruby 0.0.4

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.
@@ -0,0 +1,41 @@
1
+
2
+ <?xml version="1.0" encoding="iso-8859-1"?>
3
+ <!DOCTYPE html
4
+ PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
5
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
6
+
7
+ <!--
8
+
9
+ Methods
10
+
11
+ -->
12
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
13
+ <head>
14
+ <title>Methods</title>
15
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
16
+ <link rel="stylesheet" href="rdoc-style.css" type="text/css" />
17
+ <base target="docwin" />
18
+ </head>
19
+ <body>
20
+ <div id="index">
21
+ <h1 class="section-bar">Methods</h1>
22
+ <div id="index-entries">
23
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000007">attendee_url (BigBlueButton::BigBlueButtonApi)</a><br />
24
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000008">create_meeting (BigBlueButton::BigBlueButtonApi)</a><br />
25
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000009">end_meeting (BigBlueButton::BigBlueButtonApi)</a><br />
26
+ <a href="classes/Hash.html#M000001">from_xml (Hash)</a><br />
27
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000012">get_meeting_info (BigBlueButton::BigBlueButtonApi)</a><br />
28
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000013">get_meetings (BigBlueButton::BigBlueButtonApi)</a><br />
29
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000014">get_url (BigBlueButton::BigBlueButtonApi)</a><br />
30
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000010">is_meeting_running? (BigBlueButton::BigBlueButtonApi)</a><br />
31
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000011">join_meeting (BigBlueButton::BigBlueButtonApi)</a><br />
32
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000006">moderator_url (BigBlueButton::BigBlueButtonApi)</a><br />
33
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000005">new (BigBlueButton::BigBlueButtonApi)</a><br />
34
+ <a href="classes/Hash.html#M000003">prepare (Hash)</a><br />
35
+ <a href="classes/BigBlueButton/BigBlueButtonApi.html#M000015">send_api_request (BigBlueButton::BigBlueButtonApi)</a><br />
36
+ <a href="classes/Hash.html#M000004">to_struct (Hash)</a><br />
37
+ <a href="classes/Hash.html#M000002">xml_node_to_hash (Hash)</a><br />
38
+ </div>
39
+ </div>
40
+ </body>
41
+ </html>
data/doc/index.html ADDED
@@ -0,0 +1,24 @@
1
+ <?xml version="1.0" encoding="iso-8859-1"?>
2
+ <!DOCTYPE html
3
+ PUBLIC "-//W3C//DTD XHTML 1.0 Frameset//EN"
4
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-frameset.dtd">
5
+
6
+ <!--
7
+
8
+ bigbluebutton-api-ruby Docs
9
+
10
+ -->
11
+ <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
12
+ <head>
13
+ <title>bigbluebutton-api-ruby Docs</title>
14
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
15
+ </head>
16
+ <frameset rows="20%, 80%">
17
+ <frameset cols="25%,35%,45%">
18
+ <frame src="fr_file_index.html" title="Files" name="Files" />
19
+ <frame src="fr_class_index.html" name="Classes" />
20
+ <frame src="fr_method_index.html" name="Methods" />
21
+ </frameset>
22
+ <frame src="files/README.html" name="docwin" />
23
+ </frameset>
24
+ </html>
@@ -0,0 +1,208 @@
1
+
2
+ body {
3
+ font-family: Verdana,Arial,Helvetica,sans-serif;
4
+ font-size: 90%;
5
+ margin: 0;
6
+ margin-left: 40px;
7
+ padding: 0;
8
+ background: white;
9
+ }
10
+
11
+ h1,h2,h3,h4 { margin: 0; color: #efefef; background: transparent; }
12
+ h1 { font-size: 150%; }
13
+ h2,h3,h4 { margin-top: 1em; }
14
+
15
+ a { background: #eef; color: #039; text-decoration: none; }
16
+ a:hover { background: #039; color: #eef; }
17
+
18
+ /* Override the base stylesheet's Anchor inside a table cell */
19
+ td > a {
20
+ background: transparent;
21
+ color: #039;
22
+ text-decoration: none;
23
+ }
24
+
25
+ /* and inside a section title */
26
+ .section-title > a {
27
+ background: transparent;
28
+ color: #eee;
29
+ text-decoration: none;
30
+ }
31
+
32
+ /* === Structural elements =================================== */
33
+
34
+ div#index {
35
+ margin: 0;
36
+ margin-left: -40px;
37
+ padding: 0;
38
+ font-size: 90%;
39
+ }
40
+
41
+
42
+ div#index a {
43
+ margin-left: 0.7em;
44
+ }
45
+
46
+ div#index .section-bar {
47
+ margin-left: 0px;
48
+ padding-left: 0.7em;
49
+ background: #ccc;
50
+ font-size: small;
51
+ }
52
+
53
+
54
+ div#classHeader, div#fileHeader {
55
+ width: auto;
56
+ color: white;
57
+ padding: 0.5em 1.5em 0.5em 1.5em;
58
+ margin: 0;
59
+ margin-left: -40px;
60
+ border-bottom: 3px solid #006;
61
+ }
62
+
63
+ div#classHeader a, div#fileHeader a {
64
+ background: inherit;
65
+ color: white;
66
+ }
67
+
68
+ div#classHeader td, div#fileHeader td {
69
+ background: inherit;
70
+ color: white;
71
+ }
72
+
73
+
74
+ div#fileHeader {
75
+ background: #057;
76
+ }
77
+
78
+ div#classHeader {
79
+ background: #048;
80
+ }
81
+
82
+
83
+ .class-name-in-header {
84
+ font-size: 180%;
85
+ font-weight: bold;
86
+ }
87
+
88
+
89
+ div#bodyContent {
90
+ padding: 0 1.5em 0 1.5em;
91
+ }
92
+
93
+ div#description {
94
+ padding: 0.5em 1.5em;
95
+ background: #efefef;
96
+ border: 1px dotted #999;
97
+ }
98
+
99
+ div#description h1,h2,h3,h4,h5,h6 {
100
+ color: #125;;
101
+ background: transparent;
102
+ }
103
+
104
+ div#validator-badges {
105
+ text-align: center;
106
+ }
107
+ div#validator-badges img { border: 0; }
108
+
109
+ div#copyright {
110
+ color: #333;
111
+ background: #efefef;
112
+ font: 0.75em sans-serif;
113
+ margin-top: 5em;
114
+ margin-bottom: 0;
115
+ padding: 0.5em 2em;
116
+ }
117
+
118
+
119
+ /* === Classes =================================== */
120
+
121
+ table.header-table {
122
+ color: white;
123
+ font-size: small;
124
+ }
125
+
126
+ .type-note {
127
+ font-size: small;
128
+ color: #DEDEDE;
129
+ }
130
+
131
+ .xxsection-bar {
132
+ background: #eee;
133
+ color: #333;
134
+ padding: 3px;
135
+ }
136
+
137
+ .section-bar {
138
+ color: #333;
139
+ border-bottom: 1px solid #999;
140
+ margin-left: -20px;
141
+ }
142
+
143
+
144
+ .section-title {
145
+ background: #79a;
146
+ color: #eee;
147
+ padding: 3px;
148
+ margin-top: 2em;
149
+ margin-left: -30px;
150
+ border: 1px solid #999;
151
+ }
152
+
153
+ .top-aligned-row { vertical-align: top }
154
+ .bottom-aligned-row { vertical-align: bottom }
155
+
156
+ /* --- Context section classes ----------------------- */
157
+
158
+ .context-row { }
159
+ .context-item-name { font-family: monospace; font-weight: bold; color: black; }
160
+ .context-item-value { font-size: small; color: #448; }
161
+ .context-item-desc { color: #333; padding-left: 2em; }
162
+
163
+ /* --- Method classes -------------------------- */
164
+ .method-detail {
165
+ background: #efefef;
166
+ padding: 0;
167
+ margin-top: 0.5em;
168
+ margin-bottom: 1em;
169
+ border: 1px dotted #ccc;
170
+ }
171
+ .method-heading {
172
+ color: black;
173
+ background: #ccc;
174
+ border-bottom: 1px solid #666;
175
+ padding: 0.2em 0.5em 0 0.5em;
176
+ }
177
+ .method-signature { color: black; background: inherit; }
178
+ .method-name { font-weight: bold; }
179
+ .method-args { font-style: italic; }
180
+ .method-description { padding: 0 0.5em 0 0.5em; }
181
+
182
+ /* --- Source code sections -------------------- */
183
+
184
+ a.source-toggle { font-size: 90%; }
185
+ div.method-source-code {
186
+ background: #262626;
187
+ color: #ffdead;
188
+ margin: 1em;
189
+ padding: 0.5em;
190
+ border: 1px dashed #999;
191
+ overflow: hidden;
192
+ }
193
+
194
+ div.method-source-code pre { color: #ffdead; overflow: hidden; }
195
+
196
+ /* --- Ruby keyword styles --------------------- */
197
+
198
+ .standalone-code { background: #221111; color: #ffdead; overflow: hidden; }
199
+
200
+ .ruby-constant { color: #7fffd4; background: transparent; }
201
+ .ruby-keyword { color: #00ffff; background: transparent; }
202
+ .ruby-ivar { color: #eedd82; background: transparent; }
203
+ .ruby-operator { color: #00ffee; background: transparent; }
204
+ .ruby-identifier { color: #ffdead; background: transparent; }
205
+ .ruby-node { color: #ffa07a; background: transparent; }
206
+ .ruby-comment { color: #b22222; font-weight: bold; background: transparent; }
207
+ .ruby-regexp { color: #ffa07a; background: transparent; }
208
+ .ruby-value { color: #7fffd4; background: transparent; }
@@ -0,0 +1,203 @@
1
+ require 'net/http'
2
+ require 'cgi'
3
+ require 'rexml/document'
4
+ require 'digest/sha1'
5
+ require 'rubygems'
6
+ require 'nokogiri'
7
+ require 'hash_to_xml'
8
+
9
+ module BigBlueButton
10
+
11
+ class BigBlueButtonException < Exception
12
+
13
+ end
14
+
15
+ # This class provides access to the BigBlueButton API. BigBlueButton
16
+ # is an open source project that provides web conferencing for distance
17
+ # 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
+ #
20
+ # Sample usage of the API is as follows:
21
+ # 1) Create a meeting with the create_meeting call
22
+ # 2) Direct a user to either moderator_url or attendee_url
23
+ # 3) To force meeting to end, call end_meeting
24
+ #
25
+ # 0.0.4+:
26
+ # Author:: Leonardo Crauss Daronco (mailto:leonardodaronco@gmail.com)
27
+ # Copyright:: Copyright (c) 2011 Leonardo Crauss Daronco
28
+ # License:: Distributes under same terms as Ruby
29
+ #
30
+ # 0.0.3 and below:
31
+ # Author:: Joe Kinsella (mailto:joe.kinsella@gmail.com)
32
+ # Copyright:: Copyright (c) 2010 Joe Kinsella
33
+ # License:: Distributes under same terms as Ruby
34
+ #
35
+ # TODO: api version returned on index - added in 0.7
36
+ #
37
+ class BigBlueButtonApi
38
+
39
+ # Initializes an instance
40
+ # base_url:: URL to a BigBlueButton server (e.g. http://demo.bigbluebutton.org/bigbluebutton/api)
41
+ # salt:: Secret salt for this server
42
+ # version:: API version: 0.64 or 0.7
43
+ def initialize(base_url, salt, version='0.7', debug=false)
44
+ @supported_versions = ['0.7', '0.64']
45
+ unless @supported_versions.include?(version)
46
+ raise BigBlueButtonException.new("BigBlueButton error: Invalid API version #{version}. Supported versions: #{@supported_versions.join(', ')}")
47
+ end
48
+ @session = {}
49
+ @base_url = base_url
50
+ @salt = salt
51
+ @debug = debug
52
+ @version = version
53
+ puts "BigBlueButtonAPI: Using version #{@version}" if @debug
54
+ end
55
+
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)
62
+ end
63
+
64
+ # Returns url to login as attendee
65
+ # meeting_id:: Unique identifier for the meeting
66
+ # 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)
72
+
73
+ params = { :meetingID => meeting_id, :password => attendee_password, :fullName => user_name }
74
+ if @version == '0.7'
75
+ params[:userID] = user_id
76
+ params[:webVoiceConf] = web_voice_conf
77
+ end
78
+ get_url(:join, params)
79
+ end
80
+
81
+ # Creates a new meeting. Returns the hash with the response or
82
+ # throws BigBlueButtonException on failure.
83
+ # meeting_name:: Name for the meeting
84
+ # meeting_id:: Unique identifier for the meeting
85
+ # moderator_password:: Moderator password
86
+ # attendee_password:: Attendee password
87
+ # welcome_message:: Welcome message to display in chat window
88
+ # dialin_number:: Dial in number for conference using a regular phone
89
+ # logout_url:: URL to return user to after exiting meeting
90
+ # voice_bridge:: Voice conference number (>=0.7)
91
+ # TODO check if voice_bridge exists in 0.64
92
+ def create_meeting(meeting_name, meeting_id, moderator_password, attendee_password,
93
+ welcome_message = nil, dial_number = nil, logout_url = nil,
94
+ max_participants = nil, voice_bridge = nil)
95
+
96
+ params = { :name => meeting_name, :meetingID => meeting_id,
97
+ :moderatorPW => moderator_password, :attendeePW => attendee_password,
98
+ :welcome => welcome_message, :dialNumber => dial_number,
99
+ :logoutURL => logout_url, :maxParticpants => max_participants }
100
+ params[:voiceBridge] = voice_bridge if @version == '0.7'
101
+ send_api_request(:create, params)
102
+ end
103
+
104
+ # Ends an existing meeting. Throws BigBlueButtonException on failure.
105
+ # meeting_id:: Unique identifier for the meeting
106
+ # moderator_password:: Moderator password
107
+ def end_meeting(meeting_id, moderator_password)
108
+ send_api_request(:end, { :meetingID => meeting_id, :password => moderator_password } )
109
+ end
110
+
111
+ # Returns true or false as to whether meeting is open. A meeting is
112
+ # only open after at least one participant has joined.
113
+ # meeting_id:: Unique identifier for the meeting
114
+ def is_meeting_running?(meeting_id)
115
+ hash = send_api_request(:isMeetingRunning, { :meetingID => meeting_id } )
116
+ hash[:running] == "true"
117
+ end
118
+
119
+ # Warning: As of this version of the gem, this call does not work
120
+ # (instead of returning XML response, it should join the meeting).
121
+ #
122
+ # Joins a user into the meeting using an API call, instead of
123
+ # directing the user's browser to moderator_url or attendee_url
124
+ # (note: this will still be required however to actually use bbb).
125
+ # Returns the URL a user can use to enter this meeting.
126
+ # meeting_id:: Unique identifier for the meeting
127
+ # user_name:: Name of the user
128
+ # password:: Moderator or attendee password for this meeting
129
+ # user_id:: Unique identifier for this user (>=0.7)
130
+ # web_voice_conf:: Custom voice-extension for users using VoIP (>=0.7)
131
+ def join_meeting(meeting_id, user_name, password, user_id = nil, web_voice_conf = nil)
132
+ params = { :meetingID => meeting_id, :password => password, :fullName => user_name }
133
+ if @version == '0.64'
134
+ params[:redirectImmediately] = 0
135
+ elsif @version == '0.7'
136
+ params[:userID] = user_id
137
+ params[:webVoiceConf] = web_voice_conf
138
+ end
139
+ send_api_request(:join, params)
140
+ end
141
+
142
+ # Returns a hash object containing the meeting information.
143
+ # See the API documentation for details on the return XML
144
+ # (http://code.google.com/p/bigbluebutton/wiki/API).
145
+ #
146
+ # meeting_id:: Unique identifier for the meeting
147
+ # password:: Moderator password for this meeting
148
+ def get_meeting_info(meeting_id, password)
149
+ send_api_request(:getMeetingInfo, { :meetingID => meeting_id, :password => password } )
150
+ end
151
+
152
+ # Returns a hash object containing the meeting information.
153
+ # See the API documentation for details on the return XML
154
+ # (http://code.google.com/p/bigbluebutton/wiki/API).
155
+ # >= 0.7
156
+ #
157
+ # TODO check if getMeetings exists in 0.64
158
+ def get_meetings
159
+ if @version == '0.7'
160
+ send_api_request(:getMeetings, { :random => rand(9999999999) } )
161
+ else
162
+ {}
163
+ end
164
+ end
165
+
166
+ protected
167
+
168
+ def get_url(method, data)
169
+ base_url = "#{@base_url}/#{method}?"
170
+ params = ""
171
+ params = data.map{ |k,v| "#{k}=" + CGI::escape(v.to_s) unless k.nil? || v.nil? }.join("&")
172
+ checksum_param = params + @salt
173
+ checksum_param = method.to_s + checksum_param if @version == '0.7'
174
+ checksum = Digest::SHA1.hexdigest(checksum_param)
175
+ "#{base_url}#{params}&checksum=#{checksum}"
176
+ end
177
+
178
+ def send_api_request(method, data = {})
179
+ 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
183
+
184
+ if res.body.empty?
185
+ raise BigBlueButtonException.new("BigBlueButton error: No XML in the response body")
186
+ end
187
+
188
+ # 'Hashfy' the XML and remove the "response" node
189
+ hash = Hash.from_xml res.body
190
+ hash = Hash[hash[:response]].inject({}){|h,(k,v)| h[k] = v; h}
191
+ puts "BigBlueButtonAPI: URL response hash = #{hash.inspect}" if @debug
192
+
193
+ return_code = hash[:returncode]
194
+ unless return_code == "SUCCESS"
195
+ raise BigBlueButtonException.new("BigBlueButton error: #{hash[:message]}")
196
+ end
197
+ hash
198
+ end
199
+
200
+ end
201
+ end
202
+
203
+