Class: Jabber::Observable

Inherits:
Object
  • Object
show all
Includes:
ObservableThing
Defined in:
lib/xmpp4r/observable/helper.rb,
lib/xmpp4r/observable/pubsub.rb,
lib/xmpp4r/observable/contact.rb,
lib/xmpp4r/observable/subscription.rb

Overview

Jabber::Observable - Creates observable Jabber Clients

Defined Under Namespace

Classes: Contact, PubSub, Subscriptions

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ObservableThing

#add_observer, #changed, #changed?, #count_notifications, #count_observers, #delete_observer, #delete_observers, #notify_observers, #pending_notifications?, #wait_notifications

Constructor Details

#initialize(jid, password, status = nil, status_message = "Available", host = nil, port = 5222) ⇒ Observable

Create a new Jabber::Observable client. You will be automatically connected to the Jabber server and your status message will be set to the string passed in as the status_message argument.

jabber = Jabber::Observable.new(“[email protected]”, “password”, nil, “Talk to me - Please!”)

jid

your jid (either a string or a JID object)

password

your password

status

your status. Check Jabber::Observable#status for documentation

status_message

some funny string

host

the server host (if different from the one in the jid)

port

the server port (default: 5222)



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
# File 'lib/xmpp4r/observable/helper.rb', line 39

def initialize(jid, password, status=nil, status_message="Available", host=nil, port=5222)

  # Basic stuff
  @jid = jid.respond_to?(:resource) ? jid : Jabber::JID.new(jid)
  @password = password
  @host = host
  @port = port

  # Message dealing
  @delivered_messages = 0
  @deferred_messages = Queue.new
  start_deferred_delivery_thread

  # Connection stuff
  @connect_mutex = Mutex.new
  @client = nil
  @roster = nil
  @disconnected = false

  # Tell everybody I am here
  status(status, status_message)

  # Subscription Accessor
  @subs = Jabber::Observable::Subscriptions.new(self)

  # PubSub Accessor
  @pubsub = Jabber::Observable::PubSub.new(self)

  # Auto Observer placeholder
  @auto = nil

  # Our contacts Hash
  @contacts = Hash.new
end

Instance Attribute Details

#autoObject (readonly)

Returns the value of attribute auto.



25
26
27
# File 'lib/xmpp4r/observable/helper.rb', line 25

def auto
  @auto
end

#jidObject (readonly)

Returns the value of attribute jid.



25
26
27
# File 'lib/xmpp4r/observable/helper.rb', line 25

def jid
  @jid
end

#pubsubObject (readonly)

Returns the value of attribute pubsub.



25
26
27
# File 'lib/xmpp4r/observable/helper.rb', line 25

def pubsub
  @pubsub
end

#subsObject (readonly)

Returns the value of attribute subs.



25
26
27
# File 'lib/xmpp4r/observable/helper.rb', line 25

def subs
  @subs
end

Instance Method Details

#attach_auto_observerObject

Attach an auto-observer based on QObserver

Raises:

  • (StandardError)


97
98
99
100
101
102
103
104
# File 'lib/xmpp4r/observable/helper.rb', line 97

def attach_auto_observer
  raise StandardError, "Already attached." unless @auto.nil?

  @auto = QObserver.new
  [ :message, :presence, :iq, :new_subscription, :subscription_request, :event ].each do |thing|
    self.add_observer(thing, @auto)
  end
end

#clientObject

Pass the underlying Jabber client.



199
200
201
202
# File 'lib/xmpp4r/observable/helper.rb', line 199

def client
  connect! unless connected?
  @client
end

#connected?Boolean

Returns true if the Jabber client is connected to the Jabber server, false otherwise.

Returns:

  • (Boolean)


188
189
190
# File 'lib/xmpp4r/observable/helper.rb', line 188

def connected?
  @client.respond_to?(:is_connected?) && @client.is_connected?
end

#contacts(*contact) ⇒ Object

Transform a passed list of contacts in one or more Jabber::Observable::Contact objects.

contact

one of more jids of contacts



172
173
174
175
176
177
178
179
180
181
182
183
184
# File 'lib/xmpp4r/observable/helper.rb', line 172

def contacts(*contact)
  ret = []
  contact.each do |c|
    jid = c.to_s
    # Do we already have it?
    if ! @contacts.include?(jid)
      # Nope.
      @contacts[jid] = c.instance_of?(Jabber::Observable::Contact) ? c : Jabber::Observable::Contact.new(c, self)
    end
    ret << @contacts[jid]
  end
  ret
end

#deferred_max_waitObject

Get the maximum time to wait for a message to be delivered. Default: 600 seconds (10 minutes).



260
261
262
# File 'lib/xmpp4r/observable/helper.rb', line 260

def deferred_max_wait
  @deferred_max_wait || 600
end

#deferred_max_wait=(seconds) ⇒ Object

Sets the maximum time to wait for a message to be delivered (in seconds). It will be removed of the queue afterwards.



254
255
256
# File 'lib/xmpp4r/observable/helper.rb', line 254

def deferred_max_wait=(seconds)
  @deferred_max_wait = seconds
end

#deliver(jid, message, type = nil) ⇒ Object

Send a message to jabber user jid.

jid

jid of the recipient

message

what is to be delivered (either a string or a Jabber::Message)

type

can be either one of:

* :normal: a normal message.
* :chat (default): a one-to-one chat message.
* :groupchat: a group-chat message.
* :headline: a "headline" message.
* :error: an error message.

If the recipient is not in your contacts list, the message will be queued for later delivery, and the Contact will be automatically asked for authorization (see Jabber::Observable#add).



130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
# File 'lib/xmpp4r/observable/helper.rb', line 130

def deliver(jid, message, type=nil)
  contacts(jid).each do |contact|
    # Check if we're subscribed to contact
    if @subs.subscribed_to?(contact)
      # Yes! we are!
      if message.instance_of?(Jabber::Message)
        msg = message
        msg.to = contact.jid
        msg.type = type unless type.nil?   # Let's keep the Jabber::Message type unless passed
      else
        msg = Jabber::Message.new(contact.jid)
        msg.body = message
        msg.type = type.nil? ? :chat : type
      end
      @delivered_messages += 1
      send!(msg)
    else
      # No... Let's add it and defer the delivery.
      @subs.add(contact.jid)
      deliver_deferred(contact.jid, message, type)
    end
  end
end

#deliver_deferred(jid, message, type) ⇒ Object

Queue messages for delivery once a user has accepted our authorization request. Works in conjunction with the deferred delivery thread.

You can use this method if you want to manually add friends and still have the message queued for later delivery.



247
248
249
250
# File 'lib/xmpp4r/observable/helper.rb', line 247

def deliver_deferred(jid, message, type)
  msg = {:to => jid, :message => message, :type => type, :time => Time.now}
  @deferred_messages.enq msg
end

#dettach_auto_observerObject

Dettach the auto-observer

Raises:

  • (StandardError)


107
108
109
110
111
112
113
114
# File 'lib/xmpp4r/observable/helper.rb', line 107

def dettach_auto_observer
  raise StandardError, "Not attached." if @auto.nil?

  [ :message, :presence, :iq, :new_subscription, :subscription_request, :event ].each do |thing|
    self.delete_observer(thing, @auto)
  end
  @auto = nil
end

#disconnectObject

Use this to force the client to disconnect and not automatically reconnect.



238
239
240
# File 'lib/xmpp4r/observable/helper.rb', line 238

def disconnect
  disconnect!(false)
end

#inspectObject

:nodoc:



74
75
76
# File 'lib/xmpp4r/observable/helper.rb', line 74

def inspect # :nodoc:
  sprintf("#<%s:0x%x @jid=%s, @delivered_messages=%d, @deferred_messages=%d, @observer_count=%s, @notification_count=%s, @pubsub=%s>", self.class.name, __id__, @jid, @delivered_messages, @deferred_messages.length, observer_count.inspect, notification_count.inspect, @pubsub.inspect)
end

#notification_countObject

Count the notifications really sent for each thing



88
89
90
91
92
93
94
# File 'lib/xmpp4r/observable/helper.rb', line 88

def notification_count
  h = {}
  [ :message, :presence, :iq, :new_subscription, :subscription_request, :event ].each do |thing|
    h[thing] = count_notifications(thing)
  end
  h
end

#observer_countObject

Count the registered observers in each thing



79
80
81
82
83
84
85
# File 'lib/xmpp4r/observable/helper.rb', line 79

def observer_count
  h = {}
  [ :message, :presence, :iq, :new_subscription, :subscription_request, :event ].each do |thing|
    h[thing] = count_observers(thing)
  end
  h
end

#reconnectObject

Use this to force the client to reconnect after a disconnect.



231
232
233
234
# File 'lib/xmpp4r/observable/helper.rb', line 231

def reconnect
  @disconnected = false
  connect!
end

#rosterObject

Pass the underlying Roster helper.



193
194
195
196
# File 'lib/xmpp4r/observable/helper.rb', line 193

def roster
  return @roster unless @roster.nil?
  @roster = Jabber::Roster::Helper.new(client)
end

#send!(msg) ⇒ Object

Send a Jabber stanza over-the-wire.

msg

the stanza to be sent.



207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
# File 'lib/xmpp4r/observable/helper.rb', line 207

def send!(msg)
  retries = 0
  max = 4
  begin
    retries += 1
    client.send(msg)
  rescue Errno::ECONNRESET => e
    # Connection reset. Sleep progressively and retry until success or exhaustion.
    sleep ((retries^2) * 60) + 30
    disconnect
    reconnect
    retry unless retries > max
    raise e
  rescue Errno::EPIPE, IOError => e
    # Some minor error. Sleep 2 seconds and retry until success or exhaustion.
    sleep 2
    disconnect
    reconnect
    retry unless retries > max
    raise e
  end
end

#status(presence, message) ⇒ Object

Set your presence, with a message.

presence

any of these:

* nil: online.
* :chat: free for chat.
* :away: away from the computer.
* :dnd: do not disturb.
* :xa: extended away.
message

a string that you wish your contacts see when you change your presence.



163
164
165
166
167
# File 'lib/xmpp4r/observable/helper.rb', line 163

def status(presence, message)
  @status_message = message
  @presence = presence
  send!(Jabber::Presence.new(@presence, @status_message))
end