blather 0.4.7 → 0.4.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (59) hide show
  1. data/README.md +162 -0
  2. data/examples/{print_heirarchy.rb → print_hierarchy.rb} +5 -5
  3. data/examples/stream_only.rb +27 -0
  4. data/lib/blather.rb +4 -0
  5. data/lib/blather/client/client.rb +91 -73
  6. data/lib/blather/client/dsl.rb +156 -32
  7. data/lib/blather/client/dsl/pubsub.rb +86 -54
  8. data/lib/blather/core_ext/active_support.rb +9 -9
  9. data/lib/blather/core_ext/active_support/inheritable_attributes.rb +2 -2
  10. data/lib/blather/core_ext/nokogiri.rb +12 -7
  11. data/lib/blather/errors.rb +25 -14
  12. data/lib/blather/errors/sasl_error.rb +21 -3
  13. data/lib/blather/errors/stanza_error.rb +37 -21
  14. data/lib/blather/errors/stream_error.rb +27 -17
  15. data/lib/blather/jid.rb +79 -24
  16. data/lib/blather/roster.rb +39 -21
  17. data/lib/blather/roster_item.rb +43 -21
  18. data/lib/blather/stanza.rb +88 -40
  19. data/lib/blather/stanza/disco.rb +12 -2
  20. data/lib/blather/stanza/disco/disco_info.rb +112 -20
  21. data/lib/blather/stanza/disco/disco_items.rb +81 -12
  22. data/lib/blather/stanza/iq.rb +94 -38
  23. data/lib/blather/stanza/iq/query.rb +16 -22
  24. data/lib/blather/stanza/iq/roster.rb +98 -20
  25. data/lib/blather/stanza/message.rb +266 -111
  26. data/lib/blather/stanza/presence.rb +118 -42
  27. data/lib/blather/stanza/presence/status.rb +140 -60
  28. data/lib/blather/stanza/presence/subscription.rb +44 -10
  29. data/lib/blather/stanza/pubsub.rb +70 -15
  30. data/lib/blather/stanza/pubsub/affiliations.rb +36 -7
  31. data/lib/blather/stanza/pubsub/create.rb +26 -4
  32. data/lib/blather/stanza/pubsub/errors.rb +13 -4
  33. data/lib/blather/stanza/pubsub/event.rb +56 -10
  34. data/lib/blather/stanza/pubsub/items.rb +46 -6
  35. data/lib/blather/stanza/pubsub/publish.rb +52 -7
  36. data/lib/blather/stanza/pubsub/retract.rb +45 -6
  37. data/lib/blather/stanza/pubsub/subscribe.rb +30 -4
  38. data/lib/blather/stanza/pubsub/subscription.rb +74 -6
  39. data/lib/blather/stanza/pubsub/subscriptions.rb +35 -9
  40. data/lib/blather/stanza/pubsub/unsubscribe.rb +30 -4
  41. data/lib/blather/stanza/pubsub_owner.rb +17 -7
  42. data/lib/blather/stanza/pubsub_owner/delete.rb +23 -5
  43. data/lib/blather/stanza/pubsub_owner/purge.rb +23 -5
  44. data/lib/blather/stream.rb +96 -29
  45. data/lib/blather/stream/parser.rb +6 -9
  46. data/lib/blather/xmpp_node.rb +101 -153
  47. data/spec/blather/client/client_spec.rb +1 -1
  48. data/spec/blather/errors_spec.rb +5 -5
  49. data/spec/blather/stanza/message_spec.rb +56 -0
  50. data/spec/blather/stanza/presence/status_spec.rb +1 -1
  51. data/spec/blather/stanza_spec.rb +3 -3
  52. data/spec/blather/xmpp_node_spec.rb +19 -74
  53. metadata +6 -10
  54. data/README.rdoc +0 -185
  55. data/examples/drb_client.rb +0 -5
  56. data/examples/ping.rb +0 -11
  57. data/examples/pong.rb +0 -6
  58. data/examples/pubsub/cli.rb +0 -64
  59. data/examples/pubsub/ping_pong.rb +0 -18
@@ -1,20 +1,27 @@
1
1
  module Blather
2
2
 
3
- ##
4
- # Local Roster
3
+ # Local Roster
5
4
  # Takes care of adding/removing JIDs through the stream
6
5
  class Roster
7
6
  include Enumerable
8
7
 
8
+ # Create a new roster
9
+ #
10
+ # @param [Blather::Stream] stream the stream the roster should use to
11
+ # update roster entries
12
+ # @param [Blather::Stanza::Roster] stanza a roster stanza used to preload
13
+ # the roster
14
+ # @return [Blather::Roster]
9
15
  def initialize(stream, stanza = nil)
10
16
  @stream = stream
11
17
  @items = {}
12
18
  stanza.items.each { |i| push i, false } if stanza
13
19
  end
14
20
 
15
- ##
16
- # Process any incoming stanzas adn either add or remove the
21
+ # Process any incoming stanzas and either adds or removes the
17
22
  # corresponding RosterItem
23
+ #
24
+ # @param [Blather::Stanza::Roster] stanza a roster stanza
18
25
  def process(stanza)
19
26
  stanza.items.each do |i|
20
27
  case i.subscription
@@ -24,18 +31,21 @@ module Blather
24
31
  end
25
32
  end
26
33
 
27
- ##
28
34
  # Pushes a JID into the roster
29
- # then returns self to allow for chaining
35
+ #
36
+ # @param [String, Blather::JID, #jid] elem a JID to add to the roster
37
+ # @return [self]
38
+ # @see #push
30
39
  def <<(elem)
31
40
  push elem
32
41
  self
33
42
  end
34
43
 
35
- ##
36
- # Push a JID into the roster
37
- # Will send the new item to the server
38
- # unless overridden by calling #push(elem, false)
44
+ # Push a JID into the roster and update the server
45
+ #
46
+ # @param [String, Blather::JID, #jid] elem a jid to add to the roster
47
+ # @param [true, false] send send the update over the wire
48
+ # @see Blather::JID
39
49
  def push(elem, send = true)
40
50
  jid = elem.respond_to?(:jid) ? elem.jid : JID.new(elem)
41
51
  @items[key(jid)] = node = RosterItem.new(elem)
@@ -44,35 +54,41 @@ module Blather
44
54
  end
45
55
  alias_method :add, :push
46
56
 
47
- ##
48
- # Remove a JID from the roster
49
- # Sends a remove query stanza to the server
57
+ # Remove a JID from the roster and update the server
58
+ #
59
+ # @param [String, Blather::JID] jid the JID to remove from the roster
50
60
  def delete(jid)
51
61
  @items.delete key(jid)
52
- @stream.write Stanza::Iq::Roster.new(:set, Stanza::Iq::Roster::RosterItem.new(jid, nil, :remove))
62
+ item = Stanza::Iq::Roster::RosterItem.new(jid, nil, :remove)
63
+ @stream.write Stanza::Iq::Roster.new(:set, item)
53
64
  end
54
65
  alias_method :remove, :delete
55
66
 
56
- ##
57
67
  # Get a RosterItem by JID
68
+ #
69
+ # @param [String, Blather::JID] jid the jid of the item to return
70
+ # @return [Blather::RosterItem, nil] the associated RosterItem
58
71
  def [](jid)
59
72
  items[key(jid)]
60
73
  end
61
74
 
62
- ##
63
75
  # Iterate over all RosterItems
76
+ #
77
+ # @yield [Blather::RosterItem] yields each RosterItem
64
78
  def each(&block)
65
79
  items.each &block
66
80
  end
67
81
 
68
- ##
69
- # Returns a duplicate of all RosterItems
82
+ # Get a duplicate of all RosterItems
83
+ #
84
+ # @return [Array<Blather::RosterItem>] a duplicate of all RosterItems
70
85
  def items
71
86
  @items.dup
72
87
  end
73
88
 
74
- ##
75
89
  # A hash of items keyed by group
90
+ #
91
+ # @return [Hash<group => Array<RosterItem>>]
76
92
  def grouped
77
93
  self.inject(Hash.new{|h,k|h[k]=[]}) do |hash, item|
78
94
  item[1].groups.each { |group| hash[group] << item[1] }
@@ -81,13 +97,15 @@ module Blather
81
97
  end
82
98
 
83
99
  private
100
+ # Creates a stripped jid
84
101
  def self.key(jid)
85
102
  JID.new(jid).stripped.to_s
86
103
  end
87
104
 
105
+ # Instance method to wrap around the class method
88
106
  def key(jid)
89
107
  self.class.key(jid)
90
108
  end
91
- end #Roster
109
+ end # Roster
92
110
 
93
- end
111
+ end # Blather
@@ -1,10 +1,9 @@
1
1
  module Blather
2
2
 
3
- ##
4
3
  # RosterItems hold internal representations of the user's roster
5
4
  # including each JID's status.
6
5
  class RosterItem
7
- VALID_SUBSCRIPTION_TYPES = [:both, :from, :none, :remove, :to]
6
+ VALID_SUBSCRIPTION_TYPES = [:both, :from, :none, :remove, :to].freeze
8
7
 
9
8
  attr_reader :jid,
10
9
  :ask,
@@ -18,8 +17,19 @@ module Blather
18
17
  super
19
18
  end
20
19
 
21
- ##
22
- # item:: can be a JID, String (a@b) or a Stanza
20
+ # Create a new RosterItem
21
+ #
22
+ # @overload initialize(jid)
23
+ # Create a new RosterItem based on a JID
24
+ # @param [Blather::JID] jid the JID object
25
+ # @overload initialize(jid)
26
+ # Create a new RosterItem based on a JID string
27
+ # @param [String] jid a JID string
28
+ # @overload initialize(node)
29
+ # Create a new RosterItem based on a stanza
30
+ # @param [Blather::Stanza::Iq::Roster::RosterItem] node a RosterItem
31
+ # stanza
32
+ # @return [Blather::RosterItem] the new RosterItem
23
33
  def initialize(item)
24
34
  @statuses = []
25
35
  @groups = []
@@ -40,54 +50,66 @@ module Blather
40
50
  @groups = [nil] if @groups.empty?
41
51
  end
42
52
 
43
- ##
44
53
  # Set the jid
54
+ #
55
+ # @param [String, Blather::JID] jid the new jid
56
+ # @see Blather::JID
45
57
  def jid=(jid)
46
58
  @jid = JID.new(jid).stripped
47
59
  end
48
60
 
49
- ##
50
61
  # Set the subscription
51
62
  # Ensures it is one of VALID_SUBSCRIPTION_TYPES
63
+ #
64
+ # @param [#to_sym] sub the new subscription
52
65
  def subscription=(sub)
53
- raise ArgumentError, "Invalid Type (#{sub}), use: #{VALID_SUBSCRIPTION_TYPES*' '}" if
54
- sub && !VALID_SUBSCRIPTION_TYPES.include?(sub = sub.to_sym)
66
+ if sub && !VALID_SUBSCRIPTION_TYPES.include?(sub = sub.to_sym)
67
+ raise ArgumentError, "Invalid Type (#{sub}), use: #{VALID_SUBSCRIPTION_TYPES*' '}"
68
+ end
55
69
  @subscription = sub ? sub : :none
56
70
  end
57
71
 
58
- ##
59
72
  # Get the current subscription
60
- # returns:: :both, :from, :none, :remove, :to or :none
73
+ #
74
+ # @return [:both, :from, :none, :remove, :to]
61
75
  def subscription
62
76
  @subscription || :none
63
77
  end
64
78
 
65
- ##
66
79
  # Set the ask value
67
- # ask:: must only be nil or :subscribe
80
+ #
81
+ # @param [nil, :subscribe] ask the new ask
68
82
  def ask=(ask)
69
- raise ArgumentError, "Invalid Type (#{ask}), can only be :subscribe" if ask && (ask = ask.to_sym) != :subscribe
83
+ if ask && (ask = ask.to_sym) != :subscribe
84
+ raise ArgumentError, "Invalid Type (#{ask}), can only be :subscribe"
85
+ end
70
86
  @ask = ask ? ask : nil
71
87
  end
72
88
 
73
- ##
74
89
  # Set the status then sorts them according to priority
75
- # presence:: Status
90
+ #
91
+ # @param [Blather::Stanza::Status] the new status
76
92
  def status=(presence)
77
93
  @statuses.delete_if { |s| s.from == presence.from }
78
94
  @statuses << presence
79
95
  @statuses.sort!
80
96
  end
81
97
 
82
- ##
83
- # Return the status with the highest priority
84
- # if resource is set find the status of that specific resource
98
+ # The status with the highest priority
99
+ #
100
+ # @param [String, nil] resource the resource to get the status of
85
101
  def status(resource = nil)
86
- top = resource ? @statuses.detect { |s| s.from.resource == resource } : @statuses.first
102
+ top = if resource
103
+ @statuses.detect { |s| s.from.resource == resource }
104
+ else
105
+ @statuses.first
106
+ end
87
107
  end
88
108
 
89
- ##
90
- # Translate the RosterItem into a proper stanza that can be sent over the stream
109
+ # Translate the RosterItem into a proper stanza that can be sent over the
110
+ # stream
111
+ #
112
+ # @return [Blather::Stanza::Iq::Roster]
91
113
  def to_stanza(type = nil)
92
114
  r = Stanza::Iq::Roster.new type
93
115
  n = Stanza::Iq::Roster::RosterItem.new jid, name, subscription, ask
@@ -1,95 +1,143 @@
1
1
  module Blather
2
- ##
3
- # Base XMPP Stanza
2
+
3
+ # # Base XMPP Stanza
4
+ #
5
+ # All stanzas inherit this class. It provides a set of methods and helpers
6
+ # common to all XMPP Stanzas
7
+ #
8
+ # @handler :stanza
4
9
  class Stanza < XMPPNode
10
+ # @private
5
11
  @@last_id = 0
12
+ # @private
6
13
  @@handler_list = []
7
14
 
8
- class_inheritable_array :handler_heirarchy
15
+ class_inheritable_array :handler_hierarchy
9
16
 
10
- ##
11
- # Registers a callback onto the callback heirarchy stack
17
+ # Registers a callback onto the callback stack
12
18
  #
13
- # Thanks to help from ActiveSupport every class
14
- # that inherits Stanza can register a callback for itself
15
- # which is added to a list and iterated over when looking for
16
- # a callback to use
19
+ # @param [Symbol] handler the name of the handler
20
+ # @param [Symbol, String, nil] name the name of the first element in the
21
+ # stanza. If nil the inherited name will be used. If that's nil the
22
+ # handler name will be used.
23
+ # @param [String, nil] ns the namespace of the stanza
17
24
  def self.register(handler, name = nil, ns = nil)
18
25
  @@handler_list << handler
19
- self.handler_heirarchy ||= []
20
- self.handler_heirarchy.unshift handler
26
+ self.handler_hierarchy ||= [:stanza]
27
+ self.handler_hierarchy.unshift handler
21
28
 
22
29
  name = name || self.registered_name || handler
23
30
  super name, ns
24
31
  end
25
32
 
33
+ # The handler stack for the current stanza class
34
+ #
35
+ # @return [Array<Symbol>]
26
36
  def self.handler_list
27
37
  @@handler_list
28
38
  end
29
39
 
30
- ##
31
40
  # Helper method that creates a unique ID for stanzas
41
+ #
42
+ # @return [String] a new unique ID
32
43
  def self.next_id
33
44
  @@last_id += 1
34
45
  'blather%04x' % @@last_id
35
46
  end
36
47
 
37
- ##
38
- # Helper method to generate stanza guard methods
39
- #
40
- # attribute_helpers_for(:type, [:subscribe, :unsubscribe])
48
+ # Check if the stanza is an error stanza
41
49
  #
42
- # This generates "subscribe?" and "unsubscribe?" methods that return
43
- # true if self.type == :subscribe or :unsubscribe, respectively.
44
- def self.attribute_helpers_for(attr, values)
45
- [values].flatten.each do |v|
46
- define_method("#{v}?") { __send__(attr) == v }
47
- end
50
+ # @return [true, false]
51
+ def error?
52
+ self.type == :error
48
53
  end
49
54
 
50
- attribute_helpers_for(:type, :error)
51
-
52
- ##
53
- # Copies itself then swaps from and to
54
- # then returns the new stanza
55
+ # Creates a copy with to and from swapped
56
+ #
57
+ # @return [Blather::Stanza]
55
58
  def reply
56
59
  self.dup.reply!
57
60
  end
58
61
 
59
- ##
60
62
  # Swaps from and to
63
+ #
64
+ # @return [self]
61
65
  def reply!
62
66
  self.to, self.from = self.from, self.to
63
67
  self
64
68
  end
65
69
 
66
- attribute_accessor :id
70
+ # Get the stanza's ID
71
+ #
72
+ # @return [String, nil]
73
+ def id
74
+ read_attr :id
75
+ end
67
76
 
68
- attribute_writer :to, :from
77
+ # Set the stanza's ID
78
+ #
79
+ # @param [#to_s] id the new stanza ID
80
+ def id=(id)
81
+ write_attr :id, id
82
+ end
69
83
 
70
- ##
71
- # returns:: JID created from the "to" value of the stanza
84
+ # Get the stanza's to
85
+ #
86
+ # @return [Blather::JID, nil]
72
87
  def to
73
88
  JID.new(self[:to]) if self[:to]
74
89
  end
75
90
 
76
- ##
77
- # returns:: JID created from the "from" value of the stanza
91
+ # Set the stanza's to field
92
+ #
93
+ # @param [#to_s] to the new JID for the to field
94
+ def to=(to)
95
+ write_attr :to, to
96
+ end
97
+
98
+ # Get the stanza's from
99
+ #
100
+ # @return [Blather::JID, nil]
78
101
  def from
79
102
  JID.new(self[:from]) if self[:from]
80
103
  end
81
104
 
82
- attribute_accessor :type, :call => :to_sym
105
+ # Set the stanza's from field
106
+ #
107
+ # @param [#to_s] from the new JID for the from field
108
+ def from=(from)
109
+ write_attr :from, from
110
+ end
83
111
 
84
- ##
85
- # Transform the stanza into a stanza error
86
- # <tt>err_name_or_class</tt> can be the name of the error or the error class to use
87
- # <tt>type</tt>, <tt>text</tt>, <tt>extras</tt> are the same as for StanzaError#new
112
+ # Get the stanza's type
113
+ #
114
+ # @return [Symbol, nil]
115
+ def type
116
+ read_attr :type, :to_sym
117
+ end
118
+
119
+ # Set the stanza's type
120
+ #
121
+ # @param [#to_s] type the new stanza type
122
+ def type=(type)
123
+ write_attr :type, type
124
+ end
125
+
126
+ # Create an error stanza from the current stanza
127
+ #
128
+ # @param [String] name the error name
129
+ # @param [<Blather::StanzaError::VALID_TYPES>] type the error type
130
+ # @param [String, nil] text the error text
131
+ # @param [Array<XML::Node>] extras an array of extra nodes to attach to
132
+ # the error
133
+ #
134
+ # @return [Blather::StanzaError]
88
135
  def as_error(name, type, text = nil, extras = [])
89
136
  StanzaError.new self, name, type, text, extras
90
137
  end
91
138
 
92
- protected
139
+ protected
140
+ # @private
93
141
  def reply_if_needed!
94
142
  unless @reversed_endpoints
95
143
  reply!
@@ -1,15 +1,25 @@
1
1
  module Blather
2
2
  class Stanza
3
3
 
4
+ # # Disco Base class
5
+ #
6
+ # Use Blather::Stanza::DiscoInfo or Blather::Stanza::DiscoItems
4
7
  class Disco < Iq::Query
8
+
9
+ # Get the name of the node
10
+ #
11
+ # @return [String] the node name
5
12
  def node
6
13
  query[:node]
7
14
  end
8
15
 
16
+ # Set the name of the node
17
+ #
18
+ # @param [#to_s] node the new node name
9
19
  def node=(node)
10
20
  query[:node] = node
11
21
  end
12
22
  end
13
23
 
14
- end #Stanza
15
- end #Blather
24
+ end # Stanza
25
+ end # Blather