shingara-blather 0.4.8

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