]>Создание чат‐бота для IRC‐сети — FreeBASIC по‐русски

Библиотека IRC и личный IRC‐бот

Аватар пользователя mabu

Скриншот XChat 2.8.6.

Этим мы и займёмся — напишем «робота», который присоединяется к чату и рассказывает о компьютере. Скажем, ты на работе или в отпуске далеко от дома и хочешь наблюдать за домашней системой или сервером на площадке провайдера. Наш IRC-бот будет сидеть себе в чате и ждать, когда ты появишься и спросишь его о количестве свободной оперативной памяти.

Программ для мониторинга системы немерено, но они страдают повышенной дотошностью и забивают твой почтовый ящик письмами с лишними подробностями о работе компьютера. С нашим ботом всё намного проще: если ты хочешь узнать, сколько осталось свободного места на диске или посмотреть, хватает ли оперативной памяти, просто заскочи в IRC и спроси у него (через приватные сообщения). А самое важное — мы ограничим доступ так, чтобы эти данные мог получить только ты!

  1. Стоп… а что такое IRC?
  2. Сборка библиотеки
  3. Создание чат‐бота
    1. Подготовка
    2. Компиляция
    3. События
  4. Продолжаем работать
  5. Ссылки

Стоп… а что такое IRC?

IRC (Internet Relay Chat — ретранслируемый интернет‐чат) — это система обмена сообщениями в режиме реального времени, изобретённая в 1988 году. IRC — открытый текстовый протокол, и написать клиента для него не составит труда. IRC-обсуждения проходят во многих сетях; одни ориентированы на свободное ПО (chat.freenode.net), другие — на игры, третьи — на болтовню.

Каждая IRC‐сеть состоит из нескольких серверов, связанных друг с другом — можно выбрать как ближайший к тебе географически, так и любой другой случайным образом. В любом случае ты будешь частью одной и той же сети. Например, чтобы начать общаться в сети Freenode, найди IRC‐клиент (например, mIRC, X-Chat или ChatZilla — плагин к огнелисе), запусти его и введи:

Код
/server chat.freenode.net

Примечание: команды IRC в клиентах обычно начинаются со слэша.

После этого смени имя пользователя и зарегистрируй его со своим паролем с помощью следующих команд:

Код
/nick <mynickname>
/msg nickserv register <password>

Потом можно зайти в «канал» (отдельная комната чата) с помощью команды:

Код
/join ##freebasic-ru

Названия каналов обычно начинаются с символа решётки. В данном случае канал «freebasic-ru» начинается с двух решёток, так как он не является официальным, утверждённым сообществом сети Freenode.

Теперь ты можешь писать сообщения в общий чат или приватные сообщения отдельным пользователям (например, в X-Chat для этого щёлкни правой кнопкой мыши на имени пользователя и выбери в меню «Открыть диалог»).

Сборка библиотеки

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

Скомпилировать библиотеку из исходных текстов проще простого. Скачай исходники библиотеки libIRC и запусти компиляцию командой:

Код Batch
fbc -lib -x "libIRC.a" AsmIrc.bas SendData.bas ReceiveData.bas ParseData.bas GetIrcData.bas SendMessages.bas Network.bas

Либо можешь воспользоваться готовым релизом, там уже лежит скомпилированная библиотека.

Создание чат‐бота

Подготовка

Создадим две учётных записи для IRC: первая для тебя, вторая для бота (если ты завсегдатай IRC, то первая у тебя уже есть). Это важный этап, поскольку из‐за борьбы со спамом на многих IRC‐серверах пользователь должен зарегистрироваться, чтобы иметь возможность отправлять личные сообщения другим участникам чата.

Зайди в IRC и переключись в твоего обычного пользователя. Если ты ещё не зарегистрирован, то самое время это сделать:

Код
/msg nickserv register <password>

Параметр <password> замени на подходящий пароль (примеры команд приведены для серверов Freenode, в других сетях они могут отличаться). Теперь твой пользователь зарегистрирован на сервере IRC — то есть никто другой это имя не отберёт. Сказать IRC‐серверу кто ты такой, можно с помощью команды:

Код
/msg nickserv identify <password>

Нужно также зарегистрировать ник нашего пока нерождённого бота. Переключись в другого пользователя и задай ему пароль таким образом:

Код
/nick LeoFitz
/msg nickserv register <password>

Конечно, нужно взять другое имя пользователя, но на канале ##freebasic-ru уже сидит JemmaSimmons, почему бы не создать комплементарную пару ботов? Однако в любом случае стоит запомнить ник и пароль, они понадобятся коду нашего бота.

Компиляция

Итак, мы завели две зарегистрированные учётные записи, себе и боту. Мы готовы к созданию бота, вот его код:

Заголовочный файл bot.bi:

Код FreeBASIC
#ifndef unicode
#define unicode
#endif
' Определения библиотеки
#include once "Irc.bi"
' Обработчики событий
#include once "IrcEvents.bi"
' Константы ответов серверных сообщений
#include once "IrcReplies.bi"

' Имя сервера
Const Server = "chat.freenode.net"
' Порт
Const Port = "6667"
' Пароль на соединение с сервером, в данном случае пуст
Const Password = ""
' Ник бота
Const Nick = "LeoFitz"
' Юзер‐строка, необходима для идентификации, не должна содержать пробелов и спецсимволов
Const UserString = "LeoFitz"
' Описание бота
Const Description = "IRC bot written in FreeBASIC"
' Ник администратора бота (установи это значение в твой ник)
Const AdminNick = "AdminNick"
' Пароль для идентификации бота, замени на нужный тебе
Const BotPassword = "password"
' IP‐адрес и порт, с которых будут идти соединения с сервером
Const LocalAddress = "0.0.0.0"
Const LocalPort = "0"

Файл bot.bas:

Код FreeBASIC
#include once "bot.bi"

' Объект для работы с IRC
Dim Shared objClient As IrcClient

' Установка обработчиков событий
With objClient
&t;.ReceivedRawMessageEvent = @ReceivedRawMessage
&t;.SendedRawMessageEvent = @SendedRawMessage
&t;.ServerMessageEvent = @ServerMessage
&t;.PrivateMessageEvent = @IrcPrivateMessage
End With

' Открытие соединения с сервером
' Параметры:
' Сервер, порт, локальный адрес, локальный порт, пароль на сервер, ник, юзер‐строка, описание, режим видимости
If objClient.OpenIrc(Server, Port, LocalAddress, LocalPort, Password, Nick, UserString, Description, False) = ResultType.None Then
&t;' Соединение с сервером установлено
&t;Do
&t;&t;' Бесконечный цикл получения данных от сервера до тех пор, пока не будет ошибок
&t;Loop While objClient.GetData() = ResultType.None
&t;' Закрыть соединение
&t;objClient.CloseIrc()
End If


' Событие любых входящих данных
Sub ReceivedRawMessage(ByVal AdvData As Any Ptr, ByVal MessageText As WString Ptr)
&t;' Просто печатаем на консоль пришедшие данные
&t;Print MessageText
End Sub
' Событие любых исходящих данных
Sub SendedRawMessage(ByVal AdvData As Any Ptr, ByVal MessageText As WString Ptr)
&t;' Просто печатаем на консоль пришедшие данные
&t;Print MessageText
End Sub

' Серверное сообщение
Function ServerMessage(ByVal AdvData As Any Ptr, ByVal ServerCode As WString Ptr, ByVal MessageText As WString Ptr)As ResultType
&t;If ServerCode = RPL_WELLCOME Then
&t;&t;' Отправить идентификационные данные бота
&t;&t;objClient.SendIrcMessage("NickServ", "identify" & BotPassword)
&t;&t;' Присоединиться к каналам
&t;&t;objClient.JoinChannel("##freebasic-ru")
&t;End If
&t;Return ResultType.None
End Function

' Личное сообщение
Function IrcPrivateMessage(ByVal AdvData As Any Ptr, ByVal User As WString Ptr, ByVal MessageText As WString Ptr)As ResultType
&t;' Команда от админа
&t;If User = AdminNick Then
&t;&t;Dim intMemory As UInteger = Fre()
&t;&t;objClient.SendIrcMessage(AdminNick, "Количество свободной памяти в байтах = " & WStr(intMemory))
&t;End If
&t;Return ResultType.None
End Function

Давай пройдёмся по коду. Первые строки просто сообщает компилятору FreeBASIC о подключении заголовочных файлов библиотеки libIRC. Наш бот будет принимать и отвечать в кодировке UTF-8, поэтому никаких проблем с русскими буквами быть не должно. В заголовочном файле объявляются имя сервера, порт для подключения, имя бота, имя владельца бота и пароль для соединения с сервером (в данном случае пароль пустой). Перед компиляцией их потребуется изменить на имя твоего зарегистрированного бота.

Но сперва нужно сделать одну вещь: установить обработчики событий, которые бот генерирует при получении данных от IRC‐сервера. Наш бот ведь не глухонемой, и он должен знать, на какие сообщения давать ответ. Обработчик события — это функция, которую будет вызывать библиотека в ответ на какой‐нибудь сигнал.

Код FreeBASIC
With objClient
&t;.ReceivedRawMessageEvent = @ReceivedRawMessage
&t;.SendedRawMessageEvent = @SendedRawMessage
&t;.ServerMessageEvent = @ServerMessage
&t;.PrivateMessageEvent = @IrcPrivateMessage
End With

В данном случае события SendedRawMessageEvent и ReceivedRawMessageEvent срабатывают всякий раз, когда на сервер отправляется или приходит с него любые данные, ServerMessageEvent срабатывает при получении специального серверного сообщения (уже после события ReceivedRawMessageEvent), а PrivateMessageEvent — при получении ботом личного сообщения (тоже после события PrivateMessageEvent). IRC‐бот также может реагировать и на всякие другие события, например, присоединение пользователя к каналу, смена темы канала, но в нашем случае они не рассматриваются (домашнее задание: изучи заголовочный файл IrcEvents.bi, посмотри, какие ещё события может генерировать библиотека и установи для них обработчики).

Вызов objClient.OpenIrc() приводит бота в действие. Эта функция открывает соединение с сервером, отправляя специально подготовленную строку соединения. При успешном соединении с сервером функция возвращает значение ResultType.None

Теперь пора получать данные от сервера, что делается в бесконечном цикле функцией objClient.GetData(), при успешном выполнении возвращающей всё то же ResultType.None. Функция запускает внутри себя обработчик данных, пришедших с IRC‐сервера и в зависимости от данных генерирует соответствующие события. На четыре события мы уже подписались ранее в коде.

События

ReceivedRawMessageEvent — первое событие, которое вызывается при успешном получении данных. В качестве аргумента передаётся указатель на дополнительные данные AdvData. В нашем случае он пуст, но вполне допустимо было бы на этипе инициализации присвоить туда какие‐нибудь значение. Второй аргумент MessageText — это текст, пришедший от сервера.

В обработчике события мы просто выводим MessageText на консоль.

SendedRawMessageEvent аналогично ReceivedRawMessageEvent, только происходит оно при любой отправке данных на сервер. Эти два события показывают всю кухню IRC‐взаимодействия бота и сервера.

Событие ServerMessageEvent вызывается после ReceivedRawMessageEvent. Оно происходит тогда, когда ни одно из других специальных событий, таких как IrcPrivateMessage, не срабатывает. Второй аргумент события — это специальный числовой код, записанный в спецификации IRC‐протокола. Нас интересует код RPL_WELLCOME, что в цифрах "001". Значит, теперь можно отправлять на сервер идентификационную строку с паролем бота и присоединяться к каналам. Nickserv — это встроенный сервис‐обработчик имени пользователя на большинстве серверов IRC. Мы предоставляем ему пароль бота для аутентификации его на сервере, отправляя его личным сообщением.

Кстати, каналов, на которых будет сидеть бот, может быть несколько, а может и не быть вовсе. Однако, чтобы определить, онлайн ли бот сейчас, очень удобно зайти на канал и посмотреть в списке пользователей, есть ли он там.

Теперь наш бот будет смирно сидеть на канале, пока его оттуда не выгонят. Следующая функция здесь — это IrcPrivateMessage. Этот обработчик события IrcPrivateMessageEvent вызывается когда бот получает личное сообщение, то есть сообщение в отдельном диалоге вне какого‐нибудь канала. Бот проверит, является ли отправитель администратором бота, и если это так, то отправит текущее количество свободной памяти в системе пользователю с ником AdminNick, то есть твоему обычному пользователю.

Продолжаем работать

Пора запустить бота. Открой файл bot.bi и измените конфигурационные константы сверху в соответствии с твоими настройками, а именно впиши имя пользователя и пароль для бота, своё ник администратора бота, имя канала, на котором будет висеть бот. Запусти IRC‐клиента, авторизуйся на сервере и зайди в канал, который ты указал для бота. Скомпилируй бота командой:

Код Batch
fbc -l IRC bot.bas

Затем запусти бота.

Через пару секунд бот установит соединение, авторизуется на сервере и зайдёт в указанный канал. Командой /msg из своего клиента начни приватный диалог с ботом и скажи ему всё, что угодно — бот пришлёт результат выполнения функции Fre(). Отлично! Теперь можно запустить бота на любом компьютере и отслеживать уровень загрузки удалённой системы просто общаясь с ботом в IRC‐чате.

Хотя нарекания остаются. Бот умеет выполнять только команду Fre() — может, тебе этого и достаточно, но он способен на гораздо большее. Вряд ли ты захочешь разрешить боту выключать компьютер, но с его помощью можно получить о компьютере массу информации, запускать и останавливать приложения, отправлять письма по электронной почте, соединяться с сайтами и скачивать содержимое. Можно даже сделать говорящего бота, отвечающего на сообщения пользователя случайной фразой из списка, бота для игр в карты, крестики‐нолики, морской бой, викторину с вопросами, мафию, бота‐читателя RSS‐лент и прочее.

Это очень гибкое решение: если кажется, что с компьютером что‐то случилось, можно запустить бота на web‐сервере и допросить его; или запустить бота на домашнем компьютере и прямо с рабочего места запускать и останавливать с его помощью определённые процессы. Возможности безграничны — а всего‐то нужен доступ к IRC.

Ссылки

Поделись ссылочкой в социальных сетях