Skip to content

Instantly share code, notes, and snippets.

@mtungusov
Created September 20, 2013 12:03
Show Gist options
  • Select an option

  • Save mtungusov/6636470 to your computer and use it in GitHub Desktop.

Select an option

Save mtungusov/6636470 to your computer and use it in GitHub Desktop.
XMPP client
require 'xmpp4r'
require 'xmpp4r/roster'
module XmppExtension
# class Jabber::JID
# # generate node@domain
# def to_short_s
# s = []
# s << "#@node@" if @node
# s << @domain
# return s.to_s
# end
# end
class ChatMessage < Struct.new(:from, :to, :body, :guid, :send_time); end
class DbWorker
include Celluloid
def save_message(user_id, interlocutor_id, message, direction='to')
msg = Message.write_message_by_users(user_id, interlocutor_id, message, direction)
# Send to websocket
if direction == 'from'
message_send_time = Time.now.strftime "%b %d, %I:%m%p"
WebsocketRails[:messages].trigger 'new_message', ChatMessage.new(interlocutor_id, user_id, message, msg.guid.to_s, message_send_time)
end
end
end
# class WebsocketWorker
# include Celluloid
# def new_message(from, to, body)
# WebsocketRails[:messages].trigger 'new_message', ChatMessage.new(from, to, body)
# end
# end
class XmppClient
include Celluloid
attr_reader :messages, :unread, :friends_online, :roster, :jid
def initialize(username, password, priority=0)
# Jabber::debug = true
@password = password
@priority = priority #Priority value between -128 and +127
# @messages = {}
@unread = {}
@friends_online = {}
@db_worker = DbWorker.new
# @ws_worker = WebsocketWorker.new
connect(username, password)
if @client.is_connected?
listen_for_subscription_requests
listen_for_presence_notifications
listen_for_messages
send_initial_presence
end
end
def connect(username, password)
@jid = Jabber::JID.new(username)
@client = Jabber::Client.new(@jid)
@client.connect
@client.auth(password)
rescue
disconnect
end
def disconnect
@client.close
@db_worker.terminate if @db_worker.alive?
# @ws_worker.terminate if @ws_worker.alive?
end
def is_connected?
@client.is_connected?
end
# def messages_from(user_id)
# result = []
# if @messages.key? user_id
# messages = @messages[user_id]
# until messages.empty?
# result << messages.shift
# end
# end
# @unread[user_id] = 0
# result
# end
# def message_count_by(user_id)
# @messages.key?(user_id) ? @messages[user_id].count : 0
# end
def send_message(user, host, body)
if @client.is_connected?
@client.send(Jabber::Message::new("#{user}@#{host}", body).set_type(:chat))
# Save to hash
# @messages[user.to_i] = [] unless @messages.key? user.to_i
# @messages[user.to_i] << ['to', body]
# Send to websocket
# @ws_worker.async.new_message(@jid.node, user.to_s, body)
# Save to DB
@db_worker.async.save_message(@jid.node, user, body)
else
raise 'xmpp is not connected'
end
end
def subscribers
result = []
@roster.items.keys.each { |k| result << k.node }
result
end
private
def listen_for_subscription_requests
@roster = Jabber::Roster::Helper.new @client
@roster.add_subscription_request_callback do |item, pres|
if pres.from.domain == @jid.domain
log "ACCEPTING AUTHORIZATION REQUEST FROM: " + pres.from.to_s
@roster.accept_subscription(pres.from)
# send subscription request
@client.send(Jabber::Presence.new.set_type(:subscribe).set_to(pres.from))
# send welcome
# @client.send(Jabber::Message::new(pres.from, 'Welcome!'))
# update UserChats table
end
end
end
def listen_for_presence_notifications
@client.add_presence_callback do |m|
case m.type
when nil # status: available
log "PRESENCE: #{m.from.node} is online"
@friends_online[m.from.node] = true if m.from.node != @jid.node
when :unavailable
log "PRESENCE: #{m.from.node} is offline"
@friends_online[m.from.node] = false
end
end
end
def listen_for_messages
@client.add_message_callback do |m|
m_type = m.type
m_body = m.body
log [m_type.to_s, m_body].join(": ") if m_type == :error
if m_type == :chat
# @messages[from.to_i] = [] unless @messages.key? from.to_i
unless m_body.nil?
if @client.is_connected?
user_id = @jid.node
from = m.from.node
# Save to hash
# @messages[from.to_i] << m.body
# @messages[from.to_i] << ['from', m.body]
@unread[from.to_i] = @unread[from.to_i].to_i.next
# Send to websocket
# @ws_worker.async.new_message(from, user_id, m_body)
# Save message to DB
@db_worker.async.save_message(user_id, from, m_body, 'from')
end
end
end
end
end
def send_initial_presence
@client.send(Jabber::Presence.new.set_status("#{@jid.node} online").set_priority(@priority))
end
def log(message)
puts(message) if Jabber::debug
end
end
class XmppRegistrator
def self.register_user(username, password)
jid = Jabber::JID.new(username)
cl = Jabber::Client.new(jid)
cl.connect
cl.register(password)
log "Successful"
rescue Jabber::ServerError => e
log "Error: #{e.error.text}"
ensure
cl.close
end
def self.log(message)
puts(message) if Jabber::debug
end
end
end
# Jabber::ClientAuthenticationFailure
# Jabber::ServerError: conflict
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment