Пишем простого Irc бота на Pel

Discussion in 'PHP' started by ENFIX, 16 Jun 2007.

  1. ENFIX

    ENFIX Elder - Старейшина

    Joined:
    6 Jun 2006
    Messages:
    175
    Likes Received:
    122
    Reputations:
    75
    Пишем простого Irc бота на Perl

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

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

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

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

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

    Подключаем модули:
    Code:
    use strict; 
    use IO::Socket; 
    
    Подключили =)
    Code:
    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 хранится имя бота (увидите при хуизе)

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

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

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

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

    Основы я вам дал, дальше давайте сами. Прошу сильно не критиковать, ибо только недавно взялся за изучение перл.
    С радостью выслушаю вашу критику и замечания.
    Ниже приведу весь исходник бота.
    Code:
    #!/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"); 
    } 
    }
    
    Спасибо за внимание!
     
    #1 ENFIX, 16 Jun 2007
    Last edited: 17 Jun 2007
    9 people like this.
  2. Piflit

    Piflit Banned

    Joined:
    11 Aug 2006
    Messages:
    1,249
    Likes Received:
    585
    Reputations:
    31
    1. может значение $port тоже надо писать в кавычках?
    2. команды серверу должны начинаться со слеша "/"
     
  3. KSURi

    KSURi tnega AOLPS

    Joined:
    6 Jun 2006
    Messages:
    458
    Likes Received:
    219
    Reputations:
    357
    про perldoc рассказывать даже не пытаюсь=\

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

    кароче незачот
     
    #3 KSURi, 17 Jun 2007
    Last edited by a moderator: 17 Jun 2007
    1 person likes this.
  4. banned

    banned Banned

    Joined:
    20 Nov 2006
    Messages:
    3,324
    Likes Received:
    1,193
    Reputations:
    252
    Зачем из этого делать статью?Выложил бы своего бота, кому надо переделают...
    А вообще для начала дай хотябы одну книгу по языку pel :D :D
     
  5. Thanat0z

    Thanat0z Негрин

    Joined:
    6 Dec 2006
    Messages:
    627
    Likes Received:
    498
    Reputations:
    311
    Перенес в Кодинг
     
  6. ENFIX

    ENFIX Elder - Старейшина

    Joined:
    6 Jun 2006
    Messages:
    175
    Likes Received:
    122
    Reputations:
    75
    >1. может значение $port тоже надо писать в кавычках?
    Числа можно писать без кавычек
    >2. команды серверу должны начинаться со слеша "/"
    Нет, это в мирке и др так сделано. Прочитай документацию.
    >регекс ваще не в тему... надеюсь сам разберешься почему
    Да.. ступанул =) Учу... соррь
    >А вообще для начала дай хотябы одну книгу по языку pel
    Очепятался, бывает ;)

    За критику спасибо!
     
    1 person likes this.
  7. Cobalt

    Cobalt Member

    Joined:
    28 Mar 2007
    Messages:
    5
    Likes Received:
    10
    Reputations:
    0
    Раз пошел такой колинкор предлагаю заценить и это кто не видел: http://www.gfs-team.ru/?act=articles&pact=55 - Perl.Irc Bot

    На сайте есть исходник. Плюс немного улучшенная версия перлового бота.
     
    2 people like this.
  8. KSURi

    KSURi tnega AOLPS

    Joined:
    6 Jun 2006
    Messages:
    458
    Likes Received:
    219
    Reputations:
    357
    В обоих статьях не увидел нормального парсинга...
    Code:
    /^:(.+?)!(.+?)@(.+?)\sPRIVMSG\s(#.+?)\s:(.+?)$/
    # $1 - nick
    # $2 - ident
    # $3 - host
    # $4 - chan
    # $5 - msg text
    
    PS: perldoc Net::IRC
     
    1 person likes this.
  9. ENFIX

    ENFIX Elder - Старейшина

    Joined:
    6 Jun 2006
    Messages:
    175
    Likes Received:
    122
    Reputations:
    75
    Cobalt, прочел, только он криво работает
    В статье я также хотел немного познакомить с протоколом IRC ;)
     
  10. genom--

    genom-- Elder - Старейшина

    Joined:
    9 Jul 2006
    Messages:
    668
    Likes Received:
    416
    Reputations:
    288
    правильно что убрали из статей --- а так старо как мир -- но чтобы не совсем наезжали на новечка похвалю чуток =) молодца для начала нормально -- я как вспомню что сам сначала писал -- это пиздец был
     
  11. UnrealMAN

    UnrealMAN New Member

    Joined:
    2 Sep 2006
    Messages:
    1
    Likes Received:
    0
    Reputations:
    0
    Если уж использовал IO::Socket, то код можно было бы сделать более приятным, пользуясь методами send и recv, т.е.
    $socket->send();
    Хотя не смертельно :)