24.03.2009Jabber бот
Возникла идея написать jabber-бота. Выбор протокола обусловлен тем, что по нему достаточно много документации. И стандарт открытый — это хорошо. Много информации на code.google.com, но я решил пойти более простым путём и нашёл библиотеку на руби xmpp4r. Благодаря тому, что разработка ведется на руби, время разработки простого бота значительно сокращается. Устанавливается как библиотека:
sudo gem i xmpp4r
Регистрация
Это прекрасно, что бот может сам себя зарегистрировать.
require "rubygems"
require "xmpp4r"
include Jabber
client = Client.new(JID.new("login@server"))
client.connect
begin
client.register "secretpassword"
puts "Success!"
rescue ServerError => e
puts "Error: #{e.error.text}"
end
При регистрации можно передавать хэш с параметрами для визитной карточки. После регистрации для последующей авторизации вместо register вызываеься:
client.auth "secretpassword"
Список контактов
Список контактов называется roster. Чтобы с ним работать нужно его запросить:
require "xmpp4r/roster"
roster = Roster::Helper.new(client)
А после этого обработать ответы при обратных вызовах. Если добавлять друзей будет тоже бот, и не будет заморачиваться с группами контактов, то для вывода списка друзей на данный момент достаточно описать вызов:
roster.add_query_callback do |iq|
puts "current roster:"
roster.find_by_group(nil).each do |item|
puts "#{item.jid}"
end
end
Простейшее разрешение видеть свой статус и добавление в контакты в ответ на то, что добавляют бота выглядит так:
roster.add_subscription_request_callback do |item, pres|
puts "Added by #{pres.from}"
roster.accept_subscription(pres.from) # Разрешить видеть свой статус
new_pres = Presence.new.set_type(:subscribe).set_to(pres.from)
client.send(new_pres) # Запросить разрешение видеть статус
end
Теперь наши контакты смогут видеть наш бот онлайн, когда мы сообщаем об этом:
client.send(Presence.new.set_type(:available))
Неплохо бы что-нибудь ещё добавить, типа аватара.
Визитная карточка
Визитная карточка называется vcard:
require "xmpp4r/vcard"
require "base64"
vcard = Vcard::IqVcard.new
vcard["FN"] = "Full Name"
vcard["NICKNAME"] = "bot-nickname"
vcard["PHOTO/TYPE"]= "image/jpeg"
avatar_file = File.new("avatar.jpg", "r")
avatar_b64 = Base64.b64encode(avatar_file.read())
avatar_file.rewind
avatar_sha1 = Digest::SHA1.hexdigest(avatar_file.read())
vcard["PHOTO/BINVAL"] = avatar_b64
avatar_file.close
begin
Vcard::Helper.new(client).set(vcard)
puts "Success!"
rescue Exception => e
puts "VCARD operation failed: #{e.to_s}"
end
В соответствии со спецификацией xmpp относительно аватаров следует транслировать с какой-то периодичностью sha своего аватара:
Thread.new do
while true do
unless avatar_sha1.nil?
pres = Presence.new
x = REXML::Element.new("x")
x.add_namespace("vcard-temp:x:update")
photo = REXML::Element.new("photo")
avatar_hash = REXML::Text.new(avatar_sha1)
photo.add(avatar_hash)
x.add(photo)
pres.add_element(x)
client.send(pres)
end
sleep 60
end
end
Дело за малым.
Ответ на сообщения
cl.add_message_callback do |m|
if m.type != :error and m.body
client.send(m.answer.set_body(bot_main_function(m.body)))
end
end
Внутри bot_main_function находится собственно то, что будет делать ваш бот, как он будет отвечать на то, что написали ему.