Дарова перец!

Итак, ты всё ещё не можешь хакнуть инет-магазин с огромной базой кред 😉 и заказать себе отличный шелл со всеми операциями и поддержкой Inet-соединений. Ведь только я знаю, что твоя мечта засадить на любимый IRC-канал своего lama-бота 🙂 Увы, eggdrop на
халявных шеллах вряд ли установится как 2*2. Но, как говорится, где наша не пропадала ...

Сейчас я вам поведаю как написать своего бота. Будем писать на Perl, так как поддержка Perl скриптов есть даже на халявных шеллах.
Для тех, кто плохо знает Perl, я объясню, что наряду с самим Perl-интерпретатором существует поддержка модулей, которые выполняют самые разные функции. Интересным модулем является socket.pm, позволяющий управлять сокетными
соединениями. Это нам и нужно.

Напишем скрипт, который и будет нашим lama-ботом 🙂 Точнее бот будет состоять из множества скриптов, но выполнение дополнительных будет зависеть от главного скрипта (во сморозил то=) ). 

Итак, первый скрипт, который мы напишем будет configure.pl - скрипт общей конфигурации бота. Туда записываем переменные, которые не будут изменяться:

$respdir="response"; # директория, для дополнительных скриптов, отвечающих за реакцию бота на какие либо действия пользователей
$scr_ex="\.pl"; # расширение скриптов (на всякий случай... )

($sec,$min,$hour,$mday,$mon,$year,$wday) = (localtime(time))[0,1,2,3,4,5,6];
$time = sprintf("%02d:%02d:%02d",$hour,$min,$sec);
$year += 1900; 
@days = ('Sun','Mon','Tue','Wen',
'Thi','Fri','Sat');
@months = ('Jan','Feb','Mar','Apr','May','Jun','Jul',
'Aug','Sep','Oct','Nov','Dec');
$date = "$days[$wday] $months[$mon] $mday $time $year"; ### Генерация текущего времени
$logfile="logs/bot.log"; # Путь к логфайлу (бот тоже умеет шпионить 😉 )

Вот классический пример скрипта configure.pl. Рекомендуется внести именно эти переменные.
Далее идёт не менее интересный скрипт для переменных, значения которые могут измениться во время жизни вашего бота. Скрипт имеет название botconf.pl. Яркий пример кода:

$sname='irc.dal.net'; # IRC server
$sport=6667; # IRC port
$nickname='Super'; # Nickname for bot
$altnick='Super_'; # Альтник
$username='suPERL'; # Идент
$identname="suPERL"; # Тож идент
$infoclient="ProstoSuper"; # Инфа о боте

@cnames=(
'perl',
'test',
); # Список каналов на которые бот будет заходить (без решёток).

$modchall="tnimps"; # возможные режимы канала

$modest{"\#test"}='+nt-smplik';
$modest{"\#perl"}='+ntp-smlik'; ### Отдельно для каждого канала

Примерно таким способом мы написали два конфигурационных
скрипта. Следующий шаг - центр управления бота - скрипт bot.pl Его пример:

use IO::Socket; # Юзаем модуль socket.pm

require "configure.pl" or die print "Can't find configure!\n"; # Выполняем конф. скрипт
do "botconf$scr_ex"; # Выполняем второй конф. скрипт.

begin:; ## Начала соединения с сервером
$server=IO::Socket::INET->new( PeerAddr => $ARGV[0] || $sname, # имя сервера
PeerPort => $sport, # порт
Photo => tcp) # протокол
or die print "Unable to connect to $sname:$sport\n"; # или сообщаем об ошибке связи

print $server "nick $nickname\n"; 
print $server "user $username $identname Super :$infoclient\n"; ### Регистримся на сервера

$response=<$server>;
chomp ($response);
if ($response=~/433/i) {
print "Nick in use\n";
print $server "nick $altnick\n";
$nickname=$altnick;
} ### Юзаем альтник, если обычный ник уже кем то занят.

@sn=split(/ /,$response);
$servername=substr($sn[0],1,length($sn[0]));
$repl="\:$servername "; ### Узнаём имя сервера

while (not($response =~/376/i)) {
$response=<$server>;
} ### Коннектимся и ждём конца MOTD

$jmode="start"; # Значение переменной для нового скрипта='start'
do "$respdir/join$scr_ex"; ## Передаём управление скрипту response/join.pl - см. дальше.

open (Logfile,">>$logfile");
print Logfile "\nSession start: $date\n"; # Пишем в лог время начало сессии

con:;
$response=<$server>;
chomp ($response);
@otmessage=split(/ /,$response); # Разбиваем на пробелы очередное с сообщение с IRC-сервера.

if ($response=~/PING \:$servername/i) {
print $server "pong $servername\n";
goto now;
} ### Отвечаем на пинг сервера и переходим в конец скрипта (в случае если строка с сервера=ping).

if ($response =~/NOTICE/i) {
goto now;
} ### Нотайсы не стал рассматривать: доработаеш сам =)

@sp=split(/\!/,$otmessage[0]);
$actnick=substr($sp[0],1,length($sp[0]));
@spu=split(/\@/,$sp[1]);
$user=$spu[0];
$host=$spu[1];
$userhost=$sp[1]; ### Узнаём хост, идент и ник человека, который передал сообщение.

if ($response =~/PRIVMSG/i) {
$i=3;
while(length($otmessage[$i])>0) {
if ($i eq 3) {
$mess[$i]=substr($otmessage[$i],1,length($otmessage[$i]));
} else {
$mess[$i]=" $otmessage[$i]";
}
$i++;
}
foreach $ch (@otmessage) {
chomp ($ch);
} ### Выделяем сообщение участника (адская работа 🙂 )

$message=join('',@mess);
$message=substr($message,0,length($message)-1);
chomp($message);
$messageot=substr($message,0,length($message));
if (substr($otmessage[3],0,2) eq ":") {
do "$respdir/ctcpmore$scr_ex";
goto endpmg;
} ### Если сообщение идёт по ctcp - юзаем соответствующий скрипт (response/ctcpmore.pl).

foreach $prch (@cnames) {

if ($otmessage[2] eq "\#$prch") {
$actchan=$prch;
do "$respdir/channel$scr_ex";
print Logfile "\#$actchan \[$time\] \<$actnick\> $messageot\n";
close(Logfile);
open (Logfile,">>$logfile");
@mess=('');
goto now;
} ### Если сообщение передаётся на канал - юзаем response/channel.pl и дозаписываем сообщение в лог-файл.

if ($otmessage[2] eq "$nickname") {

do "$respdir/private$scr_ex";
print Logfile "Private \[$time\] \<$actnick\> $messageot\n";
close(Logfile);
open (Logfile,">>$logfile");
}
endpmg:;
@mess=('');
goto now;
} ### Иначе - сообщение в приват - скрипт "response/private.pl" выполнит свою работу.

if ($response =~/MODE/i) {

foreach $prch (@cnames) {

if ($otmessage[2] eq "\#$prch") {
$actchan="\#$prch";
}}
$mode=$otmessage[3];
$otmessage[4]=substr($otmessage[4],0,length($otmessage[4])-1);
if ($actnick ne $nickname) {

do "$respdir/mode$scr_ex";
print Logfile "$actchan \<$actnick\> $otmessage[3] $otmessage[4]\n";
close(Logfile);
open (Logfile,">>$logfile");
@mess=('');
goto now;
} else {
print Logfile "*** $actchan MODE :\<$nickname\> $otmessage[3] $otmessage[4]\n";
close(Logfile);
open (Logfile,">>$logfile");
goto now;
}
} ### Если происходит изменение режимов канала, и изменяет не бот - передача данны скрипту "response/mode.pl" и запись в лог.

if ($response =~/KICK/i) {
foreach $prch (@cnames) {
if ($otmessage[2] eq "\#$prch") {
$actchan="\#$prch";

}}
$jmode='kick';
$jparam='self';
do "$respdir/join$scr_ex";
goto now;
} ### Если кикнули - юзаем скрипт join.pl с параметром kick.

if (substr($response,0,7) eq "ERROR \:") {
goto begin;
} ### Если бот был отрублен от сервера - идём в начало скрипта на реконнект

now:;
goto con; ### Идём ожидать новое сообщение

Всё. Скрипт готов. Я попытался кратко объяснить, что
почём. Не отрицаю, что в моих скриптах много навороченного, и можно было сделать проще, но я писал за короткое время, поэтому особо не думал. Кому надо - тот переделает.

Для примера публикую скрипт join.pl и private.pl. Остальные напишете по аналогии.

### Join.pl

if ($jmode eq 'start') {

foreach $join (@cnames) {
print $server "join \#$join\n";
$response=<$server>;
if ($response =~/474/i) {
print Logfile "*** $actchan $kicknick KICKED by $actnick ($messg) ME banned \:\(\n";
close(Logfile);
open (Logfile,">>$logfile");
goto off;

} ### Проверка и в успешном случае join на каналы.

while (not($response =~/366/i)) {
$response=<$server>;
}
}} ### Получение сведений о канале

if ($jmode eq 'kick') {
........... ### Напишете по аналогии
}

### Private.pl

if ($messageot eq "rehash") {

print $server "msg $actnick Ok... Rehashing!\n"; ### Проверка входных данных на rehash
do "botconf$scr_ex"; ### Выполняем заново конф. скрипт
print $server "nick $nickname\n"; ### Меняем ник
$response=<$server>;
if ($response=~/433/) {
print $server "nick $altnickname\n"; ### Или на альтник
$nickname=$altnickname; ### Запоминаем ник для дальнейших действий
}

if ($messageot eq "restart") {
print $server "msg $actnick Ok... Restarting!\n"; ### Рестарт бота
print $server "quit :Restart by $actnick\n"; ### Уход с IRC
close(Logfile);
open(Logfile,">>$logfile");
print Logfile "\nSession closed: $date (Restart by $actnick\)\n";
close(Logfile);
close($server);
$a=0;
until($a eq 100000) {
$a++;
}
goto begin; ### Запись в лог, неболшая пауза и реконнект. 
}

if ($messageot eq "die") {

print $server "msg $actnick Bye my dear master $actnick!\n";
print $server "quit :Shutdown by $actnick\n";
close(Logfile);
open(Logfile,">>$logfile");
print Logfile "\nSession closed: $date (Shutdown by $actnick\)\n";
close(Logfile);
close($server);
exit 0;
} ### Завершение работы бота 🙂 Команда "die"

И так далее...

Входные данные для скрипта: $user=ident, $host=host, $actnick=никнейм того, кто слал мессагу (кикнул с канала), $messageot=само сообщение, @otmessage - вся строка сервера разбитая по пробелам.

Отмечу, что если bot.pl не находит скрипт, либо в скрипте ошибка, скрипт просто-напросто не будет выполнен, а бот останется жив.

Удачи в написании скриптов 🙂

PS: если кто заинтересуется: мылить на forb@pisem.net, я с удовольствием дам вам все исходники моего бота и поделюсь информацией.

Check Also

Исходный кот. Как заставить нейронную сеть ошибиться

Нейросети теперь повсюду, и распознавание объектов на картинках — это одно из самых популя…

Оставить мнение