File: presence.rb

package info (click to toggle)
ruby-xmpp4r 0.5.6-2
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, forky, sid, trixie
  • size: 1,384 kB
  • sloc: ruby: 17,382; xml: 74; sh: 12; makefile: 4
file content (232 lines) | stat: -rw-r--r-- 5,820 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
# =XMPP4R - XMPP Library for Ruby
# License:: Ruby's license (see the LICENSE file) or GNU GPL, at your option.
# Website::http://xmpp4r.github.io

require 'xmpp4r/xmppstanza'
require 'xmpp4r/x'

module Jabber
  ##
  # The presence class is used to construct presence messages to
  # send to the Jabber service.
  class Presence < XMPPStanza
    name_xmlns 'presence', 'jabber:client'
    force_xmlns true

    include Comparable
    include XParent

    ##
    # Create presence stanza
    # show:: [Symbol] Initial Availability Status (see show)
    # status:: [String] Initial status message
    # priority:: [Fixnum] Initial priority value
    def initialize(show=nil, status=nil, priority=nil)
      super()
      set_show(show) if show
      set_status(status) if status
      set_priority(priority) if priority
    end

    ##
    # Get type of presence
    #
    # result:: [Symbol] or [Nil] Possible values are:
    # * :error
    # * :probe (Servers send this to request presence information)
    # * :subscribe (Subscription request)
    # * :subscribed (Subscription approval)
    # * :unavailable (User has gone offline)
    # * :unsubscribe (Unsubscription request)
    # * :unsubscribed (Unsubscription approval)
    # * [nil] (available)
    # See RFC3921 - 2.2.1. for explanation.
    def type
      case super
        when 'error' then :error
        when 'probe' then :probe
        when 'subscribe' then :subscribe
        when 'subscribed' then :subscribed
        when 'unavailable' then :unavailable
        when 'unsubscribe' then :unsubscribe
        when 'unsubscribed' then :unsubscribed
        else nil
      end
    end

    ##
    # Set type of presence
    # val:: [Symbol] See type for possible subscription types
    def type=(val)
      case val
        when :error then super('error')
        when :probe then super('probe')
        when :subscribe then super('subscribe')
        when :subscribed then super('subscribed')
        when :unavailable then super('unavailable')
        when :unsubscribe then super('unsubscribe')
        when :unsubscribed then super('unsubscribed')
        else super(nil)
      end
    end

    ##
    # Set type of presence (chaining-friendly)
    # val:: [Symbol] See type for possible subscription types
    def set_type(val)
      self.type = val
      self
    end

    ##
    # Get Availability Status (RFC3921 - 5.2)
    # result:: [Symbol] or [Nil] Valid values according to RFC3921:
    # * nil (Available, no <show/> element)
    # * :away
    # * :chat (Free for chat)
    # * :dnd (Do not disturb)
    # * :xa (Extended away)
    def show
      e = first_element('show')
      text = e ? e.text : nil
      case text
        when 'away' then :away
        when 'chat' then :chat
        when 'dnd' then :dnd
        when 'xa' then :xa
        else nil
      end
    end

    ##
    # Set Availability Status
    # val:: [Symbol] or [Nil] See show for explanation
    def show=(val)
      xe = first_element('show')
      if xe.nil?
        xe = add_element('show')
      end
      case val
        when String then raise "Invalid value for show."
        when :away then text = 'away'
        when :chat then text = 'chat'
        when :dnd then text = 'dnd'
        when :xa then text = 'xa'
        when nil then text = nil
        else raise "Invalid value for show."
      end

      if text.nil?
        delete_element(xe)
      else
        xe.text = text
      end
    end

    ##
    # Set Availability Status (chaining-friendly)
    # val:: [Symbol] or [Nil] See show for explanation
    def set_show(val)
      self.show = val
      self
    end

    ##
    # Get status message
    # result:: [String] or nil
    def status
      first_element_text('status')
    end

    ##
    # Set status message
    # val:: [String] or nil
    def status=(val)
      if val.nil?
        delete_element('status')
      else
        replace_element_text('status', val)
      end
    end

    ##
    # Set status message (chaining-friendly)
    # val:: [String] or nil
    def set_status(val)
      self.status = val
      self
    end

    ##
    # Get presence priority, or nil if absent
    # result:: [Integer]
    def priority
       e = first_element_text('priority')
      if e
        return e.to_i
      else
        return nil
      end
    end

    ##
    # Set presence priority
    # val:: [Integer] Priority value between -128 and +127
    #
    # *Warning:* negative values make you receive no subscription requests etc.
    # (RFC3921 - 2.2.2.3.)
    def priority=(val)
      if val.nil?
        delete_element('priority')
      else
        replace_element_text('priority', val)
      end
    end

    ##
    # Set presence priority (chaining-friendly)
    # val:: [Integer] Priority value between -128 and +127
    def set_priority(val)
      self.priority = val
      self
    end

    ##
    # Compare two presences using priority
    # (with cmp_interest as fall-back).
    def <=>(o)
      if priority.to_i == o.priority.to_i
        cmp_interest(o)
      else
        priority.to_i <=> o.priority.to_i
      end
    end

    ##
    # Compare two presences. The most suitable to talk with is the
    # biggest.
    PRESENCE_STATUS = { :chat => 4,
                        nil => 3,
                        :dnd => 2,
                        :away => 1,
                        :xa => 0,
                        :unavailable => -1,
                        :error => -2 }
    def cmp_interest(o)
      if type.nil?
        if o.type.nil?
          # both available.
          PRESENCE_STATUS[show] <=> PRESENCE_STATUS[o.show]
        else
          return -1
        end
      elsif o.type.nil?
        return 1
      else
        # both are non-nil. We consider this is equal.
        return 0
      end
    end

  end
end