Как я могу реализовать простой клиент IRC в Perl? - PullRequest
4 голосов
/ 01 октября 2010

Я работаю над инструментом, который должен отправлять сообщения IRC на внутренний канал IRC.Это не постоянно работающая программа, а скорее инструмент, который будет вызываться изредка и должен иметь возможность уведомлять канал с помощью пары сообщений при его запуске.

Я посмотрел Net:: IRC , но он не работает с 2004 года. Поэтому я посмотрел на альтернативы, которые он перечисляет ( Bot :: BasicBot и POE :: Component :: IRC ), но обаиз них должны быть запущены в POE и его цикле событий.Та же проблема возникает для чего-то вроде Net :: Async :: IRC , поскольку его нужно запускать в цикле событий IO :: Async.

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

Итак, любые рекомендации для библиотеки для простого IRC-клиента, который не сделаетмне переписать все мое приложение?

Ответы [ 4 ]

6 голосов
/ 01 октября 2010

Используйте AnyEvent :: IRC :: Client , пока он использует AnyEvent 'цикл обработки событий', вам не нужно переписывать ваше приложение, чтобы использовать его, вы можете сделать что-то вроде этого:

use AnyEvent;
use AnyEvent::IRC::Client;

с остальными строками вашего модуля;и что-то вроде этого

sub do_irc {
    my $log_chan = '#foobar';
    my $timer; 
    my $c = AnyEvent->condvar;
    my $con = new AnyEvent::IRC::Client;

    $con->reg_cb( join => sub {
        my ($con, $nick, $channel, $is_myself) = @_; 
        if ($is_myself && $channel eq $log_chan) {
           $con->send_chan( $channel, PRIVMSG => ($channel, 'my information') );
           $timer = AnyEvent->timer ( 
                after => 1,
                cb => sub {
                    undef $timer;
                    $con->disconnect('done');
                });
        }
    });

    $con->connect($irc_serv, 6667, { nick => $your_nick } );
    $con->send_srv( JOIN => ($log_chan) );
    $c->wait;
    $con->disconnect;

}

, чтобы установить соединение, оно вернется только после того, как выполнено (обработка ошибок для краткости исключена).Больше ничего в вашем приложении не нужно использовать AnyEvent.

5 голосов
/ 01 октября 2010

Net :: IRC по-прежнему идеально подходит для использования, если все, что вы хотите сделать, это что-то столь же простое, как вы описываете, я думаю, что это будет хорошо.

Тем не менее, привыкание к POE неэто вообще плохая идея, особенно если учесть, что боты IRC со временем имеют тенденцию к росту:)

3 голосов
/ 01 октября 2010

Обратите внимание, что на самом деле ничто не мешает вам использовать PoCo-IRC или BasicBot. Да, они работают под управлением POE, но у POE нет для контроля над всем вашим приложением.

Если вы просто подключаетесь, выполняете какие-то действия в IRC, отключаетесь и делаете другие вещи, вы можете просто убедиться, что сеанс IRC уничтожается сам по себе - когда не осталось ни одного сеанса, POE::Kernel->run будет вернуть управление обратно к вашей программе.

Если вы имеете дело с более долгоживущим соединением, но все еще хотите изменить управление, POE предоставляет run_one_timeslice и run_while методы, которые дают вам точный контроль над тем, когда и где работает POE. Конечно, вы должны организовать его запуск по крайней мере достаточно часто, чтобы он реагировал на любые PING-адреса сервера и предотвращал заполнение буферов сокетов.

На самом деле, Net :: IRC делает то же самое, захватывая ваше приложение своим собственным циклом событий - за исключением того, что это не именованная вещь, такая как POE или AnyEvent - это просто "цикл событий Net :: IRC". Это не значит, что вам нужно полное переписывание для работы с Net :: IRC, и это не значит, что вам нужно полное переписывание для работы с POE :)

0 голосов
/ 11 февраля 2011

Используя ответ от MkV, я смог создать работающий скрипт командной строки:

#!/usr/bin/perl

use strict;
use warnings;
use AnyEvent;
use AnyEvent::IRC::Client;
use Data::Dumper ();
use Getopt::Long;

my %opt = (
    channel => '#ircmsgtest',
    nick    => "ircmsg$$",
    port    => 6667,
    server  => 'irc.freenode.net',
    verbose => undef,
);

GetOptions(\%opt,'channel','nick', 'port', 'server', 'verbose|v');
my $message = shift() || "test message @{[ scalar localtime() ]}";
if ($opt{verbose}) {
    warn "message is: '$message'";
    warn Data::Dumper->Dump([\%opt], [qw(*opt)]);
}

my $c = AnyEvent->condvar;
my $con = AnyEvent::IRC::Client->new;

$con->reg_cb(
    join => sub {
        my ($con, $nick, $channel, $is_myself) = @_; 
        if ($is_myself && $channel eq $opt{channel}) {
            $con->send_chan($channel, PRIVMSG => $channel, $message);
            $c->send;
        }
    }
);

$con->connect($opt{server}, $opt{port}, { nick => $opt{nick} } );
$con->send_srv(JOIN => $opt{channel});
$c->wait;
$con->disconnect;

Он подключается, отправляет сообщение, а затем отключается, что идеально подходит для my потребностей.

...