Created
September 20, 2013 12:03
-
-
Save mtungusov/6636470 to your computer and use it in GitHub Desktop.
XMPP client
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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