class OmniBot::JabberBot
Jabber bot with reconnection and dnd-care logic
Attributes
timer_provider[W]
Public Class Methods
new(jid, password)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 144 def initialize(jid, password) @client = Jabber::Client::new(jid) @password = password raise 'No jid set' if jid.empty? raise 'No password set' unless password @ignore_reconnect = false @reconnect_pause = 10 @reconnect_long_pause = 60 * 15 @messages = [] @subscriber_online = false @subscriber_concrete_jid = nil @client.on_exception { |e, stream, sym_where| on_exception_handler(e, stream, sym_where) } @client.add_message_callback { |m| on_message_handler m } @client.add_presence_callback { |from, to| on_presence_callback from, to } end
Public Instance Methods
add_message(message)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 180 def add_message(message) OmniLog::debug 'Register a message, ' + (@subscriber_online ? 'should send immediately' : 'will send later') @messages << message pump_messages if @subscriber_online end
check_presence?(presence)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 104 def check_presence?(presence) raise 'No subscriber' unless @subscriber if presence.type.nil? OmniLog::debug "Subscriber status #{presence.show ? presence.show : 'online'}" return presence.show.nil? || presence.show == :chat elsif presence.type == :unavailable OmniLog::debug 'Subscriber goes offline' return false else return false end end
connect()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 163 def connect try_reconnect end
disconnect()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 167 def disconnect @client.close end
dump_presence(p)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 6 def dump_presence(p) p ? "Presence status=#{p.status} type=#{p.type} show=#{p.show} from=#{p.from} to=#{p.to} xml=(#{p})" : 'nil' end
needed_user?(jid)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 14 def needed_user?(jid) jid.strip == @subscriber && @subscriber_resource.match((jid.resource || '')) end
on_exception_handler(e, stream, sym_where)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 36 def on_exception_handler(e, stream, sym_where) OmniLog::error "Jabber exception of #{e ? e.class : nil} happens at symbol \"#{sym_where}\": #{e}\nbacktrace\n#{Helpers::backtrace e}" OmniLog::debug "stream is #{stream} vs client #{@client}" on_generic_exception_handler e end
on_generic_exception_handler(e)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 53 def on_generic_exception_handler(e) if e && (e.is_a?(Jabber::ServerDisconnected) || e.class.to_s =~ /^Errno::.+/ || e.is_a?(SocketError)) OmniLog::warn "Looking to error, ign=#{@ignore_reconnect}, tp=#{@timer_provider}" OmniLog::error 'No timer provider assigned' unless @timer_provider # attempt counter is set when it's needed to connect unless @ignore_reconnect @timer_provider.add_timer(@reconnect_pause) { try_reconnect } end else OmniLog::warn "Ignoring error #{e}" end end
on_message_handler(m)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 10 def on_message_handler(m) OmniLog::debug "Got jabber message from #{m.from}:\n#{m.body}\n." end
on_presence_callback(old_presence, _new_presence)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 18 def on_presence_callback(old_presence, _new_presence) # OmniLog::debug "Presence changed:\n...old #{dump_presence old_presence}\n...new #{dump_presence new_presence}" return unless needed_user? old_presence.from @subscriber_online = check_presence? old_presence @subscriber_concrete_jid = old_presence.from OmniLog::debug "Subscriber #{@subscriber} is #{@subscriber_online ? 'ready' : 'not ready'}" pump_messages if @subscriber_online unless @greeting_done @greeting_done = true add_message [Time.now, 'Hello, I am online'] end end
on_subscripton_request_callback(item, pres)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 32 def on_subscripton_request_callback(item, pres) OmniLog::debug "Subscription request item=#{item} pres=#{dump_presence pres}" end
pump_messages()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 134 def pump_messages while (msg = @messages.shift) send msg end end
reconnect()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 66 def reconnect OmniLog::debug 'Going to reconnect' @client.connect @client.auth(@password) @client.send(Jabber::Presence.new.set_type(:available)) end
safe_reconnect()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 42 def safe_reconnect reconnect rescue Jabber::ClientAuthenticationFailure => e OmniLog::error "Authentification error: #{e.class}: #{e}" raise rescue Exception => e # rubocop:disable Lint/RescueException # needed to handle all errors from xmpp OmniLog::error "Reconnect hard error: #{e.class}: #{e}" on_generic_exception_handler e end
say_when_human(orig, now)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 118 def say_when_human(orig, now) if Helpers::same_day? now, orig amount = now - orig if amount < 60 return 'just now' elsif amount < 60 * 60 return 'less than a hour ago' elsif amount < 60 * 60 * 2 return ' two hours ago' elsif amount < 60 * 60 * 6 return amount.div(3600).to_s + ' hours ago' end end orig.to_s end
send(message)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 186 def send(message) raise 'Not connected' unless @client.is_connected? raise 'No concrete jid' unless @subscriber_concrete_jid OmniLog::info 'Sending a message...' orig = message[0] content = message[1] body = 'Omnibot reported ' + say_when_human(orig, Time.now) + ":\n" + content.to_s OmniLog::debug body msg = Jabber::Message::new(@subscriber_concrete_jid, body) msg.type = :chat @client.send(msg) end
set_subscriber(jid, resource = nil)
click to toggle source
# File lib/omnibot/jabberbot.rb, line 171 def set_subscriber(jid, resource = nil) @subscriber = jid if resource.nil? || resource == '' @subscriber_resource = /.*/ else @subscriber_resource = Regexp.new(resource) end end
try_reconnect()
click to toggle source
# File lib/omnibot/jabberbot.rb, line 73 def try_reconnect OmniLog::debug "Called try_reconnect, #{@client.inspect}, #{@client.is_connected?}" return if @client.is_connected? OmniLog::debug 'Called try_reconnect' @attempt_counter = AttemptCounter.new(5) unless @attempt_counter @attempt_counter.increase if @attempt_counter.out_of_attempts? OmniLog::warn "Can't reconect too often, sleep for #{@reconnect_long_pause / 60} minutes..." @attempt_counter = nil @ignore_reconnect = true @timer_provider.add_timer(@reconnect_long_pause) do @ignore_reconnect = false try_reconnect end return end safe_reconnect if @client.is_connected? @attempt_counter = nil @roster = Jabber::Roster::Helper.new(@client) @roster.add_subscription_request_callback { |item, pres| on_subscripton_request_callback item, pres } end OmniLog::debug "Client #{@client.is_connected? ? 'is' : 'isn\'t'} connected" end