ANTICHAT.XYZ    VIDEO.ANTICHAT.XYZ    НОВЫЕ СООБЩЕНИЯ    ФОРУМ  
Баннер 1   Баннер 2
Antichat снова доступен.
Форум Antichat (Античат) возвращается и снова открыт для пользователей. Здесь обсуждаются безопасность, программирование, технологии и многое другое. Сообщество снова собирается вместе.
Новый адрес: forum.antichat.xyz
Вернуться   Форум АНТИЧАТ > Программирование > PHP, PERL, MySQL, JavaScript
   
Ответ
 
Опции темы Поиск в этой теме Опции просмотра

Пишем простого Irc бота на Perl
  #1  
Старый 16.06.2007, 23:30
Аватар для ENFIX
ENFIX
Участник форума
Регистрация: 06.06.2006
Сообщений: 213
Провел на форуме:
1628290

Репутация: 474
Отправить сообщение для ENFIX с помощью ICQ
По умолчанию Пишем простого Irc бота на Perl

Пишем IRC бота на PERL

Здравствуйте! Сегодня я вам расскажу, как написать простенького irc бота на PERL.
Сам недавно только взялся за изучение этого языка. Как то раз скачал книгу Клинтон Пирс - "Освой самостоятельно Perl за 24 часа"
Скажу сразу - книга так себе, только основы (Но мне как раз это и нужно было)
И вот, когда я дошел до модулей, наткнулся на IO::Socket. Тем вечером я еще сидел в ирке, и подумал: "А почему бы не попробовать..."

Ну вот, лирическое отступление кончилось =) Начнем!

И так, что нам понадобится:
ActivePerl, подключение к интернету, mIRC(или другой клиент для IRC), минимальные знания PERL, а также документация по протоколу IRC со стороны клиента (я брал http://tools.ietf.org/html/rfc2812)

Собственно вот... Открываем текстовый редакор, пишем строчки:
Код:
#!/usr/bin/perl
Думаю, тут комментировать ненадо, но все таки. Эта строка указывает путь к интерпритатору PERL.

Подключаем модули:
Код:
use strict; 
use IO::Socket;
Подключили =)
Код:
my $server = "irc.inattack.ru"; 
my $port=6667;
my $chanel = "#inattack";
my $nick = "MIKE"; 
my $ident = "mike";
my $name="Майк";
В переменной $server хранится адрес irc сервера (вписываем нужный)
В переменной $port хранится порт irc сервера (вписываем нужный)
И в переменной $chanel хранится адрес канала
В переменной $nick хранится Ник бота
В переменной $ident хранится Идент бота
В переменной $name хранится имя бота (увидите при хуизе)

Идем дальше:
Код:
my $socket = new IO::Socket::INET(PeerAddr => $server, PeerPort => $port, Proto => "tcp");
в этой строке создаем новый объект IO::Socket::INET и ссылка на него присваевается переменной $socket

Ну вот, переменные мы задали, начало есть =)
Теперь идем к документации, видим, что первым делом мы должны послать
Цитата:
Command: NICK
Parameters: <nickname>
Так и сделаем 8)
Код:
print $socket "NICK $nick\r\n";
В переменную $socket вы вводим NICK $nick, \r\n - перевод каретки на следущую строку (то же что и Enter)

Идем дальше, следущей командой должна быть:
Цитата:
Command: USER
Parameters: <user> <mode> <unused> <realname>
Собственно что мы и сделаем:
Код:
print $socket "USER $ident 8 * :$name\r\n";
Что далее? Далее мы заходим на нужный нам канал, что говорит документация?
Цитата:
Command: JOIN
Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
/ "0"
Реализовываем:
Код:
print $socket "JOIN $chanel\r\n";
Готово, бот законнектился на ирк сервер, зашел на канал, НО, спустя какое то время его выкинет по причине (Ping timeout)
Этого нам конечно же не нужно. По протоколу, спустя какое то время, сервер на посылает запрос вида "PING : irc.site.com", а нам надо отправить ответ PONG.
Идем к документации, видим:
Цитата:
Command: PONG
Parameters: <server> [ <server2> ]
"Шкодим" через цикл
Код:
while (my $body = <$socket>) { 
chop $body; 
if ($body =~ /^PING(.*)$/i) { 
print $socket "PONG $1\r\n"; 
}
}
Готово! Теперь наш бот умеет коннектиться к серверу, заходить на канал и "не вылетать" 8)
Но все равно чего-то не хватает, правда? =)
Давайте сделаем, чтоб при заходе на канал, он говорил привет:
Код:
print $socket ("PRIVMSG $chanel : Привет всем =)\r\n");
Отлично! Но бот без команд, это не бот, так? =)

Приведу пример некоторых: (пишем в цикл while() )
Код:
if ($body =~ /^.*!yandex(.*)$/i) { 
print $socket ("PRIVMSG $chanel Сам ищи, я не лох :-P\r\n"); 
}
if ($body =~ /^.*!bye(.*)$/i) { 
print $socket ("QUIT\r\n"); 
}
Собственно вот он, самый простой бот готов! =)

Основы я вам дал, дальше давайте сами. Прошу сильно не критиковать, ибо только недавно взялся за изучение перл.
С радостью выслушаю вашу критику и замечания.
Ниже приведу весь исходник бота.
Код:
#!/usr/bin/perl
use strict; 
use IO::Socket; 
my $server = "irc.inattack.ru"; 
my $port=6667;
my $chanel = "#inattack";
my $nick = "MIKE"; 
my $ident = "mike";
my $name="Майк";
my $socket = new IO::Socket::INET(PeerAddr => $server, PeerPort => $port, Proto => "tcp") or die "lol";
print $socket "NICK $nick\r\n"; 
print $socket "USER $ident 8 * :$name\r\n"; 
print $socket "JOIN $chanel\r\n"; 
print $socket ("PRIVMSG $chanel : Рад вновь увидеть вас всех!!\r\n"); 
while (my $body = <$socket>) { 
chop $body; 
if ($body =~ /^PING(.*)$/i) { 
print $socket "PONG $1\r\n"; 
} 
if ($body =~ /^.*!yandex(.*)$/i) { 
print $socket ("PRIVMSG $chanel Сам ищи, я не лох :-P\r\n"); 
}
if ($body =~ /^.*!bye(.*)$/i) { 
print $socket ("QUIT\r\n"); 
} 
}
Спасибо за внимание!

Последний раз редактировалось ENFIX; 17.06.2007 в 04:43..
 
Ответить с цитированием

  #2  
Старый 17.06.2007, 00:15
Аватар для Piflit
Piflit
Banned
Регистрация: 11.08.2006
Сообщений: 1,522
Провел на форуме:
5128756

Репутация: 2032


Отправить сообщение для Piflit с помощью ICQ
По умолчанию

1. может значение $port тоже надо писать в кавычках?
2. команды серверу должны начинаться со слеша "/"
 
Ответить с цитированием

  #3  
Старый 17.06.2007, 01:21
Аватар для KSURi
KSURi
Постоянный
Регистрация: 06.06.2006
Сообщений: 515
Провел на форуме:
1985206

Репутация: 963


По умолчанию

про perldoc рассказывать даже не пытаюсь=\

Код:
/^.*!yandex(.*)$/i
регекс ваще не в тему... надеюсь сам разберешься почему

кароче незачот

Последний раз редактировалось Thanat0z; 17.06.2007 в 02:51..
 
Ответить с цитированием

  #4  
Старый 17.06.2007, 01:50
Аватар для Isis
Isis
Флудер
Регистрация: 20.11.2006
Сообщений: 3,316
Провел на форуме:
16641028

Репутация: 2371


По умолчанию

Зачем из этого делать статью?Выложил бы своего бота, кому надо переделают...
А вообще для начала дай хотябы одну книгу по языку pel
 
Ответить с цитированием

  #5  
Старый 17.06.2007, 02:54
Аватар для Thanat0z
Thanat0z
Постоянный
Регистрация: 06.12.2006
Сообщений: 762
Провел на форуме:
5352530

Репутация: 2062


По умолчанию

Цитата:
Сообщение от Isis  
Зачем из этого делать статью?
Перенес в Кодинг
 
Ответить с цитированием

  #6  
Старый 17.06.2007, 04:42
Аватар для ENFIX
ENFIX
Участник форума
Регистрация: 06.06.2006
Сообщений: 213
Провел на форуме:
1628290

Репутация: 474
Отправить сообщение для ENFIX с помощью ICQ
По умолчанию

>1. может значение $port тоже надо писать в кавычках?
Числа можно писать без кавычек
>2. команды серверу должны начинаться со слеша "/"
Нет, это в мирке и др так сделано. Прочитай документацию.
>регекс ваще не в тему... надеюсь сам разберешься почему
Да.. ступанул =) Учу... соррь
>А вообще для начала дай хотябы одну книгу по языку pel
Очепятался, бывает

За критику спасибо!
 
Ответить с цитированием

  #7  
Старый 18.06.2007, 09:46
Аватар для Cobalt
Cobalt
Новичок
Регистрация: 28.03.2007
Сообщений: 7
Провел на форуме:
4007

Репутация: 21
По умолчанию

Раз пошел такой колинкор предлагаю заценить и это кто не видел: http://www.gfs-team.ru/?act=articles&pact=55 - Perl.Irc Bot

Цитата:
В этой статье мы попытаемся охотиться сразу на двух зайцев. А именно, разберем
IRC протокол и напишем скрипт на Perl, который будет выполнять функции IRC бота.
Эта статья посвящена в первую очередь програмистам которые хотят изучить Perl,
и подразумевается что они хотябы знают синтаксис данного языка.

Для начала опишем настроечные переменные, а именно:

1. Адрес и порт сервера.
2. Ник и идент
3. IRC канал на котором будет крутиться наш бот.

Это делается так:

$host="irc.lxxl.info";
$port="6667";
$nick="MyBot";
$ident="MyBot";
$chan="#GFS";

Советую использовать в качестве сервера именно irc.lxxl.info, он не очень строг
к вашему иденту ). Далее создадим сокет соединения с сервером:

use Socket;
socket(SOCK, PF_INET, SOCK_STREAM, getprotobyname(\'tcp\'))
or die "Couldn`t create socket : $!\n";
$iaddr=inet_aton($host);
$paddr=sockaddr_in($port,$iaddr);
print "\n>> Connecting to $host:$port...\n";
connect(SOCK, $paddr)
or die "Couldn`t connect to $host:$port : $!\n";
for($i=0; $i<4; $i++){
$data=;
print($data);
}

Рассмотрим этот кусок кода более подробно. use Socket - сдесь мы указали что
необходимо использовать стандартную библиотеку Socket, которая содержит
функции и переменные для работы с сокетами. Функция socket предназначена
для создания сокета. В ее первом параметре указывается идентификатор по которому
мы в последствии будем обращаться к сокету. Во втором указывается комуникацион-
ный домен, в нашем случае это PF_INET, что означает домен Интернет. Так же
существует домен unix - PF_UNIX. Третий параметр указывает тип сокета. Мы будем
использовать SOCK_STREAM - этот тип обеспечивает последовательный, надежный
поток байтов. Так же существуют Datagram socket и Raw socket, но о них как-
нибудь в другой раз. И наконец в последнем параметре определяется протокол.
Делается это функцией getprotobyname(\'tcp\'), которая указывает в качестве
протокола TCP. Так же возможно использовать и udp, ip и т.д. Функция
getprotobyname возвращает название протокола в более удобном для функции socket
виде.

Далее необходимо преобразовать адрес сервера в бинарную последовательность.
Для этого используется функция inet_aton(). И дописать в нее порт к которому
мы будем соединяться функцией sockaddr_in(). Теперь соединим сокет с сервером
функцией connect(). Если все прошло успешно, в указателе SOCK у нас будет
поток сокета. Работать с ним можно точно также как и с потоком файла. Например
при успешном соединении сервер должен послать нам четыре строки служебной инфы.
Вот мы их прочитаем и выведем на экран в цикле For.

Теперь необходимо послать серверу информацию о себе. А именно идент и ник.
Для этого нам понадобится вункция send() которая принимает в качестве аргумента
три параметра: идентификатор сокета, строку которую необходимо отослать и 0.
Вместо нуля могут быть установлены следующие флаги:

MSG_OOB - Посылать/получать данные, характерные для сокетов типа
SOCK_STREAM
MSG_DONTROUTE - Посылать данные без маршрутизации пакетов. Как правило
используется диагностическими программами и процессами
управляющими таблицами маршрутизации.

Посылаем данные, читаем 10 строк и выводим на экран:

print ">> Sending NICK and IDENT...\n";
send (SOCK, "NICK $nick\n", 0);
send (SOCK, "USER $ident localhost localhost :$nick\n", 0);
for($i=0; $i<10; $i++){
$data=;
print($data);
}

В соответствии со стандартом IRC протокола, мы обязаны при соединении
уведомить сервер о том кто мы такие. Это делают IRC команды NICK и USER. Их
синтаксис не сложно понять из запросов которые мы только что отослали серверу.
Команда JOIN предназначается для входа на какой-либо канал. Отсылаем

print ">> Join chanel $chan...\n";
send (SOCK, "JOIN $chan\n", 0);

для входа на указаный канал. Заметь, что каждая IRC команда оканчивается
обязательным символом \n (перенос строки). Ведь ты нажимешь Enter в mIRC ?=)
Давай запустим бесконечный цикл приема сообщений:

while($data=){
print($data);
}
close(SOCK);

Теперь твой бот висит на канале и слушает что ему говорят. В окошке консоли
отлично видно какая информация приходит с сервера. Но возникает одна существен-
ная проблема: нашего бота через некоторое время выкидывает с сервера по таймауту
Это происходит из-за того что бот не отвичает на пинги посылаемые сервером.
Да да, на сервере установлен миханизм защиты от зомби. Каждому своему клиенту
через определенное время посылается команда PING, на которую в течении 256-ти
секунд клиент обязан ответить командой PONG с копией переданых данных. Если
же сервер по прошествии 256-ти секунд не получает ответа, он закрывает свое
соединение с клиентом, считая его зависшим.

Выходом из данной ситуации будет служить если мы пропишем в цикле бота обработ-
чик пингов.Т.е. нам необходимо уловить когда придет комада содержащая слово PING
взять данные пришедшие вместе с ней, и отослать в месте с командой PONG обратно
серверу.

@part=split(/:/,$data);
if(@part[0] eq "PING "){
print ">> PONG :@part[1]\n";
send (SOCK, "PONG :@part[1]\n", 0);
}

Функция split разбирает строку в переменную, считая в качестве разделителя
первый аргумент. В нашем случае это простейшее регулярное выражение /:/, которое
указывает в качестве разделителя двоеточие. После у нас в массиве @part
содержатся элементы строки $data. eq - аналогично знаку равенства для
строк.

Теперь было бы не плохо если бы наш бот хоть что-то бы делал, а не просто сидел
и молчал на канале. Давай напишем обработчик излюбленной всеми команды !пиво ).
Получая такую команду наш бот должен проверить, идет ли за ней чей-то ник. Если
да, то он должен сказать что пославший команду налил указаному нику пива. Если
же не идет, то бот обязан сказать что пославший команду налил всем пива.

### парсим полученую строку.
chop($data); ## обрезаем символы конца у строки
chop($data); ## обрезаем символы конца у строки
@part=split(/:/,$data);
@tmp=split(/!/,@part[1]);
$_user=@tmp[0]; # $_user - задавший команду
@tmp=split(/ /,@tmp[1]);
$_id=@tmp[0]; # $_id - идент юзера
@tmp=split(/ /,@part[1]);
$_cmd=@tmp[1]; # $_cmd - IRC команда
@tmp=split(/ :/,$data);
$_data=@tmp[1]; # $_data - команда

Эти переменные пригодятся тебе а дальнейшем. Теперь осталось только проверить
$_data на наличие !пиво в начале строки. делается это через регулярные
выражения:

if($_data=~/^!пиво/){
## $_data содержит !пиво в начале строки
}

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

@part=split(/ /,$_data);
if(@part[1]){
send (SOCK, "PRIVMSG $chan :$_user налил пива @part[1]\n", 0);
}else{
send (SOCK, "PRIVMSG $chan :$_user налил всем по пиву\n", 0);
}

IRC команда PRIVMSG предназначена для отправки сообщений. Если вместо $chan
указать ник юзера, то сообщение будет отправлено ему в приват.

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

Ну вот и все на cегодня. До скорых встреч! =)


© Cobalt
На сайте есть исходник. Плюс немного улучшенная версия перлового бота.
 
Ответить с цитированием

  #8  
Старый 18.06.2007, 12:58
Аватар для KSURi
KSURi
Постоянный
Регистрация: 06.06.2006
Сообщений: 515
Провел на форуме:
1985206

Репутация: 963


По умолчанию

В обоих статьях не увидел нормального парсинга...
Код:
/^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s(#.+?)\s:(.+?)$/
# $1 - nick
# $2 - ident
# $3 - host
# $4 - chan
# $5 - msg text
PS: perldoc Net::IRC
 
Ответить с цитированием

  #9  
Старый 18.06.2007, 15:24
Аватар для ENFIX
ENFIX
Участник форума
Регистрация: 06.06.2006
Сообщений: 213
Провел на форуме:
1628290

Репутация: 474
Отправить сообщение для ENFIX с помощью ICQ
По умолчанию

Cobalt, прочел, только он криво работает
Цитата:
Сообщение от KSURi  
PS: perldoc Net::IRC
В статье я также хотел немного познакомить с протоколом IRC
 
Ответить с цитированием

  #10  
Старый 19.06.2007, 20:52
Аватар для genom--
genom--
Постоянный
Регистрация: 09.07.2006
Сообщений: 937
Провел на форуме:
1948091

Репутация: 1686


По умолчанию

правильно что убрали из статей --- а так старо как мир -- но чтобы не совсем наезжали на новечка похвалю чуток =) молодца для начала нормально -- я как вспомню что сам сначала писал -- это пиздец был
 
Ответить с цитированием
Ответ



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Irc, добро пожаловать на #antichat madnet Авторские статьи 109 17.06.2010 20:45
Настройка бота вида eggdrop MicRO *nix 0 11.12.2006 03:26
Вводный курс по созданию и настройке Irc ботов KPOT_f!nd Чужие Статьи 0 15.10.2006 02:17
Пишем MailBomber на перле foreva Чужие Статьи 3 08.02.2005 07:13



Здесь присутствуют: 1 (пользователей: 0 , гостей: 1)
 


Быстрый переход




ANTICHAT.XYZ