Ruby com XMPP enviando e recebendo mensagens

Este é o primeiro post de uma série que pretendo publicar sobre como usar Ruby e o XMPP, protocolo utilizado pelo Google Talk e outros servidores Jabber (que há pouco foi adiquirido pela Cisco).

Primeiramente vou instalar um servidor Jabber, escolhi o Openfire, porém, fique a vontade para instalar qualquer servidor que você queira.

Para fazer o download do Openfire clique aqui.

 

Na interface WEB do Openfire criei alguns usuários, todos dentro de um mesmo grupo chamado test

Criando usuários no Openfire

Criando usuários no Openfire

Importante: todos os usuário aqui, neste exemplo, estão com a senha 123456. Em sistemas que estejam em produção NUNCA faça isso!

Neste exemplo vou utilizar o Pidgin como interface gráfica para ajudar na explicação, mas, novamente, fique a vontade para utilizar qualquer outro aplicativo do gênero.

Caso você não tenha o Pidgin instalado:

 

 shell> sudo apt-get install pidgin

 

 

Com o Pidgin instalado, vou configurá-lo para conectar-me com o usuário: acc

Configurações básicas do Pidgin

Configurações básicas do Pidgin

Configurações avançadas do Pidgin

Configurações avançadas do Pidgin

Vamos agora instalar a gem do Ruby que será sua interface com o XMPP: xmpp4r

 

 shell> sudo gem install xmpp4r

 

 

Feito isso já temos a infra-estrutura pronta para desenvolvermos nosso código.

Este exemplo, abaixo, mostra como funciona o recebimento de mensagem e de envio. O que ele faz basicamente é: ao receber uma mensagem de um outro cliente qualquer via Pidgin, GAIM, IChat, PSI ou mesmo outro cliente que você desenvolveu, ele processa e de acordo com o que foi recebido ele envia uma mensagem de retorno específica. Vejamos:

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
#!/usr/bin/env ruby

require 'rubygems'
require 'xmpp4r'

# Sends to a specific one an arbitrary text message
def my_send_message(body = nil)
  to_jid = Jabber::JID.new('acc@localhost/receive')
  message = Jabber::Message::new(to_jid, body).set_type(:chat)
  @client.send(message)
end

# Process the incoming message body and returns what it is
def process_body(body)
  if body.nil? || body == ''
    nil
  elsif body.match(/\d+/)
    'Number'
  elsif body.downcase.match(/^[aeiou]{1}$/)
    'Vowel'
  elsif body.length == 1
    'Consonant'
  elsif body.downcase == 'quit'
    @quit = span class="kw2">true
    nil
  elsif body.split(/\s/).size > 1
    'Phrase'
  else
    'Word'
  end
end

@quit = false

# Connect to Jabber server. The neo@localhost/Home means:
# 'node'@'domain'/'resource'
# node: user ID
# domain: What organization user is part
# resource: Where user is; work, home, coffee, restaurant ...
@client = Jabber::Client.new(Jabber::JID.new('neo@localhost/Home'))
@client.connect('localhost', '5222')
@client.auth('123456')
@client.send(Jabber::Presence.new.set_type(:available))

# Adding threaded callback, dispatched on every  new incoming
# message
@client.add_message_callback do |message|
  begin
    response = process_body(message.body)
    unless response.nil?
      puts "Message from #{message.from}: #{message.body}"
      puts "Response: #{response}"
      puts '---'
      my_send_message(response)
    end
  rescue Exception => exception
    puts exception.to_s
  end
end

# HACK: this thread is just to keep the application running.
# When the "quit" message arrives the @quit variable is setted
# to "true". So, it closes the thread, also closes the user
# connection and finishes the application gracefully.
main_thread = Thread.new {
  while !@quit do
  end
}
main_thread.join

@client.close
puts 'Bye'

Salve o código ruby acima e execute-o:

 

 shell> ruby auto_chat.rb

 

 

Observe agora seu cliente gráfico (Pidgin?)

Usuário conectado

Usuário conectado

Abra uma janela com o usuário online, começe o enviar mensagens e veja as respostas automáticas do código ruby que fizemos:

Chat de respostas automáticas com Ruby e XMPP

Chat de respostas automáticas com Ruby e XMPP