shingara-blather 0.4.8

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.
Files changed (100) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +162 -0
  3. data/examples/echo.rb +18 -0
  4. data/examples/execute.rb +16 -0
  5. data/examples/ping_pong.rb +37 -0
  6. data/examples/print_hierarchy.rb +76 -0
  7. data/examples/rosterprint.rb +14 -0
  8. data/examples/stream_only.rb +27 -0
  9. data/examples/xmpp4r/echo.rb +35 -0
  10. data/lib/blather/client/client.rb +310 -0
  11. data/lib/blather/client/dsl/pubsub.rb +170 -0
  12. data/lib/blather/client/dsl.rb +264 -0
  13. data/lib/blather/client.rb +87 -0
  14. data/lib/blather/core_ext/nokogiri.rb +40 -0
  15. data/lib/blather/errors/sasl_error.rb +43 -0
  16. data/lib/blather/errors/stanza_error.rb +107 -0
  17. data/lib/blather/errors/stream_error.rb +82 -0
  18. data/lib/blather/errors.rb +69 -0
  19. data/lib/blather/jid.rb +142 -0
  20. data/lib/blather/roster.rb +111 -0
  21. data/lib/blather/roster_item.rb +122 -0
  22. data/lib/blather/stanza/disco/disco_info.rb +176 -0
  23. data/lib/blather/stanza/disco/disco_items.rb +132 -0
  24. data/lib/blather/stanza/disco.rb +25 -0
  25. data/lib/blather/stanza/iq/query.rb +53 -0
  26. data/lib/blather/stanza/iq/roster.rb +179 -0
  27. data/lib/blather/stanza/iq.rb +138 -0
  28. data/lib/blather/stanza/message.rb +332 -0
  29. data/lib/blather/stanza/presence/status.rb +212 -0
  30. data/lib/blather/stanza/presence/subscription.rb +101 -0
  31. data/lib/blather/stanza/presence.rb +163 -0
  32. data/lib/blather/stanza/pubsub/affiliations.rb +79 -0
  33. data/lib/blather/stanza/pubsub/create.rb +65 -0
  34. data/lib/blather/stanza/pubsub/errors.rb +18 -0
  35. data/lib/blather/stanza/pubsub/event.rb +123 -0
  36. data/lib/blather/stanza/pubsub/items.rb +103 -0
  37. data/lib/blather/stanza/pubsub/publish.rb +103 -0
  38. data/lib/blather/stanza/pubsub/retract.rb +92 -0
  39. data/lib/blather/stanza/pubsub/subscribe.rb +68 -0
  40. data/lib/blather/stanza/pubsub/subscription.rb +134 -0
  41. data/lib/blather/stanza/pubsub/subscriptions.rb +81 -0
  42. data/lib/blather/stanza/pubsub/unsubscribe.rb +68 -0
  43. data/lib/blather/stanza/pubsub.rb +129 -0
  44. data/lib/blather/stanza/pubsub_owner/delete.rb +52 -0
  45. data/lib/blather/stanza/pubsub_owner/purge.rb +52 -0
  46. data/lib/blather/stanza/pubsub_owner.rb +51 -0
  47. data/lib/blather/stanza.rb +149 -0
  48. data/lib/blather/stream/client.rb +31 -0
  49. data/lib/blather/stream/component.rb +38 -0
  50. data/lib/blather/stream/features/resource.rb +63 -0
  51. data/lib/blather/stream/features/sasl.rb +187 -0
  52. data/lib/blather/stream/features/session.rb +44 -0
  53. data/lib/blather/stream/features/tls.rb +28 -0
  54. data/lib/blather/stream/features.rb +53 -0
  55. data/lib/blather/stream/parser.rb +102 -0
  56. data/lib/blather/stream.rb +231 -0
  57. data/lib/blather/xmpp_node.rb +218 -0
  58. data/lib/blather.rb +78 -0
  59. data/spec/blather/client/client_spec.rb +559 -0
  60. data/spec/blather/client/dsl/pubsub_spec.rb +462 -0
  61. data/spec/blather/client/dsl_spec.rb +143 -0
  62. data/spec/blather/core_ext/nokogiri_spec.rb +83 -0
  63. data/spec/blather/errors/sasl_error_spec.rb +33 -0
  64. data/spec/blather/errors/stanza_error_spec.rb +129 -0
  65. data/spec/blather/errors/stream_error_spec.rb +108 -0
  66. data/spec/blather/errors_spec.rb +33 -0
  67. data/spec/blather/jid_spec.rb +87 -0
  68. data/spec/blather/roster_item_spec.rb +96 -0
  69. data/spec/blather/roster_spec.rb +103 -0
  70. data/spec/blather/stanza/discos/disco_info_spec.rb +226 -0
  71. data/spec/blather/stanza/discos/disco_items_spec.rb +148 -0
  72. data/spec/blather/stanza/iq/query_spec.rb +64 -0
  73. data/spec/blather/stanza/iq/roster_spec.rb +140 -0
  74. data/spec/blather/stanza/iq_spec.rb +45 -0
  75. data/spec/blather/stanza/message_spec.rb +132 -0
  76. data/spec/blather/stanza/presence/status_spec.rb +132 -0
  77. data/spec/blather/stanza/presence/subscription_spec.rb +105 -0
  78. data/spec/blather/stanza/presence_spec.rb +66 -0
  79. data/spec/blather/stanza/pubsub/affiliations_spec.rb +57 -0
  80. data/spec/blather/stanza/pubsub/create_spec.rb +56 -0
  81. data/spec/blather/stanza/pubsub/event_spec.rb +84 -0
  82. data/spec/blather/stanza/pubsub/items_spec.rb +79 -0
  83. data/spec/blather/stanza/pubsub/publish_spec.rb +83 -0
  84. data/spec/blather/stanza/pubsub/retract_spec.rb +75 -0
  85. data/spec/blather/stanza/pubsub/subscribe_spec.rb +61 -0
  86. data/spec/blather/stanza/pubsub/subscription_spec.rb +97 -0
  87. data/spec/blather/stanza/pubsub/subscriptions_spec.rb +59 -0
  88. data/spec/blather/stanza/pubsub/unsubscribe_spec.rb +61 -0
  89. data/spec/blather/stanza/pubsub_owner/delete_spec.rb +50 -0
  90. data/spec/blather/stanza/pubsub_owner/purge_spec.rb +50 -0
  91. data/spec/blather/stanza/pubsub_owner_spec.rb +27 -0
  92. data/spec/blather/stanza/pubsub_spec.rb +67 -0
  93. data/spec/blather/stanza_spec.rb +116 -0
  94. data/spec/blather/stream/client_spec.rb +1011 -0
  95. data/spec/blather/stream/component_spec.rb +95 -0
  96. data/spec/blather/stream/parser_spec.rb +145 -0
  97. data/spec/blather/xmpp_node_spec.rb +231 -0
  98. data/spec/fixtures/pubsub.rb +311 -0
  99. data/spec/spec_helper.rb +43 -0
  100. metadata +249 -0
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Blather
2
+
3
+ Copyright (c) 2009 Jeff Smick
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # Blather
2
+
3
+ XMPP DSL (and more) for Ruby written on EventMachine and Nokogiri.
4
+
5
+ ## Features
6
+
7
+ * evented architecture
8
+ * uses Nokogiri
9
+ * simplified starting point
10
+
11
+ ## Project Pages
12
+
13
+ * [Docs](http://blather.squishtech.com)
14
+ * [GitHub](https://github.com/sprsquish/blather)
15
+ * [Gemcutter](http://gemcutter.org/gems/blather)
16
+ * [Google Group](http://groups.google.com/group/xmpp-blather)
17
+
18
+ # Usage
19
+
20
+ ## Installation
21
+
22
+ sudo gem install blather
23
+
24
+ ## Example
25
+
26
+ See the examples directory for more advanced examples.
27
+
28
+ This will auto-accept any subscription requests and echo back any chat messages.
29
+
30
+ require 'rubygems'
31
+ require 'blather/client'
32
+
33
+ setup 'echo@jabber.local', 'echo'
34
+
35
+ # Auto approve subscription requests
36
+ subscription :request? do |s|
37
+ write_to_stream s.approve!
38
+ end
39
+
40
+ # Echo back what was said
41
+ message :chat?, :body do |m|
42
+ write_to_stream m.reply
43
+ end
44
+
45
+ ## Handlers
46
+
47
+ Setup handlers by calling their names as methods.
48
+
49
+ # Will only be called for messages where #chat? responds positively
50
+ # and #body == 'exit'
51
+ message :chat?, :body => 'exit'
52
+
53
+ ### Non-Stanza Handlers
54
+
55
+ So far there are two non-stanza related handlers.
56
+
57
+ # Called after the connection has been connected. It's good for initializing
58
+ # your system.
59
+ # DSL:
60
+ when_ready {}
61
+ # Client:
62
+ client.register_handler(:ready) {}
63
+
64
+ # Called after the connection has been terminated. Good for teardown or
65
+ # automatic reconnection.
66
+ # DSL:
67
+ disconnected {}
68
+ # Client
69
+ client.register_handler(:disconnected) {}
70
+ # The following will reconnect every time the connection is lost:
71
+ disconnected { client.connect }
72
+
73
+ ### Handler Guards
74
+
75
+ Guards act like AND statements. Each condition must be met if the handler is to
76
+ be used.
77
+
78
+ # Equivalent to saying (stanza.chat? && stanza.body)
79
+ message :chat?, :body
80
+
81
+ The different types of guards are:
82
+
83
+ # Symbol
84
+ # Checks for a non-false reply to calling the symbol on the stanza
85
+ # Equivalent to stanza.chat?
86
+ message :chat?
87
+
88
+ # Hash with any value (:body => 'exit')
89
+ # Calls the key on the stanza and checks for equality
90
+ # Equivalent to stanza.body == 'exit'
91
+ message :body => 'exit'
92
+
93
+ # Hash with regular expression (:body => /exit/)
94
+ # Calls the key on the stanza and checks for a match
95
+ # Equivalent to stanza.body.match /exit/
96
+ message :body => /exit/
97
+
98
+ # Hash with array (:name => [:gone, :forbidden])
99
+ # Calls the key on the stanza and check for inclusion in the array
100
+ # Equivalent to [:gone, :forbidden].include?(stanza.name)
101
+ stanza_error :name => [:gone, :fobidden]
102
+
103
+ # Proc
104
+ # Calls the proc passing in the stanza
105
+ # Checks that the ID is modulo 3
106
+ message proc { |m| m.id % 3 == 0 }
107
+
108
+ # Array
109
+ # Use arrays with the previous types effectively turns the guard into
110
+ # an OR statement.
111
+ # Equivalent to stanza.body == 'foo' || stanza.body == 'baz'
112
+ message [{:body => 'foo'}, {:body => 'baz'}]
113
+
114
+ # XPath
115
+ # Runs the xpath query on the stanza and checks for results
116
+ # This guard type cannot be combined with other guards
117
+ # Equivalent to !stanza.find('/iq/ns:pubsub', :ns => 'pubsub:namespace').empty?
118
+ iq '/iq/ns:pubsub', :ns => 'pubsub:namespace'
119
+
120
+ ### Filters
121
+
122
+ Blather provides before and after filters that work much the way regular
123
+ handlers work. Filters come in a before and after flavor. They're called in
124
+ order of definition and can be guarded like handlers.
125
+
126
+ before { |s| "I'm run before any handler" }
127
+ before { |s| "I'm run next" }
128
+
129
+ before(:message) { |s| "I'm only run in front of message stanzas" }
130
+ before(nil, :id => 1) { |s| "I'll only be run when the stanza's ID == 1" }
131
+
132
+ # ... handlers
133
+
134
+ after { |s| "I'm run after everything" }
135
+
136
+ ## On the Command Line:
137
+
138
+ Default usage is:
139
+
140
+ [blather_script] [options] node@domain.com/resource password [host] [port]
141
+
142
+ Command line options:
143
+
144
+ -D, --debug Run in debug mode (you will see all XMPP communication)
145
+ -d, --daemonize Daemonize the process
146
+ --pid=[PID] Write the PID to this file
147
+ --log=[LOG] Write to the [LOG] file instead of stdout/stderr
148
+ -h, --help Show this message
149
+ -v, --version Show version
150
+
151
+
152
+ # Author
153
+
154
+ [Jeff Smick](http://github.com/sprsquish)
155
+
156
+ ### Contributors
157
+
158
+ [Nolan Darilek](http://github.com/thewordnerd)
159
+
160
+ # Copyright
161
+
162
+ Copyright (c) 2009 Jeff Smick. See LICENSE for details.
data/examples/echo.rb ADDED
@@ -0,0 +1,18 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'blather/client'
4
+
5
+ when_ready { puts "Connected ! send messages to #{jid.stripped}." }
6
+
7
+ subscription :request? do |s|
8
+ write_to_stream s.approve!
9
+ end
10
+
11
+ message :chat?, :body => 'exit' do |m|
12
+ say m.from, 'Exiting ...'
13
+ shutdown
14
+ end
15
+
16
+ message :chat?, :body do |m|
17
+ say m.from, "You sent: #{m.body}"
18
+ end
@@ -0,0 +1,16 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'blather/client'
4
+
5
+ message :chat?, :body => 'exit' do |m|
6
+ say m.from, 'Exiting ...'
7
+ shutdown
8
+ end
9
+
10
+ message :chat?, :body do |m|
11
+ begin
12
+ say m.from, eval(m.body)
13
+ rescue => e
14
+ say m.from, e.inspect
15
+ end
16
+ end
@@ -0,0 +1,37 @@
1
+ require 'blather/client/dsl'
2
+ $stdout.sync = true
3
+
4
+ module Ping
5
+ extend Blather::DSL
6
+ def self.run; client.run; end
7
+
8
+ setup 'echo@jabber.local/ping', 'echo'
9
+
10
+ status :from => Blather::JID.new('echo@jabber.local/pong') do |s|
11
+ puts "serve!"
12
+ say s.from, 'ping'
13
+ end
14
+
15
+ message :chat?, :body => 'pong' do |m|
16
+ puts "ping!"
17
+ say m.from, 'ping'
18
+ end
19
+ end
20
+
21
+ module Pong
22
+ extend Blather::DSL
23
+ def self.run; client.run; end
24
+
25
+ setup 'echo@jabber.local/pong', 'echo'
26
+ message :chat?, :body => 'ping' do |m|
27
+ puts "pong!"
28
+ say m.from, 'pong'
29
+ end
30
+ end
31
+
32
+ trap(:INT) { EM.stop }
33
+ trap(:TERM) { EM.stop }
34
+ EM.run do
35
+ Ping.run
36
+ Pong.run
37
+ end
@@ -0,0 +1,76 @@
1
+ require 'blather'
2
+
3
+ class Object
4
+ begin
5
+ ObjectSpace.each_object(Class.new) {}
6
+
7
+ # Exclude this class unless it's a subclass of our supers and is defined.
8
+ # We check defined? in case we find a removed class that has yet to be
9
+ # garbage collected. This also fails for anonymous classes -- please
10
+ # submit a patch if you have a workaround.
11
+ def subclasses_of(*superclasses)
12
+ subclasses = []
13
+
14
+ superclasses.each do |sup|
15
+ ObjectSpace.each_object(class << sup; self; end) do |k|
16
+ if k != sup && (k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
17
+ subclasses << k
18
+ end
19
+ end
20
+ end
21
+
22
+ subclasses
23
+ end
24
+ rescue RuntimeError
25
+ # JRuby and any implementations which cannot handle the objectspace traversal
26
+ # above fall back to this implementation
27
+ def subclasses_of(*superclasses)
28
+ subclasses = []
29
+
30
+ superclasses.each do |sup|
31
+ ObjectSpace.each_object(Class) do |k|
32
+ if superclasses.any? { |superclass| k < superclass } &&
33
+ (k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
34
+ subclasses << k
35
+ end
36
+ end
37
+ subclasses.uniq!
38
+ end
39
+ subclasses
40
+ end
41
+ end
42
+ end
43
+
44
+ class Hash
45
+ def deep_merge(second)
46
+ # From: http://www.ruby-forum.com/topic/142809
47
+ # Author: Stefan Rusterholz
48
+ merger = proc { |key,v1,v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
49
+ self.merge(second, &merger)
50
+ end
51
+ end
52
+
53
+ handlers = {}
54
+ (Object.subclasses_of(Blather::Stanza) + Object.subclasses_of(Blather::BlatherError)).each do |klass|
55
+ handlers = handlers.deep_merge klass.handler_hierarchy.inject('klass' => klass.to_s.gsub('Blather::', '')) { |h,k| {k.to_s => h} }
56
+ end
57
+
58
+ level = 0
59
+ runner = proc do |k,v|
60
+ next if k == 'klass'
61
+
62
+ str = ''
63
+ if level > 0
64
+ (level - 1).times { str << '| ' }
65
+ str << '|- '
66
+ end
67
+
68
+ puts str+k
69
+ if Hash === v
70
+ level += 1
71
+ v.sort.each &runner
72
+ level -= 1
73
+ end
74
+ end
75
+
76
+ handlers.sort.each &runner
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # Prints out each roster entry
4
+
5
+ require 'blather/client'
6
+
7
+ when_ready do
8
+ roster.grouped.each do |group, items|
9
+ puts "#{'*'*3} #{group || 'Ungrouped'} #{'*'*3}"
10
+ items.each { |item| puts "- #{item.name} (#{item.jid})" }
11
+ puts
12
+ end
13
+ shutdown
14
+ end
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'blather'
4
+
5
+ trap(:INT) { EM.stop }
6
+ trap(:TERM) { EM.stop }
7
+ EM.run do
8
+ Blather::Stream::Client.start(Class.new {
9
+ attr_accessor :jid
10
+
11
+ def post_init(stream, jid = nil)
12
+ @stream = stream
13
+ self.jid = jid
14
+
15
+ @stream.send_data Blather::Stanza::Presence::Status.new
16
+ puts "Stream started!"
17
+ end
18
+
19
+ def receive_data(stanza)
20
+ @stream.send_data stanza.reply!
21
+ end
22
+
23
+ def unbind
24
+ puts "Stream ended!"
25
+ end
26
+ }.new, 'echo@jabber.local', 'echo')
27
+ end
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/ruby
2
+
3
+ # This bot will reply to every message it receives. To end the game, send 'exit'
4
+
5
+ require 'xmpp4r/client'
6
+ include Jabber
7
+
8
+ # settings
9
+ if ARGV.length != 2
10
+ puts "Run with ./echo_thread.rb user@server/resource password"
11
+ exit 1
12
+ end
13
+ myJID = JID.new(ARGV[0])
14
+ myPassword = ARGV[1]
15
+ cl = Client.new(myJID)
16
+ cl.connect
17
+ cl.auth(myPassword)
18
+ cl.send(Presence.new)
19
+ puts "Connected ! send messages to #{myJID.strip.to_s}."
20
+ mainthread = Thread.current
21
+ cl.add_message_callback do |m|
22
+ if m.type != :error
23
+ m2 = Message.new(m.from, "You sent: #{m.body}")
24
+ m2.type = m.type
25
+ cl.send(m2)
26
+ if m.body == 'exit'
27
+ m2 = Message.new(m.from, "Exiting ...")
28
+ m2.type = m.type
29
+ cl.send(m2)
30
+ mainthread.wakeup
31
+ end
32
+ end
33
+ end
34
+ Thread.stop
35
+ cl.close