jubjub 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.infinity_test +35 -0
- data/.rspec +2 -0
- data/LICENSE +19 -0
- data/README.mdown +78 -0
- data/lib/jubjub/connection/xmpp_gateway/helper.rb +17 -0
- data/lib/jubjub/connection/xmpp_gateway/muc.rb +353 -0
- data/lib/jubjub/connection/xmpp_gateway.rb +47 -0
- data/lib/jubjub/errors.rb +7 -0
- data/lib/jubjub/jid.rb +33 -0
- data/lib/jubjub/muc.rb +143 -0
- data/lib/jubjub/user.rb +60 -0
- data/lib/jubjub.rb +1 -0
- data/spec/connection/xmpp_gateway_spec.rb +136 -0
- data/spec/fixtures/vcr_cassettes/muc_configuration.yml +134 -0
- data/spec/fixtures/vcr_cassettes/muc_create.yml +68 -0
- data/spec/fixtures/vcr_cassettes/muc_create_with_configuration.yml +68 -0
- data/spec/fixtures/vcr_cassettes/muc_destroy.yml +68 -0
- data/spec/fixtures/vcr_cassettes/muc_list.yml +115 -0
- data/spec/mixins/user_spec.rb +137 -0
- data/spec/models/jid_spec.rb +123 -0
- data/spec/models/muc_collection_spec.rb +71 -0
- data/spec/models/muc_configuration_spec.rb +459 -0
- data/spec/models/muc_spec.rb +57 -0
- data/spec/spec_helper.rb +17 -0
- metadata +176 -0
data/.infinity_test
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
infinity_test do
|
2
|
+
|
3
|
+
notifications :growl do
|
4
|
+
show_images :mode => :mario_bros
|
5
|
+
end
|
6
|
+
|
7
|
+
use :rubies => %w(1.9.2 ree), :test_framework => :rspec
|
8
|
+
|
9
|
+
# use :specific_options => {'jruby' => 'J-cp bar/whisky-in-the.jar:.'}
|
10
|
+
|
11
|
+
before(:each_ruby) do |environment|
|
12
|
+
# ...
|
13
|
+
end
|
14
|
+
|
15
|
+
after(:each_ruby) do |environment|
|
16
|
+
# ...
|
17
|
+
end
|
18
|
+
|
19
|
+
before_run do
|
20
|
+
clear :terminal
|
21
|
+
end
|
22
|
+
|
23
|
+
after_run do
|
24
|
+
# ...
|
25
|
+
end
|
26
|
+
|
27
|
+
#heuristics('my_pattern') do |file|
|
28
|
+
# ...
|
29
|
+
#end
|
30
|
+
|
31
|
+
replace_patterns do |application|
|
32
|
+
# ...
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/.rspec
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
Copyright (C) 2010 by Theo Cushion
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to deal
|
5
|
+
in the Software without restriction, including without limitation the rights
|
6
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
THE SOFTWARE.
|
data/README.mdown
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
Description
|
2
|
+
===========
|
3
|
+
|
4
|
+
Jubjub is an object to XMPP mapping library designed to be used inside of a web app to simplify the administration of XMPP resources. It aims to provide a very simple interface which hides the complexity of the XMPP protocol allowing your code to communicate intent rather than implementation details. This also makes the code significantly easier to mock and test.
|
5
|
+
|
6
|
+
Currently it uses [xmpp_gateway](https://github.com/theozaurus/xmpp_gateway) to communicate to the XMPP server. This allows Jubjub to be used within non evented web servers like [Phusion Passenger](http://www.modrails.com).
|
7
|
+
|
8
|
+
It is currently alpha software and merely a proof of concept.
|
9
|
+
|
10
|
+
Requirements
|
11
|
+
============
|
12
|
+
|
13
|
+
It is currently fully tested against:
|
14
|
+
|
15
|
+
- Ruby 1.8.7
|
16
|
+
- Ruby 1.9.2
|
17
|
+
|
18
|
+
Examples
|
19
|
+
========
|
20
|
+
|
21
|
+
require 'jubjub'
|
22
|
+
class User
|
23
|
+
|
24
|
+
attr_accessor :xmpp_jid, :xmpp_password
|
25
|
+
|
26
|
+
# :jid and :password are used to point to methods that contain
|
27
|
+
# the credentials required to login as a user
|
28
|
+
include Jubjub::User
|
29
|
+
jubjub_client :jid => :xmpp_jid, :password => :xmpp_password
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
u = User.new
|
34
|
+
u.xmpp_jid = "theozaurus@jabber.org"
|
35
|
+
u.xmpp_password = "ruby"
|
36
|
+
|
37
|
+
# Sensibly defaults to conference.YOUR_CONNECTION_JID
|
38
|
+
u.mucs
|
39
|
+
=> [
|
40
|
+
#<Jubjub::Muc:0x1027222b8 @jid="all@conference.jabber.org" @name="all">,
|
41
|
+
#<Jubjub::Muc:0x102722038 @jid="all-linux-ru@conference.jabber.org" @name="all-linux-ru">,
|
42
|
+
#<Jubjub::Muc:0x102721b60 @jid="allgorithmus@conference.jabber.org" @name="Allgorithmus Project">,
|
43
|
+
...
|
44
|
+
|
45
|
+
# Fancy a list from a different service?
|
46
|
+
u.mucs('conference.jabber.ru')
|
47
|
+
=> [
|
48
|
+
#<Jubjub::Muc:0x10166e930 @jid="tota-room@conference.jabber.ru" @name="tota-room (5)">,
|
49
|
+
#<Jubjub::Muc:0x10166e6b0 @jid="friends_room@conference.jabber.ru" @name="Friends (6)">,
|
50
|
+
#<Jubjub::Muc:0x10166dcb0 @jid="think_linux@conference.jabber.ru" @name="think_linux (n/a)">
|
51
|
+
...
|
52
|
+
|
53
|
+
# Create a room
|
54
|
+
room = u.mucs.create('jubjub')
|
55
|
+
=> #<Jubjub::Muc:0x101532f58 @jid="jubjub@conference.jabber.org" @name=nil>
|
56
|
+
|
57
|
+
# Create a room somewhere else
|
58
|
+
room = u.mucs('chat.test.com').create('jubjub')
|
59
|
+
=> #<Jubjub::Muc:0x10161c3b0 @jid="jubjub@chat.test.com" @name=nil>
|
60
|
+
|
61
|
+
# Create a room with a custom configuration
|
62
|
+
room = u.mucs.create('customjub'){|c|
|
63
|
+
c['muc#roomconfig_allowinvites'] = false
|
64
|
+
}
|
65
|
+
|
66
|
+
# Destroy a room
|
67
|
+
room.destroy
|
68
|
+
=> true
|
69
|
+
|
70
|
+
TODO
|
71
|
+
====
|
72
|
+
|
73
|
+
- Error handling
|
74
|
+
- MUC user role and affiliation control
|
75
|
+
- Service discovery
|
76
|
+
- Pubsub / PEP
|
77
|
+
- Operations that are not IQ based, such as rosters and two way messaging
|
78
|
+
- Other backends (for servers that are evented)
|
@@ -0,0 +1,353 @@
|
|
1
|
+
require 'jubjub/connection/xmpp_gateway/helper'
|
2
|
+
require 'jubjub/muc'
|
3
|
+
|
4
|
+
module Jubjub
|
5
|
+
module Connection
|
6
|
+
class XmppGateway
|
7
|
+
class Muc
|
8
|
+
|
9
|
+
include Helper
|
10
|
+
|
11
|
+
def initialize(connection)
|
12
|
+
@connection = connection
|
13
|
+
end
|
14
|
+
|
15
|
+
# http://xmpp.org/extensions/xep-0045.html#createroom-instant
|
16
|
+
# <presence
|
17
|
+
# from='crone1@shakespeare.lit/desktop'
|
18
|
+
# to='darkcave@chat.shakespeare.lit/firstwitch'>
|
19
|
+
# <x xmlns='http://jabber.org/protocol/muc'/>
|
20
|
+
# </presence>
|
21
|
+
# <iq from='crone1@shakespeare.lit/desktop'
|
22
|
+
# id='create1'
|
23
|
+
# to='darkcave@chat.shakespeare.lit'
|
24
|
+
# type='set'>
|
25
|
+
# <query xmlns='http://jabber.org/protocol/muc#owner'>
|
26
|
+
# <x xmlns='jabber:x:data' type='submit'/>
|
27
|
+
# </query>
|
28
|
+
# </iq>
|
29
|
+
#
|
30
|
+
# Expected
|
31
|
+
# <iq from='darkcave@chat.shakespeare.lit'
|
32
|
+
# id='create2'
|
33
|
+
# to='crone1@shakespeare.lit/desktop'
|
34
|
+
# type='result'/>
|
35
|
+
#
|
36
|
+
def create(full_jid, configuration = nil)
|
37
|
+
room_jid = Jubjub::Jid.new full_jid.node, full_jid.domain
|
38
|
+
|
39
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
40
|
+
xml.iq(:type => 'set', :to => room_jid) {
|
41
|
+
xml.query('xmlns' => 'http://jabber.org/protocol/muc#owner'){
|
42
|
+
xml.x('xmlns' => 'jabber:x:data', :type => 'submit') {
|
43
|
+
configuration.settings.each{|name,values|
|
44
|
+
xml.field('var' => name){
|
45
|
+
values.each {|v|
|
46
|
+
xml.value v
|
47
|
+
}
|
48
|
+
}
|
49
|
+
} if configuration
|
50
|
+
}
|
51
|
+
}
|
52
|
+
}
|
53
|
+
end
|
54
|
+
|
55
|
+
presence full_jid
|
56
|
+
|
57
|
+
success = write(
|
58
|
+
# Open room
|
59
|
+
request.to_xml
|
60
|
+
).xpath(
|
61
|
+
# Check for valid response
|
62
|
+
'//iq[@type="result"]'
|
63
|
+
).any?
|
64
|
+
Jubjub::Muc.new room_jid, nil, @connection if success
|
65
|
+
end
|
66
|
+
|
67
|
+
# http://xmpp.org/extensions/xep-0045.html#createroom-reserved
|
68
|
+
# <presence
|
69
|
+
# from='crone1@shakespeare.lit/desktop'
|
70
|
+
# to='darkcave@chat.shakespeare.lit/firstwitch'>
|
71
|
+
# <x xmlns='http://jabber.org/protocol/muc'/>
|
72
|
+
# </presence>
|
73
|
+
# <iq from='crone1@shakespeare.lit/desktop'
|
74
|
+
# id='create1'
|
75
|
+
# to='darkcave@chat.shakespeare.lit'
|
76
|
+
# type='get'>
|
77
|
+
# <query xmlns='http://jabber.org/protocol/muc#owner'/>
|
78
|
+
# </iq>
|
79
|
+
#
|
80
|
+
# Expected
|
81
|
+
# <iq from='darkcave@chat.shakespeare.lit'
|
82
|
+
# id='create1'
|
83
|
+
# to='crone1@shakespeare.lit/desktop'
|
84
|
+
# type='result'>
|
85
|
+
# <query xmlns='http://jabber.org/protocol/muc#owner'>
|
86
|
+
# <x xmlns='jabber:x:data' type='form'>
|
87
|
+
# <title>Configuration for "darkcave" Room</title>
|
88
|
+
# <instructions>
|
89
|
+
# Your room darkcave@macbeth has been created!
|
90
|
+
# The default configuration is as follows:
|
91
|
+
# - No logging
|
92
|
+
# - No moderation
|
93
|
+
# - Up to 20 occupants
|
94
|
+
# - No password required
|
95
|
+
# - No invitation required
|
96
|
+
# - Room is not persistent
|
97
|
+
# - Only admins may change the subject
|
98
|
+
# - Presence broadcasted for all users
|
99
|
+
# To accept the default configuration, click OK. To
|
100
|
+
# select a different configuration, please complete
|
101
|
+
# this form.
|
102
|
+
# </instructions>
|
103
|
+
# <field
|
104
|
+
# type='hidden'
|
105
|
+
# var='FORM_TYPE'>
|
106
|
+
# <value>http://jabber.org/protocol/muc#roomconfig</value>
|
107
|
+
# </field>
|
108
|
+
# <field
|
109
|
+
# label='Natural-Language Room Name'
|
110
|
+
# type='text-single'
|
111
|
+
# var='muc#roomconfig_roomname'/>
|
112
|
+
# <field
|
113
|
+
# label='Natural Language for Room Discussions'
|
114
|
+
# type='text-single'
|
115
|
+
# var='muc#roomconfig_lang'/>
|
116
|
+
# <field
|
117
|
+
# label='Enable Public Logging?'
|
118
|
+
# type='boolean'
|
119
|
+
# var='muc#roomconfig_enablelogging'>
|
120
|
+
# <value>0</value>
|
121
|
+
# </field>
|
122
|
+
# <field
|
123
|
+
# label='Maximum Number of Occupants'
|
124
|
+
# type='list-single'
|
125
|
+
# var='muc#roomconfig_maxusers'>
|
126
|
+
# <value>20</value>
|
127
|
+
# <option label='10'><value>10</value></option>
|
128
|
+
# <option label='20'><value>20</value></option>
|
129
|
+
# <option label='30'><value>30</value></option>
|
130
|
+
# <option label='50'><value>50</value></option>
|
131
|
+
# <option label='100'><value>100</value></option>
|
132
|
+
# <option label='None'><value>none</value></option>
|
133
|
+
# </field>
|
134
|
+
# <field
|
135
|
+
# label='Roles for which Presence is Broadcast'
|
136
|
+
# type='list-multi'
|
137
|
+
# var='muc#roomconfig_presencebroadcast'>
|
138
|
+
# <value>moderator</value>
|
139
|
+
# <value>participant</value>
|
140
|
+
# <value>visitor</value>
|
141
|
+
# <option label='Moderator'><value>moderator</value></option>
|
142
|
+
# <option label='Participant'><value>participant</value></option>
|
143
|
+
# <option label='Visitor'><value>visitor</value></option>
|
144
|
+
# </field>
|
145
|
+
# <field
|
146
|
+
# label='Roles and Affiliations that May Retrieve Member List'
|
147
|
+
# type='list-multi'
|
148
|
+
# var='muc#roomconfig_getmemberlist'>
|
149
|
+
# <value>moderator</value>
|
150
|
+
# <value>participant</value>
|
151
|
+
# <value>visitor</value>
|
152
|
+
# <option label='Moderator'><value>moderator</value></option>
|
153
|
+
# <option label='Participant'><value>participant</value></option>
|
154
|
+
# <option label='Visitor'><value>visitor</value></option>
|
155
|
+
# </field>
|
156
|
+
# <field
|
157
|
+
# label='Make Room Publicly Searchable?'
|
158
|
+
# type='boolean'
|
159
|
+
# var='muc#roomconfig_publicroom'>
|
160
|
+
# <value>1</value>
|
161
|
+
# </field>
|
162
|
+
# <field
|
163
|
+
# label='Make Room Persistent?'
|
164
|
+
# type='boolean'
|
165
|
+
# var='muc#roomconfig_persistentroom'>
|
166
|
+
# <value>0</value>
|
167
|
+
# </field>
|
168
|
+
# <field type='fixed'>
|
169
|
+
# <value>
|
170
|
+
# If a password is required to enter this room,
|
171
|
+
# you must specify the password below.
|
172
|
+
# </value>
|
173
|
+
# </field>
|
174
|
+
# <field
|
175
|
+
# label='Password'
|
176
|
+
# type='text-private'
|
177
|
+
# var='muc#roomconfig_roomsecret'/>
|
178
|
+
# <field
|
179
|
+
# label='Who May Discover Real JIDs?'
|
180
|
+
# type='list-single'
|
181
|
+
# var='muc#roomconfig_whois'>
|
182
|
+
# <option label='Moderators Only'>
|
183
|
+
# <value>moderators</value>
|
184
|
+
# </option>
|
185
|
+
# <option label='Anyone'>
|
186
|
+
# <value>anyone</value>
|
187
|
+
# </option>
|
188
|
+
# </field>
|
189
|
+
# <field type='fixed'>
|
190
|
+
# <value>
|
191
|
+
# You may specify additional people who have
|
192
|
+
# administrative privileges in the room. Please
|
193
|
+
# provide one Jabber ID per line.
|
194
|
+
# </value>
|
195
|
+
# </field>
|
196
|
+
# <field
|
197
|
+
# label='Room Admins'
|
198
|
+
# type='jid-multi'
|
199
|
+
# var='muc#roomconfig_roomadmins'/>
|
200
|
+
# <field type='fixed'>
|
201
|
+
# <value>
|
202
|
+
# You may specify additional owners for this
|
203
|
+
# room. Please provide one Jabber ID per line.
|
204
|
+
# </value>
|
205
|
+
# </field>
|
206
|
+
# <field
|
207
|
+
# label='Room Owners'
|
208
|
+
# type='jid-multi'
|
209
|
+
# var='muc#roomconfig_roomowners'/>
|
210
|
+
# </x>
|
211
|
+
# </query>
|
212
|
+
# </iq>
|
213
|
+
def configuration(full_jid)
|
214
|
+
room_jid = Jubjub::Jid.new full_jid.node, full_jid.domain
|
215
|
+
|
216
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
217
|
+
xml.iq(:to => room_jid, :type => 'get') {
|
218
|
+
xml.query('xmlns' => 'http://jabber.org/protocol/muc#owner')
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
presence full_jid
|
223
|
+
response = write(
|
224
|
+
# Request room configuration
|
225
|
+
request.to_xml
|
226
|
+
).xpath(
|
227
|
+
# Get fields
|
228
|
+
"//iq[@type='result']/muc_owner:query/x_data:x[@type='form']/x_data:field",
|
229
|
+
namespaces
|
230
|
+
).inject({}){|result,field|
|
231
|
+
# Build MucConfiguration parameters
|
232
|
+
hash = {}
|
233
|
+
hash[:type] = field.attr 'type'
|
234
|
+
hash[:label] = field.attr 'label'
|
235
|
+
|
236
|
+
value = field.xpath('x_data:value', namespaces)
|
237
|
+
hash[:value] = hash[:type].match(/\-multi$/) ? value.map{|e| e.content } : value.text
|
238
|
+
|
239
|
+
options = field.xpath('x_data:option', namespaces).map{|o|
|
240
|
+
{ :label => o.attr('label'), :value => o.xpath('x_data:value', namespaces).text }
|
241
|
+
}
|
242
|
+
hash[:options] = options if options.any?
|
243
|
+
|
244
|
+
result[field.attr 'var'] = hash
|
245
|
+
result
|
246
|
+
}
|
247
|
+
|
248
|
+
Jubjub::MucConfiguration.new response
|
249
|
+
end
|
250
|
+
|
251
|
+
# http://xmpp.org/extensions/xep-0045.html#destroyroom
|
252
|
+
# <iq from='crone1@shakespeare.lit/desktop'
|
253
|
+
# id='begone'
|
254
|
+
# to='heath@chat.shakespeare.lit'
|
255
|
+
# type='set'>
|
256
|
+
# <query xmlns='http://jabber.org/protocol/muc#owner'>
|
257
|
+
# <destroy jid='darkcave@chat.shakespeare.lit'>
|
258
|
+
# <reason>Macbeth doth come.</reason>
|
259
|
+
# </destroy>
|
260
|
+
# </query>
|
261
|
+
# </iq>
|
262
|
+
#
|
263
|
+
# Expected
|
264
|
+
# <iq from='heath@chat.shakespeare.lit'
|
265
|
+
# id='begone'
|
266
|
+
# to='crone1@shakespeare.lit/desktop'
|
267
|
+
# type='result'/>
|
268
|
+
def destroy(jid)
|
269
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
270
|
+
xml.iq(:to => jid, :type => 'set') {
|
271
|
+
xml.query('xmlns' => 'http://jabber.org/protocol/muc#owner'){
|
272
|
+
xml.destroy
|
273
|
+
}
|
274
|
+
}
|
275
|
+
end
|
276
|
+
|
277
|
+
write(
|
278
|
+
# Generate stanza
|
279
|
+
request.to_xml
|
280
|
+
).xpath(
|
281
|
+
# Check for valid response
|
282
|
+
'//iq[@type="result"]'
|
283
|
+
).any?
|
284
|
+
end
|
285
|
+
|
286
|
+
# http://xmpp.org/extensions/xep-0045.html#disco-rooms
|
287
|
+
# <iq from='hag66@shakespeare.lit/pda'
|
288
|
+
# id='disco2'
|
289
|
+
# to='chat.shakespeare.lit'
|
290
|
+
# type='get'>
|
291
|
+
# <query xmlns='http://jabber.org/protocol/disco#items'/>
|
292
|
+
# </iq>
|
293
|
+
#
|
294
|
+
# Expected
|
295
|
+
# <iq from='chat.shakespeare.lit'
|
296
|
+
# id='disco2'
|
297
|
+
# to='hag66@shakespeare.lit/pda'
|
298
|
+
# type='result'>
|
299
|
+
# <query xmlns='http://jabber.org/protocol/disco#items'>
|
300
|
+
# <item jid='heath@chat.shakespeare.lit'
|
301
|
+
# name='A Lonely Heath'/>
|
302
|
+
# <item jid='darkcave@chat.shakespeare.lit'
|
303
|
+
# name='A Dark Cave'/>
|
304
|
+
# <item jid='forres@chat.shakespeare.lit'
|
305
|
+
# name='The Palace'/>
|
306
|
+
# <item jid='inverness@chat.shakespeare.lit'
|
307
|
+
# name='Macbeth's Castle'/>
|
308
|
+
# </query>
|
309
|
+
# </iq>
|
310
|
+
def list(jid)
|
311
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
312
|
+
xml.iq(:to => jid, :type => 'get') {
|
313
|
+
xml.query('xmlns' => 'http://jabber.org/protocol/disco#items')
|
314
|
+
}
|
315
|
+
end
|
316
|
+
|
317
|
+
write(
|
318
|
+
# Generate stanza
|
319
|
+
request.to_xml
|
320
|
+
).xpath(
|
321
|
+
# Pull out required parts
|
322
|
+
'//iq[@type="result"]/disco_items:query/disco_items:item',
|
323
|
+
namespaces
|
324
|
+
).map{|item|
|
325
|
+
# Convert to Jubjub object
|
326
|
+
Jubjub::Muc.new item.attr('jid'), item.attr('name'), @connection
|
327
|
+
}
|
328
|
+
end
|
329
|
+
|
330
|
+
private
|
331
|
+
|
332
|
+
def presence(full_jid)
|
333
|
+
request = Nokogiri::XML::Builder.new do |xml|
|
334
|
+
xml.presence(:to => full_jid) {
|
335
|
+
xml.x('xmlns' => 'http://jabber.org/protocol/muc')
|
336
|
+
}
|
337
|
+
end
|
338
|
+
|
339
|
+
write request.to_xml
|
340
|
+
end
|
341
|
+
|
342
|
+
def namespaces
|
343
|
+
{
|
344
|
+
'disco_items' => 'http://jabber.org/protocol/disco#items',
|
345
|
+
'muc_owner' => "http://jabber.org/protocol/muc#owner",
|
346
|
+
'x_data' => 'jabber:x:data'
|
347
|
+
}
|
348
|
+
end
|
349
|
+
|
350
|
+
end
|
351
|
+
end
|
352
|
+
end
|
353
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require "net/http"
|
2
|
+
require "nokogiri"
|
3
|
+
require "jubjub/connection/xmpp_gateway/muc"
|
4
|
+
|
5
|
+
module Jubjub
|
6
|
+
module Connection
|
7
|
+
class XmppGateway
|
8
|
+
|
9
|
+
attr_reader :jid
|
10
|
+
|
11
|
+
def initialize(jid,password,settings)
|
12
|
+
@jid = jid
|
13
|
+
@password = password
|
14
|
+
@settings = settings
|
15
|
+
end
|
16
|
+
|
17
|
+
def muc
|
18
|
+
@muc ||= Muc.new(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def write(stanza)
|
22
|
+
req = Net::HTTP::Post.new( url.path )
|
23
|
+
req.basic_auth( @jid.to_s, @password )
|
24
|
+
req.set_form_data( { 'stanza'=> stanza }, ';' )
|
25
|
+
res = Net::HTTP.new(url.host, url.port).start {|http| http.request req }
|
26
|
+
case res
|
27
|
+
when Net::HTTPSuccess
|
28
|
+
# OK
|
29
|
+
else
|
30
|
+
#res.error!
|
31
|
+
end
|
32
|
+
decode res.body
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def url
|
38
|
+
URI.parse "http://#{@settings[:host]}:#{@settings[:port]}/"
|
39
|
+
end
|
40
|
+
|
41
|
+
def decode(http_body)
|
42
|
+
Nokogiri::XML::Document.parse http_body
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
data/lib/jubjub/jid.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
module Jubjub
|
2
|
+
class Jid
|
3
|
+
|
4
|
+
PATTERN = /^(?:([^@]*)@)??([^@\/]*)(?:\/(.*?))?$/
|
5
|
+
|
6
|
+
attr_reader :node, :domain, :resource
|
7
|
+
|
8
|
+
def initialize(node, domain = nil, resource = nil)
|
9
|
+
if node.is_a? Jid
|
10
|
+
@node = node.node
|
11
|
+
@domain = node.domain
|
12
|
+
@resource = node.resource
|
13
|
+
else
|
14
|
+
@node = node
|
15
|
+
@domain = domain
|
16
|
+
@resource = resource
|
17
|
+
end
|
18
|
+
|
19
|
+
if @domain.nil? && @resource.nil?
|
20
|
+
@node, @domain, @resource = node.to_s.scan(PATTERN).first
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_s
|
25
|
+
(node ? "#{node}@" : '') + domain + (resource ? "/#{resource}" : '')
|
26
|
+
end
|
27
|
+
|
28
|
+
def ==(obj)
|
29
|
+
obj.is_a?( self.class ) && obj.to_s == self.to_s
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
33
|
+
end
|