Pull to refresh

Jabber-бот для Openfire за час

Reading time10 min
Views16K


Вот уже порядка двух лет я занимаюсь разработкой ботов для ICQ. После ряда недавних событий, из-за которых ICQ-боты часто оказывались неработоспособными, а также после статьи Знакомство с jabber ботами, у меня возникло стойкое желание изучить вопросы, связанные с разработкой ботов для Jabber.
В данном посте я хочу поделиться с вами своим первым опытом в данной области. Расскажу как с нуля, потратив всего один час времени, написать простого Jabber-бота.
В качестве платфомы для разработки бота я выбрал Openfire. На выбор повлияло то, что Openfire написан на Java (изучать что-нибудь типа Python совершенно не хотелось). Плагинная структура Openfire позволяет быстро и удобно прикрутить к нему функционал бота. Кроме того, Openfire прост в настройке, и к тому времени уже был установлен в качестве моего jabber-сервера.

Устанавливаем окружение


Для начала необходимо установить окружение для разработки, которое позволит строить и запускать Openfire и плагины к нему. Здесь приведен процесс установки под Windows. На других ОС процесс должен выглядеть примерно так же.
  1. Качаем и устанавливаем Java SE Development Kit (JDK). Взять можно тут. Я установил JDK в C:\Program Files\Java (папка по-умолчанию). После установки в C:\Program Files\Java появились подпапки jdk1.6.0_12 и jre6.
  2. Качаем Eclipse IDE for Java Developers отсюда. Распаковываем в ту же папку C:\Program Files\Java. В результате там появится еще одна подпапка – eclipse.
  3. Устанавливаем переменные окружения (это делается через My Computer > Properties > Advanced > Environment Variables):
    • JAVA_HOME = C:\Program Files\Java\jdk1.6.0_12. Если вы распаковали JDK в другую папку, указывайте соответствующий путь.
    • В переменную Path дописываем C:\Program Files\Java\jre6\bin (тоже проверьте правильность пути).
  4. Перезагружаемся.
  5. Запускаем Eclipse, который попросит выбрать Workspace, или, другими словами, каталог, в котором будут находиться проекты. Допустим, что это будет С:\Edit. После выбора Workspace появится Welcome screen, его можно сразу закрыть.

Строим Openfire


Теперь приступаем ко второму этапу – построению и запуску Openfire. Постарайтесь в точности следовать инструкции, иначе велика вероятность что ничего сразу работать не будет:
  1. Качаем исходники Openfire отсюда. Кроме непосредственно Openfire, архив содержит исходники для всех бесплатных плагинов. При разработке своего плагина можно будет смотреть в их код.
  2. Архив с исходниками содержит папку openfire_src. Распаковываем её в С:\Edit.
  3. Идем в Eclipse, создаем новый проект по данным исходниками. Для этого выбираем в меню File > New > Project > Java Project. Появится окно создания нового Java-проекта. Пишем в нем следующее:
    • Project name = openfire_src.
    • Отмечаем Create project from existing source. В Directory указываем С:\Edit\openfire_src.
    • Жмем Finish.
  4. После того как Eclipse создаст проект, настанет время его собрать. Для этого выбираем в меню Window > Show view > Ant. В рабочей зоне Eclipse появится панель Ant. Щелкаем по ней правой кнопкой мыши, в ниспадающем меню выбираем Add Buildfiles.
  5. В появившемся дереве выбираем openfire_src > build > build.xml. Жмем OK.
  6. В панели Ant появляется Openfire XMPP server со множеством вариантов сборки.
  7. Собираем Openfire. Для этого находим в дереве вариант сборки с названием openfire [default] и дважды щелкаем по нему. Можно также просто щелкнуть по корневому элементу дерева.
  8. Спустя небольшое время после запуска сборки, Eclipse должен показать консоль, в которой будет появляться информация о ходе сборки. Ждем появления надписи BUILD SUCCESSFUL.
  9. Теперь настраиваем параметры запуска Openfire, для этого идем в меню Run > Run configurations.
  10. В появившемся окне дважды щелкаем по Java application. Создается новая конфигурация, теперь её нужно настроить для правильного запуска нашей сборки. Пишем следующее:
    • Name = Openfire (или любое другое, не важно).
    • Project = openfire_src.
    • Main class = org.jivesoftware.openfire.starter.ServerStarter.
    • На закладке Arguments в VM arguments пишем -DopenfireHome=«target/openfire». Обратите внимание на отсутствие пробела после -D.
    • На закладке Classpath выбираем User entries и нажимаем кнопку Advanced. Выбираем Add folders и добавляем папку openfire_src\src\i18n. После этого таким же образом добавляем папку openfire_src\src\resources\jar.
    • Жмем Apply, затем Run.

Если все сделано правильно, то в консоли появится строчка с версией Openfire и сообщение о том, что консоль администратора слушает на порту 9090. Теперь можно сходить за кофе, так как основная часть работы уже позади. Можно также мысленно посочуствовать тем, у кого заветная надпись в консоли не появилась. Обращаясь к последним – внимательно проверьте последовательность своих действий. Как я предупреждал ранее, инструкцию нужно выполнять в точности, ничего лишнего не делать.

Настраиваем Openfire


Продолжаем. Теперь необходимо настроить сам сервер Openfire. Вводим в браузере localhost:9090, после чего запустится процедура настройки. Здесь все достаточно тривиально. Так как мы устанавливаем конфигурацию для разработки, то особо мудрствовать не будем:
  • На странице Server Settings выставляем server name = localhost, порты по-умолчанию.
  • На странице Database Settings выбираем Embedded Database.
  • На странице Profile Settings оставляем все по-умолчанию.
  • На странице Administrator Account – вводим любой несуществующий почтовый ящик. Также вводим и запоминаем пароль администратора.

После этого можно выбрать Login to the admin console и перейти на страницу авторизации. Заходить нужно под учетной записью admin с указанным ранее паролем. Также можно попробовать подключиться к нашему серверу любым jabber-клиентом под тем же admin. Если все нормально, то можно останавливать сервер и переходить к следующему этапу.

Пишем бота


Вот мы и добрались до самого главного этапа. Теперь мы должны написать плагин, который будет реализовывать функции бота.
Все исходники Openfire-плагинов расположены в папке openfire_src\src\plugins. Для каждого плагина там есть отдельная папка, в которой как минимум находится файл plugin.xml с описанием плагина и Java-файл с описанием основного класса плагина. Дополнительная информация есть в документации по Openfire (загляните к примеру в openfire_src\documentation\docs\plugin-dev-guide.html).
Создаем папку для нового плагина: openfire_src\src\plugins\simplebot. В ней заводим файл plugin.xml, в который пишем следующее:

<?xml version="1.0" encoding="UTF-8"?><br><br><plugin><br>  <class>org.jivesoftware.openfire.plugin.simplebot</class><br>  <name>Simple Bot</name><br>  <description>Provides simple bot functionality.</description><br>  <author>Habrahabr</author><br>  <version>1.0.0</version><br>  <date>18/2/2009</date><br>  <minServerVersion>3.5.0</minServerVersion><br></plugin><br><br><br>* This source code was highlighted with Source Code Highlighter.


Теперь нужно создать папку, в которой будет лежать исходник плагина. Точнее это будет целая серия вложенных папок: openfire_src\src\plugins\simplebot\src\java\org\jivesoftware\openfire\plugin. Так как у каждого Openfire-плагина путь к основному классу всегда одинаковый, я не стал создавать все эти папки вручную, а просто скопировал их из плагина MOTD, затем удалил из них старое содержимое.
Последнее что нужно сделать, это в папку openfire_src\src\plugins\simplebot\src\java\org\jivesoftware\openfire\plugin поместить исходник бота. Для этого создаем там файл simplebot.java (регистр важен) и копируем в него исходный код:

package org.jivesoftware.openfire.plugin;<br><br>import java.io.File;<br>import org.jivesoftware.openfire.container.Plugin;<br>import org.jivesoftware.openfire.container.PluginManager;<br>import org.jivesoftware.openfire.XMPPServer;<br>import org.jivesoftware.openfire.auth.AuthToken;<br>import org.jivesoftware.openfire.multiplex.ClientSessionConnection;<br>import org.jivesoftware.openfire.SessionManager;<br>import org.jivesoftware.openfire.SessionPacketRouter;<br>import org.jivesoftware.openfire.session.Session;<br>import org.jivesoftware.openfire.session.LocalClientSession;<br>import org.jivesoftware.openfire.interceptor.*;<br>import org.xmpp.packet.*;<br><br>//<br>// Simple Bot Plugin<br>//<br>public class simplebot implements Plugin {<br><br>  private JID myJID;<br>  private LocalClientSession mySession;<br>  private myPacketInterceptor myInterceptor = new myPacketInterceptor();<br><br>  public void initializePlugin(PluginManager manager, File pluginDirectory) {<br>    System.out.println("Starting Simple Bot Plugin");<br>    <br>    myJID = new JID("test", XMPPServer.getInstance().getServerInfo().getXMPPDomain(), "simplebot");<br>    <br>    ClientSessionConnection connection = <br>      new ClientSessionConnection(XMPPServer.getInstance().getConnectionManager().getClass().getName(),<br>          "localhost", "127.0.0.1");<br>    mySession = SessionManager.getInstance().createClientSession(connection);<br>    mySession.setAuthToken(new AuthToken(myJID.getNode()), myJID.getResource());<br>    <br>    InterceptorManager.getInstance().addInterceptor(myInterceptor);<br>  } // initializePlugin<br><br>  public void destroyPlugin() {<br>    // Resources are no longer needed<br>    InterceptorManager.getInstance().removeInterceptor(myInterceptor);<br>    mySession.close();<br><br>    myJID = null;<br>    mySession = null;<br>    myInterceptor = null;<br>  } // destroyPlugin<br>  <br>  private class myPacketInterceptor implements PacketInterceptor {<br>    <br>    public void interceptPacket(Packet packet,<br>        Session session,<br>        boolean incoming,<br>        boolean processed) throws PacketRejectedException<br>        {<br>            // If there is an incoming message for the bot<br>            if (packet instanceof Message &&<br>              packet.getTo().getNode().equals(myJID.getNode()) &&<br>              incoming == true &&<br>              processed == true)<br>            {<br>              // Create the response ...<br>              Message message = new Message();<br>              message.setTo(packet.getFrom());<br>              message.setFrom(packet.getTo());<br>              message.setSubject("");<br>              message.setBody("Hello from Simple OpenFire Bot");<br>              <br>              // ... and send it<br>              SessionPacketRouter router = new SessionPacketRouter(mySession);<br>              router.route(message);<br>            }<br>        } // interceptPacket<br>    <br>  } // myPacketInterceptor<br><br>} // simplebot<br><br><br>* This source code was highlighted with Source Code Highlighter.


Сразу замечу, что это минимальный объем рабочего кода, которого мне удалось добиться. Выкинуты все дополнительные функции и все проверки. Бот не умеет менять свой статус, не умеет авторизовать пользователей. Зато он стабильно отвечает на все входящие сообщения фразой “Hello from Simple OpenFire Bot”.
Давайте немного разберем как он работает. Основной класс плагина представляет собой реализацию интерфейса Plugin с двумя функциями внутри:
  • initializePlugin – инициализирует плагин при его запуске. Здесь мы инициализируем переменную myJID, которая будет содержать JID бота вида test@domain\simplebot. При запуске на localhost это соответственно будет test@localhost\simplebot. Далее мы создаем новую сессию для нашего JID. Для этого необходимо установить подключение к серверу (connection) и в рамках этого подключения создать сессию (mySession). В заключении необходимо выполнить авторизацию нашего пользователя в этой сессии.
  • destroyPlugin – вызывается при уничтожении плагина. Здесь мы освобождаем все ранее захваченные ресурсы.

Кроме того основной класс плагина содержит вспомогательный класс myPacketInterceptor, реализующий интерфейс PacketInterceptor. Данный класс отвечает за перехват всех сообщений, которые проходят через сервер Openfire (для этого внутри initializePlugin мы подписываем экземпляр этого класса на перехват сообщений используя InterceptorManager). Теперь при появлении любого сообщения будет вызываться функция interceptPacket из этого класса. Все что нам остается сделать, это внутри этой функции выделять сообщения, адресованные нашему JID и отвечать на них фразой «Hello from Simple OpenFire Bot».
Теперь нужно собрать наш плагин, а затем запустить Openfire. Для того чтобы собрать плагин (а также все прочие плагины), нужно в панели Ant дважды щелкнуть по таргету plugins (не перепутайте с plugin). Затем дождаться появления в консоли надписи BUILD SUCCESSFUL. Теперь при запуске Openfire в консоли кроме всего прочего должна появиться надпись Starting Simple Bot Plugin.
Ну вот и все, сейчас можно подключиться к серверу любым jabber-клиентом (используя учетную запись admin) и написать какое-нибудь сообщение на test@localhost чтобы проверить работу бота.

Что дальше?


Как уже отмечалость ранее, описанный здесь бот наделен самой скромной функциональностью. В настоящее время я добавляю к нему дополнительные функции, и планирую написать целую серию заметок об этом.
В любом случае, надеюсь на то, что донес мысль о том, что разработка jabber-бота на самом деле не такое сложное дело, как может показаться на первый взгляд.
Tags:
Hubs:
Total votes 19: ↑16 and ↓3+13
Comments9

Articles