jubjub 0.0.3 → 0.0.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -72,6 +72,47 @@ Examples
72
72
  c['muc#roomconfig_persistentroom'] = true
73
73
  }.exit
74
74
 
75
+ # List pubsub nodes
76
+ u.pubsub
77
+ => [
78
+ #<Jubjub::Pubsub:0x101f23c88 @service="pubsub.jabber.org" @node="facts">,
79
+ #<Jubjub::Pubsub:0x101f23a30 @service="pubsub.jabber.org" @node="news">
80
+ ]
81
+
82
+ # List from a different service?
83
+ u.pubsub('pubsub.jabber.ru')
84
+ => [
85
+ ...
86
+ ]
87
+
88
+ # Create a pubsub node
89
+ node = u.pubsub.create('node_1')
90
+ => #<Jubjub::Pubsub:0x101f3bae0 @service="pubsub.jabber.org" @node="node_1">
91
+
92
+ # Subscribe to node
93
+ subscription = node.subscribe
94
+ => #<Jubjub::PubsubSubscription:0x101effd60 @service="pubsub.jabber.org" @node="node_1" @subscriber="theozaurus@jabber.org" @subid="5129CD7935528" @subscription="subscribed">
95
+
96
+ # Subscribe to something else
97
+ u.pubsub.subscribe('new_thing')
98
+ => #<Jubjub::PubsubSubscription:0x101effd60 @service="pubsub.jabber.org" @node="new_thing" @subscriber="theozaurus@jabber.org" @subid="5129CD7935528" @subscription="subscribed">
99
+
100
+ # Unsubscribe
101
+ subscription.unsubscribe
102
+ => true
103
+
104
+ # Destroy a node directly
105
+ node.destroy
106
+ => true
107
+
108
+ # Destroy another node
109
+ u.pubsub.destroy('spare_node')
110
+ => true
111
+
112
+ # Destroy another node with redirect
113
+ u.pubsub.destroy('old_node', 'pubsub.jabber.ru', 'new_new')
114
+ => true
115
+
75
116
  TODO
76
117
  ====
77
118
 
@@ -1,6 +1,7 @@
1
1
  require "net/http"
2
2
  require "nokogiri"
3
3
  require "jubjub/connection/xmpp_gateway/muc"
4
+ require "jubjub/connection/xmpp_gateway/pubsub"
4
5
 
5
6
  module Jubjub
6
7
  module Connection
@@ -18,6 +19,10 @@ module Jubjub
18
19
  @muc ||= Muc.new(self)
19
20
  end
20
21
 
22
+ def pubsub
23
+ @pubsub ||= Pubsub.new(self)
24
+ end
25
+
21
26
  def write(stanza)
22
27
  req = Net::HTTP::Post.new( url.path )
23
28
  req.basic_auth( @jid.to_s, @password )
@@ -0,0 +1,242 @@
1
+ require 'jubjub/connection/xmpp_gateway/helper'
2
+ require 'jubjub/pubsub'
3
+
4
+ module Jubjub
5
+ module Connection
6
+ class XmppGateway
7
+ class Pubsub
8
+
9
+ include Helper
10
+
11
+ def initialize(connection)
12
+ @connection = connection
13
+ end
14
+
15
+ # http://xmpp.org/extensions/xep-0060.html#entity-nodes
16
+ # <iq type='get'
17
+ # from='francisco@denmark.lit/barracks'
18
+ # to='pubsub.shakespeare.lit'
19
+ # id='nodes1'>
20
+ # <query xmlns='http://jabber.org/protocol/disco#items'/>
21
+ # </iq>
22
+ #
23
+ # Expected
24
+ # <iq type='result'
25
+ # from='pubsub.shakespeare.lit'
26
+ # to='francisco@denmark.lit/barracks'
27
+ # id='nodes1'>
28
+ # <query xmlns='http://jabber.org/protocol/disco#items'>
29
+ # <item jid='pubsub.shakespeare.lit'
30
+ # node='blogs'
31
+ # name='Weblog updates'/>
32
+ # <item jid='pubsub.shakespeare.lit'
33
+ # node='news'
34
+ # name='News and announcements'/>
35
+ # </query>
36
+ # </iq>
37
+ def list(jid)
38
+ request = Nokogiri::XML::Builder.new do |xml|
39
+ xml.iq_(:to => jid, :type => 'get') {
40
+ xml.query_('xmlns' => namespaces['disco_items'])
41
+ }
42
+ end
43
+
44
+ write(
45
+ # Generate stanza
46
+ request.to_xml
47
+ ).xpath(
48
+ # Pull out required parts
49
+ '//iq[@type="result"]/disco_items:query/disco_items:item',
50
+ namespaces
51
+ ).map{|item|
52
+ jid = item.attr('jid')
53
+ node = item.attr('node')
54
+ Jubjub::Pubsub.new jid, node, @connection
55
+ }
56
+ end
57
+
58
+ # http://xmpp.org/extensions/xep-0060.html#owner-create
59
+ # <iq type='set'
60
+ # from='hamlet@denmark.lit/elsinore'
61
+ # to='pubsub.shakespeare.lit'
62
+ # id='create1'>
63
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub'>
64
+ # <create node='princely_musings'/>
65
+ # </pubsub>
66
+ # </iq>
67
+ #
68
+ # Expected
69
+ # <iq type='result'
70
+ # from='pubsub.shakespeare.lit'
71
+ # to='hamlet@denmark.lit/elsinore'
72
+ # id='create2'>
73
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub'>
74
+ # <create node='25e3d37dabbab9541f7523321421edc5bfeb2dae'/>
75
+ # </pubsub>
76
+ # </iq>
77
+ def create(jid, node)
78
+ request = Nokogiri::XML::Builder.new do |xml|
79
+ xml.iq_(:to => jid, :type => 'set') {
80
+ xml.pubsub_('xmlns' => namespaces['pubsub']) {
81
+ xml.create_('node' => node)
82
+ }
83
+ }
84
+ end
85
+
86
+ success = write(
87
+ # Generate stanza
88
+ request.to_xml
89
+ ).xpath(
90
+ # Pull out required parts
91
+ '//iq[@type="result"]/pubsub:pubsub/pubsub:create',
92
+ namespaces
93
+ ).any?
94
+ Jubjub::Pubsub.new jid, node, @connection if success
95
+ end
96
+
97
+ # http://xmpp.org/extensions/xep-0060.html#owner-delete
98
+ # <iq type='set'
99
+ # from='hamlet@denmark.lit/elsinore'
100
+ # to='pubsub.shakespeare.lit'
101
+ # id='delete1'>
102
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub#owner'>
103
+ # <delete node='princely_musings'>
104
+ # <redirect uri='xmpp:hamlet@denmark.lit?;node=blog'/>
105
+ # </delete>
106
+ # </pubsub>
107
+ # </iq>
108
+ #
109
+ # Expected
110
+ # <iq type='result'
111
+ # from='pubsub.shakespeare.lit'
112
+ # id='delete1'/>
113
+ def destroy(jid, node, redirect_jid = nil, redirect_node = nil)
114
+ request = Nokogiri::XML::Builder.new do |xml|
115
+ xml.iq_(:to => jid, :type => 'set') {
116
+ xml.pubsub_('xmlns' => namespaces['pubsub_owner']) {
117
+ xml.delete_('node' => node){
118
+ xml.redirect( 'uri' => pubsub_uri(redirect_jid, redirect_node) ) if redirect_jid && redirect_node
119
+ }
120
+ }
121
+ }
122
+ end
123
+
124
+ success = write(
125
+ # Generate stanza
126
+ request.to_xml
127
+ ).xpath(
128
+ # Pull out required parts
129
+ '//iq[@type="result"]'
130
+ ).any?
131
+ end
132
+
133
+ # http://xmpp.org/extensions/xep-0060.html#subscriber-subscribe
134
+ # <iq type='set'
135
+ # from='francisco@denmark.lit/barracks'
136
+ # to='pubsub.shakespeare.lit'
137
+ # id='sub1'>
138
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub'>
139
+ # <subscribe
140
+ # node='princely_musings'
141
+ # jid='francisco@denmark.lit'/>
142
+ # </pubsub>
143
+ # </iq>
144
+ #
145
+ # Expected
146
+ # <iq type='result'
147
+ # from='pubsub.shakespeare.lit'
148
+ # to='francisco@denmark.lit/barracks'
149
+ # id='sub1'>
150
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub'>
151
+ # <subscription
152
+ # node='princely_musings'
153
+ # jid='francisco@denmark.lit'
154
+ # subid='ba49252aaa4f5d320c24d3766f0bdcade78c78d3'
155
+ # subscription='subscribed'/>
156
+ # </pubsub>
157
+ # </iq>
158
+ def subscribe(jid, node)
159
+ request = Nokogiri::XML::Builder.new do |xml|
160
+ xml.iq_(:to => jid, :type => 'set') {
161
+ xml.pubsub_('xmlns' => namespaces['pubsub']) {
162
+ xml.subscribe_('node' => node, 'jid' => subscriber)
163
+ }
164
+ }
165
+ end
166
+
167
+ result = write(
168
+ # Generate stanza
169
+ request.to_xml
170
+ ).xpath(
171
+ # Pull out required parts
172
+ '//iq[@type="result"]/pubsub:pubsub/pubsub:subscription',
173
+ namespaces
174
+ )
175
+ if result.any?
176
+ subscriber = Jubjub::Jid.new(result.first.attr('jid'))
177
+ subid = result.first.attr('subid')
178
+ subscription = result.first.attr('subscription')
179
+ Jubjub::PubsubSubscription.new jid, node, subscriber, subid, subscription, @connection
180
+ end
181
+ end
182
+
183
+ # http://xmpp.org/extensions/xep-0060.html#subscriber-unsubscribe
184
+ # <iq type='set'
185
+ # from='francisco@denmark.lit/barracks'
186
+ # to='pubsub.shakespeare.lit'
187
+ # id='unsub1'>
188
+ # <pubsub xmlns='http://jabber.org/protocol/pubsub'>
189
+ # <unsubscribe
190
+ # node='princely_musings'
191
+ # jid='francisco@denmark.lit'/>
192
+ # </pubsub>
193
+ # </iq>
194
+ #
195
+ # Expected
196
+ # <iq type='result'
197
+ # from='pubsub.shakespeare.lit'
198
+ # to='francisco@denmark.lit/barracks'
199
+ # id='unsub1'/>
200
+ def unsubscribe(jid, node, subid=nil)
201
+ unsubscribe_options = {'node' => node, 'jid' => subscriber}
202
+ unsubscribe_options['subid'] = subid if subid
203
+
204
+ request = Nokogiri::XML::Builder.new do |xml|
205
+ xml.iq_(:to => jid, :type => 'set') {
206
+ xml.pubsub_('xmlns' => namespaces['pubsub']) {
207
+ xml.unsubscribe_(unsubscribe_options)
208
+ }
209
+ }
210
+ end
211
+
212
+ write(
213
+ # Generate stanza
214
+ request.to_xml
215
+ ).xpath(
216
+ # Pull out required parts
217
+ '//iq[@type="result"]'
218
+ ).any?
219
+ end
220
+
221
+ private
222
+
223
+ def subscriber
224
+ Jubjub::Jid.new @connection.jid.node, @connection.jid.domain
225
+ end
226
+
227
+ def pubsub_uri(jid, node)
228
+ "xmpp:#{jid}?;node=#{node}"
229
+ end
230
+
231
+ def namespaces
232
+ {
233
+ 'disco_items' => 'http://jabber.org/protocol/disco#items',
234
+ 'pubsub' => 'http://jabber.org/protocol/pubsub',
235
+ 'pubsub_owner' => 'http://jabber.org/protocol/pubsub#owner'
236
+ }
237
+ end
238
+
239
+ end
240
+ end
241
+ end
242
+ end
@@ -60,14 +60,12 @@ module Jubjub
60
60
  list.inspect
61
61
  end
62
62
 
63
- protected
63
+ private
64
64
 
65
65
  def method_missing(name, *args, &block)
66
66
  list.send(name, *args, &block)
67
67
  end
68
-
69
- private
70
-
68
+
71
69
  def list
72
70
  @list ||= @connection.muc.list @jid
73
71
  end
@@ -0,0 +1,107 @@
1
+ require "jubjub/connection/xmpp_gateway/pubsub"
2
+
3
+ module Jubjub
4
+
5
+ class Pubsub
6
+
7
+ attr_reader :jid, :node
8
+
9
+ def initialize(jid, node, connection)
10
+ @jid = Jubjub::Jid.new jid
11
+ @node = node
12
+ @connection = connection
13
+ end
14
+
15
+ def destroy(redirect_jid = nil, redirect_node = nil)
16
+ redirect_jid = Jubjub::Jid.new(redirect_jid) if redirect_jid
17
+ @connection.pubsub.destroy jid, node, redirect_jid, redirect_node
18
+ end
19
+
20
+ def subscribe
21
+ @connection.pubsub.subscribe jid, node
22
+ end
23
+
24
+ def unsubscribe(subid = nil)
25
+ @connection.pubsub.unsubscribe jid, node, subid
26
+ end
27
+
28
+ # Hide the connection details and show jid as string for compactness
29
+ def inspect
30
+ obj_id = "%x" % (object_id << 1)
31
+ "#<#{self.class}:0x#{obj_id} @jid=\"#{jid}\" @node=#{node.inspect}>"
32
+ end
33
+
34
+ end
35
+
36
+ class PubsubSubscription
37
+
38
+ attr_reader :jid, :node, :subscriber, :subid, :subscription
39
+
40
+ def initialize(jid, node, subscriber, subid, subscription, connection)
41
+ @jid = Jubjub::Jid.new jid
42
+ @node = node
43
+ @subscriber = Jubjub::Jid.new subscriber
44
+ @subid = subid
45
+ @subscription = subscription
46
+ @connection = connection
47
+ end
48
+
49
+ def unsubscribe
50
+ @connection.pubsub.unsubscribe jid, node, subid
51
+ end
52
+
53
+ # Hide the connection details and show jid as string for compactness
54
+ def inspect
55
+ obj_id = "%x" % (object_id << 1)
56
+ "#<#{self.class}:0x#{obj_id} @jid=\"#{jid}\" @node=#{node.inspect} @subscriber=\"#{subscriber}\" @subid=#{subid.inspect} @subscription=#{subscription.inspect}>"
57
+ end
58
+
59
+ end
60
+
61
+ # Uses proxy pattern for syntax sugar
62
+ # and delaying expensive operations until
63
+ # required
64
+ class PubsubCollection
65
+
66
+ attr_reader :jid
67
+
68
+ def initialize(jid, connection)
69
+ @jid = Jubjub::Jid.new jid
70
+ @connection = connection
71
+ end
72
+
73
+ def create(node)
74
+ @connection.pubsub.create jid, node
75
+ end
76
+
77
+ def destroy(node, redirect_jid = nil, redirect_node = nil)
78
+ redirect_jid = Jubjub::Jid.new(redirect_jid) if redirect_jid
79
+ @connection.pubsub.destroy jid, node, redirect_jid, redirect_node
80
+ end
81
+
82
+ def subscribe(node)
83
+ @connection.pubsub.subscribe jid, node
84
+ end
85
+
86
+ def unsubscribe(node, subid=nil)
87
+ @connection.pubsub.unsubscribe jid, node, subid
88
+ end
89
+
90
+ # Hint that methods are actually applied to list using method_missing
91
+ def inspect
92
+ list.inspect
93
+ end
94
+
95
+ private
96
+
97
+ def method_missing(name, *args, &block)
98
+ list.send(name, *args, &block)
99
+ end
100
+
101
+ def list
102
+ @list ||= @connection.pubsub.list jid
103
+ end
104
+
105
+ end
106
+
107
+ end
@@ -51,7 +51,12 @@ module Jubjub
51
51
  # if no jid is specified will default to 'connection.JID_DOMAIN'
52
52
  def mucs(jid = nil)
53
53
  jid ||= "conference.#{jubjub_jid.domain}"
54
- Jubjub::MucCollection.new(jid, jubjub_connection)
54
+ Jubjub::MucCollection.new jid, jubjub_connection
55
+ end
56
+
57
+ def pubsub(jid = nil)
58
+ jid ||= "pubsub.#{jubjub_jid.domain}"
59
+ Jubjub::PubsubCollection.new jid, jubjub_connection
55
60
  end
56
61
  end
57
62