XMPP для самых маленьких

в 3:54, , рубрики: irc, jabber, XML, xmpp, Программирование, метки: , ,

Дорогой дневник,

IRC отмирает, — кто-то уходит в социальные сети с концами, кто-то сменяет IRC на Jabber. На протяжении 6 лет моим хобби было написание mIRC бота (это как Emacs, только чат, но с таким же потенциалом для обвешивания его разным функционалом), но каналы опустели и теперь стало писать не для кого.
А писал я, позвольте похвастаться, многое — реализации HTTP, FTP, IRC серверов, Feed агрегатор, игры для IRC, и просто различные утилиты, которые выполняли рутинную задачу и делали жизнь легче. Все это — на чистом mIRC Scripting Language.

С потерей популярности IRC я не хочу отказываться от чатов и тоже перешел на Jabber, но в конференциях без своего бота, который предоставляет кучу полезных фич и развлекает посетителей — совсем не то. Поэтому я решил написать реализацию XMPP клиента, и для тех, кому это тоже может быть полезно — сделал шпаргалку, с описанием основных команд. По ней вы, используя любой любимый ЯП, в котором нет библиотек для XMPP, — да даже просто используя telnet, сможете сидеть в Jabber'е. Сравнивать я буду с IRC.

Подключение (USER)

При открытии сокета с IRC сервером клиент сразу «регистрируется», указывая ник, идент и имя. При наличии пароля на сервере — нужно указать и его, но команда PASS не обязательна.

PASS password
USER username * * :realname
NICK nickname

Ничего сложного нет и в XMPP, только здесь все описано XML-тегами, а суть остается одна и та же. Подключаться нужно к серверу, на котором у вас предварительно создан Jabber-аккаунт, указывая логин, пароль и ресурс (например название клиента или места, откуда вы подключаетесь). Так же, просто меняя имя ресурса, с одного аккаунта можно иметь несколько подключений одновременно.

<stream:stream xmlns:stream='http://etherx.jabber.org/streams' to='server' xmlns='jabber:client'>
  <iq type='set'>
    <query xmlns='jabber:iq:auth'>
      <username>username</username>
      <password>password</password>
      <resource>resource</resource>
    </query>
  </iq>

server, username, password, resource — замените на свое. Некоторые серверы умеют в шифрование пароля, т.е. если вы подключаетесь не через SSL/TLS, то лучше оберните пароль в md5, но я например использую сервер talk.google.com:5223 и не беспокоюсь об этом.

После чего — добро пожаловать в мир Jabber, здесь нет обязательного PING как в IRC, и вы уже можете на свой аккаунт написать что-нибудь из любого клиента, и увидите это на трафике (если используете telnet или типа того).

Заходим на канал (JOIN)

В IRC это выглядило как просто JOIN #channel password, в XMPP чуть больше текста, но суть не меняется.

  <presence to='channel@conference.server/nickname'>
    <x xmlns='http://jabber.org/protocol/muc#user'>
      <password />
    </x>
  </presence>

channel, server, nickname — заменить на свое, password опционален и может быть включен в тег <password>password</password>

И вот вы уже в конференции, испугались большого количества полученного XML, но это всего-лишь

  • Список пользователей, аналог команды NAMES #channel в IRC (вы так же получаете их при заходе на канал).
  • Последние несколько сообщений, которые написали перед вашим заходом. В IRC такого нет.
  • Тема конференции, аналог TOPIC
  • И все остальное — уже живой чат в реальном времени, все похоже на IRC.

Отправка сообщений (PRIVMSG)

Аналог PRIVMSG #channel/nickname : сообщение, только здесь оно определяется типом groupchat (в канал) или chat (пользователю), и в зависимости от того, кому направлено сообщение — нужно правильно указать адрес (to).

  <message to='channel@conference.server' type='groupchat'>
    <body>message</body>
  </message>

Заодно добавлю, что смена темы (команда TOPIC в IRC) конференции делается просто заменой тега body на тег subject. А еще, не забудьте, чтобы содержимое вашего сообщение было валидным для XML, то есть замените все < на &lt;, > на &gt;, & на &amp; и т.д.

И это пожалуй самый минимум, который необходим, — находиться в чате, парсить сообщения и отвечать на них. Далее, изучая протокол сами вы без труда сможете написать полноценный клиент для себя или любую другую простую его реализацию, моей же задачей было вернуть бота из IRC в Jabber.

Покинуть канал (PART)

Вы отправляете обновление присутствия самому себе на канале, обязательно указывая тип unavailable и таким образом покидаете канал. При необходимости можно указать сообщение выхода.

  <presence to='channel@conference.server/nickname' type='unavailable'>
    <status>message</status>
  </presence>

Сменить ник (NICK)

  <presence to='channel@conference.server/newnickname'/>

Пригласить пользователя (INVITE)

Так же как и в IRC, указав Jabber-аккаунт пользователя (jid), можно пригласить его в конференцию.

  <message to='channel@conference.server'>
    <x xmlns='http://jabber.org/protocol/muc#user'>
      <invite to='jid'>
        <reason>message</reason>
      </invite>
    </x>
  </message>

Забанить пользователя (MODE #channel +b)

  <iq id='id' to='channel@conference.server' type='set'>
    <query xmlns='http://jabber.org/protocol/muc#admin'>
      <item affiliation='outcast' jid='jid'>
        <reason>message</reason>
      </item>
    </query>
  </iq>

Кикнуть пользователя (KICK)

  <iq id='id' to='channel@conference.server' type='set'>
    <query xmlns='http://jabber.org/protocol/muc#admin'>
      <item nick='nickname' role='none'>
        <reason>message</reason>
      </item>
    </query>
</iq>

И пожалуй на первый раз этого достаточно, чтобы пользоваться Jabber'ом как обычным IRC'ом.

В завершение

Закрываем соединение

</stream>


У XMPP поистине большие возможности и возможности протокола постоянно расширяются, за чем следить вы можете в официальной документации к протоколу: xmpp.org/xmpp-protocols/xmpp-extensions/
В ней очень подробно расписываются описания команд с примерами, но нужно учитывать, что в большинстве клиентов и серверов может быть не 100% реализация протокола, и команды внезапно могут не работать. Чтож, пишите тогда свой сервер и клиент.

Мне же с переходом на Linux стало проблематично поддерживать mIRC бота и я переписываю его на чистом Bash, который будет одинакого работать в IRC и XMPP. Почему Bash? — Он есть везде, у него низкий порог вхождения, много вкусных фич, хотя и недостатки тоже имеются. Мне он нравится как и mIRC Scripting Language.
Параллельно переписываю функционал из mIRC и на данный момент уже реализовал удобную работу с сокетами, и в качестве примера приведу скрипт уже рабочего «бота» для IRC

sockname=$RANDOM
sockopen $sockname "irc.ixx.ru" 9996

if [ $? = 0 ]; then
  sockwrite $sockname "NICK Voglea"
  sockwrite $sockname "USER robot * * :The Goddess of Darkness"
else
  exit 1
fi

while true; do
  sockread $sockname i
  i=${i/%[$'r'$'n']/}
  case "${i%% *}" in
    "PING")
      sockwrite $sockname "PONG ${i#*:}"
      ;;
    *)
      ;;
  esac
  echo $i
done

Команды sockopen, sockread, sockwrite, sockclose — полные аналоги mIRC, их я написал всего за вечер, с использованием /dev/tcp bash для обычных сокетов и openssl для SSL подключений. И затем, переписав большинство необходимого функционала mIRC на Bash, я возьмусь писать XMPP реализацию бота.
Но расскажу обо всем подробнее и поделюсь сорцами уже в другой статье.

Удачи с написанием XMPP бота, если вам таковой необходим.

Автор: Spoofing

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js