如何在Perl中实现简单的IRC客户端?

时间:2010-09-30 21:34:49

标签: perl cpan irc

我正在研究一种需要将IRC消息发送到内部IRC频道的工具。这不是一个不断运行的程序,而是一个偶尔会调用的工具,并且需要能够在调用时通过一些消息通知该通道。

我查看了Net::IRC,但它自2004年以来已经死了。所以我查看了它列出的替代方案(Bot::BasicBotPOE::Component::IRC),但这两个方案都需要在POE及其事件循环。类似于Net::Async::IRC的问题也会出现同样的问题,因为它需要在IO :: Async事件循环中运行。

我不是在写一个需要与任何东西进行交互的完整机器人,我只想登录到irc服务器,加入频道,发布一些快速消息然后离开。我不想重新编写整个程序以适应一些框架的事件循环只是为了做到这一点。

那么,对于一个简单的IRC客户端的库的任何建议都不会让我重写我的整个应用程序?

4 个答案:

答案 0 :(得分:6)

使用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。

答案 1 :(得分:5)

Net :: IRC仍然是完全可用的,如果你想做的只是你描述的那么简单,我认为它会做得很好。

也就是说,习惯POE并不是一个坏主意,特别是因为IRC机器人的功能随着时间的推移而增长:)

答案 2 :(得分:3)

请注意,实际上并没有什么能阻止您使用PoCo-IRC或BasicBot。是的,它们在POE下运行,但是POE没有拥有来控制整个应用程序。

如果您只是连接,在IRC上执行某些操作,断开连接以及执行其他操作,您可以确保IRC会话在完成时会自行销毁 - 当没有剩余会话时,{{1}将控制权返回给你的程序。

如果您正在处理更长寿命的连接,但仍希望关闭控制,POE会提供POE::Kernel->runrun_one_timeslice方法,让您可以精确控制POE运行的时间和地点。当然,您必须安排它至少经常运行以响应任何服务器PING并保持套接字缓冲区不会填满。

实际上,Net :: IRC在使用自己的事件循环接管您的应用程序时完全相同 - 除了它不是像POE或AnyEvent这样的命名之类 - 它只是“Net :: IRC事件循环”。这并不意味着您需要完全重写才能使用Net :: IRC,这并不意味着您需要完全重写才能使用POE:)

答案 3 :(得分:0)

使用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;

它连接,发送消息,然后断开连接,这非常适合我的需求。