12/08/2018, 13:22

Tìm hiểu về XMPP và gem XMPP4R

Extensible Messaging and Presence Protocol (XMPP), trước đây là Jabber, là giao thức mở và dựa trên nền tảng XML dùng trong nhắn tin nhanh (instant messaging) và thông tin hiện diện trực tuyến (presence information). - Wikipedia Extensible Messaging and Presence Protocol (XMPP) là một công ...

XMPP.png

Extensible Messaging and Presence Protocol (XMPP), trước đây là Jabber, là giao thức mở và dựa trên nền tảng XML dùng trong nhắn tin nhanh (instant messaging) và thông tin hiện diện trực tuyến (presence information). - Wikipedia

Extensible Messaging and Presence Protocol (XMPP) là một công nghệ mở cho truyền thông thời gian thực, nó cung cấp một loạt các ứng dụng bao gồm nhắn tin, trình diễn, hội thoại nhóm, gọi điện và video trực tuyến, nội dung cung cấp thông tin, và tuyến dữ liệu XML. - Xmpp.org

eXtensible Messaging and Presence Protocol, còn được gọi là Jabber (giao thức ban đầu được đặt tên là Jabber và được phát triển bởi cộng đồng mã nguồn mở Jabber) là một giao thức để trao đổi tin nhắn giữa 2 đối tượng. Những thông điệp được truyền qua mạng với định dạng XML. Nó được sử dụng bởi Jabber, Google Talk, Google Wave, Pidgin, Kopete, và tất cả các loại ứng dụng tin nhắn tức thời nguồn mở.

Ưu điểm của XMPP

Phân cấp

Các mạng XMPP được phân cấp một cách tự nhiên. Không có máy chủ hoặc máy chủ trung tâm. Bất kỳ ai có thể sở hữu hoặc chạy một XMPP Server.

Các chuẩn mở

Internet Engineering Task Force đã chính thức phê duyệt XMPP như một chuẩn tin nhắn thời gian thực và công nghệ hiện diện dưới tên của XMPP (thông số kỹ thuật mới nhất là RFC 6120 và RFC 6121). Không có yêu cầu tiền bản quyền nào để thực hiện hỗ trợ các thông số kỹ thuật và phát triển, XMPP không được gắn với một nhà cung cấp duy nhất.

Ổn định và an toàn

XMPP đã có hiệu lực từ năm 1999 và nhiều ứng dụng đã sử dụng giao thức này kể từ đó. Kể từ khi máy chủ XMPP có thể được thiết đặt độc lập hoặc được lưu trữ trên một mạng riêng ở phía sau bức tường lửa, đảm bảo an toàn.

Linh hoạt

Một trong những lợi thế chính của giao thức này là sự linh hoạt của nó. Chức năng tùy chỉnh có thể được thiết đặt ở phần đầu của XMPP rất dễ dàng. Bản chất linh hoạt của giao thức làm cho XMPP là sự lựa chọn hoàn hảo để viết IM bots, chat client vv,... XMPP sẽ tự động làm việc với tất cả các dịch vụ IM XMPP đã cung cấp.

XMPP4R - Thư viện client Ruby cho XMPP

XMPP4R là một thư viện XMPP / Jabber cho Ruby. Mục tiêu của nó là để cung cấp một khuôn khổ toàn diện để phát triển các ứng dụng Jabber liên quan đến hoặc các kịch bản trong Ruby.

Cài đặt

gem install xmpp4r

hoặc

sudo gem install xmpp4r

Máy chủ XMPP

Ejabberd là một máy chủ Jabber / XMPP xây dựng sử dụng Erlang và là mã nguồn mở. Một lựa chọn phổ biến cho ejabberd là Openfire. Hướng dẫn cài đặt cho ejabbered có thể được tìm thấy ở đây . Vì việc cài đặt và config một server như ejabbered hoặc Openfire tương đối phức tạp, nên trong ví dụ này chúng ta sẽ sử dụng một tài khoản Google để kết nối.

XMPP Bot

Xây dựng một Bot là một cách lý tưởng để giới thiệu các giao thức XMPP và Wrapper Ruby cho XMPP - XMPP4R. Như vậy, chúng ta sẽ xây dựng một bot để xử lý các thông điệp và trả lời các thông điệp tùy chỉnh hoặc kết quả.

Cài đặt Gem

gem install xmpp4r

Kết nối đến máy chủ Jabber

require 'xmpp4r'
require 'xmpp4r/client'
include Jabber

class Bot

  attr_reader :client

  def initialize jabber_id
    @jabber_id = jabber_id
    @jabber_password = ENV['jabber_password']
  end

  def connect
    jid = JID.new(@jabber_id)
    @client = Client.new jid
    @client.connect
    @client.auth @jabber_password
    @client.send(Presence.new.set_type(:available))
    puts "Hurray...!!  Connected..!!"
  end
end

Bot.new('neo@codingarena.in').connect

Đoạn mã trên cho thấy làm thế nào để kết nối với máy chủ Jabber, hoặc trong trường hợp của chúng ta là các máy chủ của Google. Jabber ID được cung cấp khi khởi tạo một Bot và mật khẩu được lấy ra từ một biến môi trường. Các kết nối tạo ra một đối tượng mới của Jabber, kết nối đến máy chủ, và xác thực bằng cách sử dụng mật khẩu theo quy định. Ngoài trạng thái được đặt là available. Các tùy chọn khác có thể được thông qua là :busy, :invisible.

Gửi và nhận tin nhắn

Gửi một tin nhắn là đơn giản như sau:

message = Message.new("manu@codingarena.in", "Hello... Manu?")
message.type=:chat
@client.send(message)

Các phương thức add_method_callback có thể được sử dụng cho nhận và xử lý các thông điệp mà bot nhận được.

@client.add_message_callback do |message|
  unless message.body.nil? && message.type != :error
    puts "Received message: #{message.body}"
    #Echo the received message back to the sender.
    reply = Message.new(message.from, message.body)
    reply.type = message.type
    @client.send(reply)
  end
end

Chấp nhận lời mời mới

def roster
  @roster ||= Roster::Helper.new(@client)
end

def process_invite
  roster.add_subscription_request_callback do |_, presence|
    inviter = JID::new(presence.from)
    roster.accept_subscription(inviter)
    invite(JID::new(inviter))
  end
end

Roster là danh sách liên lạc của bot. Bất cứ khi nào một người sử dụng mới được bổ sung vào bot và gửi một lời mời, roster_add_subscription_request_callback được kích hoạt sẽ tự động chấp nhận lời mời mới.

Dạy bot một số lệnh

Sau khi xây dựng một bot đơn giản và cơ bản sử dụng XMPP, bây giờ chúng ta sẽ cố gắng để xử lý các tin nhắn nhận được bằng bot và xem xét xung quanh một chút.

Làm thế khi chúng ta yêu cầu bot một số câu hỏi hay câu lệnh và xem nếu nó đáp ứng thông điệp của chúng ta với các tùy chỉnh hoặc trả lời xử lý? Với một số tin nhắn nhận được, bot có thể được xử lý theo cách thực hiện một số câu lệnh cụ thể. Ví dụ, khi bot nhận được tin nhắn Help nó sẽ trả lại tất cả các lệnh mà bot của chúng tôi biết hoặc Time để trả lại thời gian hiện tại.

@client.add_message_callback do |message|
  unless message.body.nil? && message.type != :error
    reply = case message.body
      when "Time" then reply(message, "Current time is #{Time.now}")
      when "Help" then reply(message, "Available commands are: 'Time', 'Help', 'Latest sitepoint articles.")
      when "Latest sitepoint articles" then latest_sitepoint_articles(message)
      else reply(message, "You said: #{message.body}")
    end
  end
end

def reply message, reply_content
  reply_message = Message.new(message.from, reply_content)
  reply_message.type = message.type
  @client.send reply_message
end

def latest_sitepoint_articles message
  feeds = SitepointFeedParser.get_feeds
  feeds.items.each do |item|
    reply(message, item.link)
  end
end

class SitepointFeedParser
  URL = 'http://www.sitepoint.com/feed/'
  class << self
    def get_feeds
      open(URL) do |rss|
        @feeds = RSS::Parser.parse(rss)
      end
      @feeds
    end
  end
end

Khi người dùng gửi Latest sitepoint articles bot sẽ phân tích các feeds sitepoint.com và trả lại các liên kết đến các bài viết mới nhất. Các module RSS được sử dụng cho phân tích feeds, được kiểm tra và trả về các liên kết cho người sử dụng.

Daemonize Bot

require 'rubygems'
require 'daemons'

Daemons.run('bot.rb',
  {
    app_name: 'myIMBot',
    monitor: true,
    log_output: false
  }
)

Sử dụng daemons gem, chúng ta chạy bot như là một dịch vụ nền. Nó cũng cho chúng ta lựa chọn để start, restart, và stop các daemon bằng cách gọi lệnh ruby im.rb start, ruby im.rb restart, và ruby im.rb stop. Chúng ta có thể có được tình trạng hiện tại của các daemon sử dụng ruby im.rb status.

Ngoài ra, monit cho chúng ta lựa chọn để giám sát các daemon. Đầu ra của daemon có thể được đăng nếu log_output được thiết lập là true.

Kết hợp tất cả chúng với nhau

require 'xmpp4r'
require 'xmpp4r/client'
require 'xmpp4r/roster'
require 'rss'
require 'open-uri'
include Jabber

class Bot

  attr_reader :client

  def initialize jabber_id
    @jabber_id = jabber_id
    @jabber_password = ENV['jabber_password']
  end

  def connect
    jid = JID.new(@jabber_id)
    @client = Client.new jid
    @client.connect
    @client.auth @jabber_password
    @client.send(Presence.new.set_type(:available))
    puts "Hurray...!!  Connected..!!"
    on_message
  end

  private
  def on_message
    mainthread = Thread.current
    @client.add_message_callback do |message|
      unless message.body.nil? && message.type != :error
        reply = case message.body
          when "Time" then reply(message, "Current time is #{Time.now}")
          when "Help" then reply(message, "Available commands are: 'Time', 'Help'.")
          when "Latest sitepoint articles" then latest_sitepoint_articles(message)
          else reply(message, "You said: #{message.body}")
        end
      end
    end
    Thread.stop
    @client.close
  end

  def reply message, reply_content
    reply_message = Message.new(message.from, reply_content)
    reply_message.type = message.type
    @client.send reply_message
  end

  def latest_sitepoint_articles message
    feeds = SitepointFeedParser.get_feeds
    feeds.items.each do |item|
      reply(message, item.link)
    end
  end

end

class SitepointFeedParser

  URL = 'http://www.sitepoint.com/feed/'
  class << self
    def get_feeds
      open(URL) do |rss|
        @feeds = RSS::Parser.parse(rss)
      end
      @feeds
    end
  end

end

@bot = Bot.new 'manusajith@gmail.com'
@bot.connect

Mã này có thể được tìm thấy ở đây .

Phần kết luận

Nếu bạn chưa từng sử dụng XMPP hoặc XMPP4R, tôi đề nghị bạn nên thử một lần. XMPP4R có rất nhiều lựa chọn khác không được đề cập trong hướng dẫn này. Vui lòng kiểm tra trang web chính thức để biết thêm chi tiết.

Bài được dịch từ bài viết của Manu Ajith: Looking at XMPP and the XMPP4R Gem

0