среда, 8 октября 2008 г.

Linux. DBhub, пишем чат-бота

Решил я у себя поднять DirectConnect Hub (DC-Hub то бишь).
Среди 3 дистрибутивов (Verli, PtokaX, DBhub) поставить смог только один - DBhub (http://www.dbhub.org/). Хаб в общем-то простой как в установке, так и настройке. По возможностям тоже достаточно прост и не обладает такой мощной поддержкой всякими скриптами как 2 его "соперника". Ну, по крайней мере на официальном сайте это представлено скупо, всего порядка 6 скриптов (http://www.dbhub.org/olddbhub/scripts/).
Но, хаб поддерживает Perl-скрипты, а это уже очень даже хорошо (главное не забыть при установке включить их поддержку).

Но прежде чем говорить про бота - рассмотрим базовые настройки по установке и настройке хаба. У меня помнится возникли вопросы, поэтому может вам будет проще.

Итак, взять свежий пакет можно на официальном сайте (http://www.dbhub.org/). Там представлены как исходники для компиляции, так и пакеты для распространенных систем (Debian'a, RPM'ы и прочее).
В принципе проблем с установкой как того, так и другого нет. С пакетом вообще проблем нету, если не ошибаюсь - нажали, и он встал. Другое дело что он там поставит.

Руками это можно проконтролировать, если компилировать самим. В общем-то и компилировать с особыми настройками смысла нет, можно оставить по-умолчанию. Единственное - надо добавить поддержку Perl-скриптов (если они вам нужны). Для этого надо иметь установленные пакеты Perl и perl-devel, если не ошибаюсь. А при конфигурировании указать параметр --enable-perl. Т.е. выполнить строку:
./configure --enable-perl
После чего вы узнаете, будет ли у вас хаб с поддержкой (если все нормально с Perl) или без поддержки Perl-скриптов. Наконец пишите make, make install и хаб должен встать.

Встает он каждому юзеру в папку я так понял. А может только тому, кто хаб запустит, точно не знаю. Путь такой:
домашняя_папка_юзера/.dbhub

Я запускаю под рутом, соответственно папка "/root/.dbhub".
Все настройки в этой папке и фактически собраны в одном конфигурационном файле. Описания каждой настройки подробно можно узнать из википедии DBhub'a (ссылка на сайте).
Все скрипты лежат в одноименной папке. Для их выполнения достаточно кинуть их туда и перезапустить сам хаб или только скрипты.

Хаб запускается командой "dbhub" из консоли.
Убить его можно командой "killall dbhub".
Если же нужно только перезапустить скрипты, то достаточно лишь написать от имени владельца хаба (или администратора) команду "!reloadscripts" в окне чата.

Владелец хаба и пароль к его учетной записи определяются при первом запуске, хотя потом и то и то можно изменить через конфигурационные файлы.
Для русификации надо заменить файл "lang" на русский и выполнить команду "!reloadlang" (если не ошибаюсь - подробнее читайте в описании к самому русификатору).

В общем решил я написать чат-бота. Простого такого бота, который отвечает тому, кто к нему обращается - фразой из своей базы. Ботов таких много, у меня идея возникла когда я увидел "Кубика" для хаба PtokaX (отсюда имя Rubik, как мой ответ PtokaX-боту). Бот неплох, но имеет недостатки: лезет в разговор когда не просят и его фразы быстро приедаются и надоедают.

При разработке были учтены эти 2 момента, в итоге бот отвечает только если к нему обращаются, и умеет обучаться новым фразам прямо во время разговора. Например, если написать "Rubik: Москва - Столица России!", то в след.раз встретив слово Москва бот ответит "Столица России!" =)

В общем довольно просто, но интересно при достаточно большой базе (которая быстро накапливается).
Короче говоря код бота приведен ниже. Сохраните его в файл "Rubik.pl" в кодировке CP1251 и положите в папку "/root/.dbhub/scripts" (или смотря откуда у вас запускается хаб). Если поддержка скриптов при компиляции была включена (./configure --enable-perl)



#!/usr/bin/perl

# Rubik-bot 0.3

# Моя первая Perl-программа. В этом языке практически не разбираюсь.
# Копипастил из кодов и инета. Так что извините за корявость написания кода =)
# Дополнять, копировать и т.д. никому не воспрещается.
# Просто не забывайте указывать меня в авторах ^_^
#
# My first Perl-program. My English is bad, but i hope you unerstand me =)
# Code is free-for-all. You can do with it what you want.
# But don't forget write my nick in comments ^_^
#
# TrenAr
#

### Rubik settings ###
my $bot = "Rubik"; #name of your bot
my $uhomedir = `echo ~`;
chop $uhomedir;
my $path = "$uhomedir/.dbhub/scripts/";

# Если в чате новое сообщение
# If a new message in a chat
sub data_arrival() {
my ($user, $data) = @_;

# Ищем - есть ли в чате упоминание ника бота
# Search Bot name in chat
$find = index ($data,$bot);
$findadd = index ($data,"$bot:");

# Если нашли упоминание его ника
# If find his name
if ($find > (-1)) {

# Берем то что написано после его ника, и обработка ":"
# Take the message after bot nick, without ":" if this need
$msg = substr($data,$find + length($bot)+1,length($data) - $find - length($bot));
if ($findadd > (-1)) {$msg = substr($data,$find + length($bot)+2,length($data)- $find - length($bot));}

# Ищем вероятные "определения", т.е " - "
# Find " - "
$st = " - ";
$target = index ($msg,$st);

# Здесь 2 как "защита от "пустых строк"
# Когда находим - разбиваем предложение на 2 части
# 1 it's defence
# When find $st - devine string to two string
if ($target > (2)) {
$part1 = substr($msg,0,$target);
$part2 = substr($msg,$target+length($st),length($msg) - $target - length($st) -1);

# Добавляем строки в файл
# Add strings in file
open MSSG, ">>$path/Rubik-database";
print MSSG "$part1.-.$part2";
for ($index = 0; $index <= 128 - length($part1) - length($part2) - 3; $index++)
{print MSSG "*";}
print MSSG "\n";
close MSSG;
odch::data_to_all("<$bot> Ясно |");

} else {

# Проверяем на наличие слов в фразе msg - в нашей базе
# Если есть совпадения - пишем 2 часть фразы.
# Если совпадений на одной слово несколько - пишем первое, а лучше рандомно.
#
# Look at our database and message. If it have equal phrases - $msg = $part1
# (msg - message to our bot; part1 one of words in base)
# then write in chat first phrase which true.
# Or Random - it will be more interesting.

$otv = "";
$kol = 0;
open MSSG, "<$path/Rubik-database";
while () {
read MSSG, $str, 128;

$search1 = index ($str,".-.");
if ($search1 > (-1)) {
$otvet1 = substr($str,0,$search1);
$search2 = index ($msg,$otvet1);
if ($search2 > (-1)) {
$kol++;
}
}
}
close MSSG;

open MSSG, "<$path/Rubik-database";
while () {
read MSSG, $str, 128;

$search1 = index ($str,".-.");
if ($search1 > (-1)) {
$otvet1 = substr($str,0,$search1);
$search2 = index ($msg,$otvet1);
if ($search2 > (-1)) {
$otvet2 = substr($str,$search1 + 3,length($str) - $search1 - 3);
$search3 = index ($otvet2,"**");
$otvet3 = substr($otvet2,0,$search3);
if ($otv eq "") {$otv = "$otvet3";}
else {
$tmp = int(rand($kol));
if ($tmp == 1) {$otv = "$otvet3";}
}
}

}

#while End
}
close MSSG;
odch::data_to_all("<$bot> $user $otv |");
}

# "If for Rubik" End
}
# DataArrival_End
}

sub main() {
odch::register_script_name($bot);
}

Если вам помогла эта статья - оставьте комментарий! Они доступны даже не зарегистрированным пользователям.

Комментариев нет: