简体   繁体   English

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

[英]How can I implement a simple IRC client in Perl?

I'm working on a tool that needs to send IRC messages to an internal IRC channel. 我正在研究一种需要将IRC消息发送到内部IRC通道的工具。 This isn't a constantly running program, but rather a tool that will be invoked occasionally and needs to be able to notify the channel with a couple of messages when it's invoked. 这不是一个不断运行的程序,而是一个偶尔会调用的工具,并且需要能够在调用时通过一些消息通知该通道。

I looked at Net::IRC , but it's been dead since 2004. So I looked at the alternatives that it lists ( Bot::BasicBot and POE::Component::IRC ) but both of those need to be run under POE and its event loop. 我查看了Net :: IRC ,但它自2004年以来已经死了。所以我看了它列出的替代品( Bot :: BasicBotPOE :: Component :: IRC ),但这两个都需要在POE下运行事件循环。 The same problem occurs for something like Net::Async::IRC since it needs to be run in the IO::Async event loop. Net :: Async :: IRC之类的问题也出现了同样的问题,因为它需要在IO :: Async事件循环中运行。

I'm not writing a full fledged bot that needs to interact with anything, I just want to login to an irc server, join a channel, post some quick messages and then leave. 我不是在写一个需要与任何东西进行交互的完整机器人,我只想登录到irc服务器,加入频道,发布一些快速消息然后离开。 I don't want to have to re-write this whole program to fit inside of some framework's event loop just to do this. 我不想重新编写整个程序以适应一些框架的事件循环只是为了做到这一点。

So, any recommendations for a library for a simple IRC client that won't make me rewrite my whole app? 那么,对于简单的IRC客户端的库的任何建议都不会让我重写我的整个应用程序?

Use AnyEvent::IRC::Client , while it is using the AnyEvent 'event loop', you don't have to rewrite your app to use it, you can do something like this: 使用AnyEvent :: IRC :: Client ,当它使用AnyEvent'事件循环'时,你不必重写你的应用程序来使用它,你可以这样做:

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

with the rest of your module use lines; 与你的模块的其余部分一起使用线; and something like this 和这样的事情

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;

}

to do the connection, it will only return once it is done (error handling left out for brevity). 要进行连接,它只会在完成后返回(为简洁而省略错误处理)。 Nothing else in your app needs to use AnyEvent. 您的应用中的任何其他内容都不需要使用AnyEvent。

Net::IRC is still perfectly usable, if all you want to do is something as simple as you're describing, I think it would do just fine. Net :: IRC仍然是完全可用的,如果你想做的只是你描述的那么简单,我认为它会做得很好。

That said, getting used to POE isn't a bad idea at all, especially since IRC bots tend to grow in functionality over time :) 也就是说,习惯POE并不是一个坏主意,特别是因为IRC机器人随着时间的推移往往会增加功能:)

Note that there's actually nothing stopping you from using PoCo-IRC or BasicBot. 请注意,实际上并没有什么能阻止您使用PoCo-IRC或BasicBot。 Yes, they run under POE, but POE doesn't have to have control over your entire app. 是的,他们POE下运行,但POE 不必有超过你的整个应用程序的控制。

If you're just connecting, doing some stuff on IRC, disconnecting, and doing other things, you can just make sure that the IRC session destroys itself when it's done -- when there are no sessions remaining, POE::Kernel->run will return control right back to your program. 如果您只是连接,在IRC上执行某些操作,断开连接以及执行其他操作,您可以确保IRC会话在完成时自行销毁 - 当没有剩余会话时, POE::Kernel->run将控制权返回给您的程序。

If you're dealing with a longer-lived connection, but you still want to turn the control around, POE provides run_one_timeslice and run_while methods that give you fine control over when and where POE runs. 如果您正在处理更长寿命的连接,但仍希望转向控制,则POE提供run_one_timeslicerun_while方法,使您可以精确控制POE运行的时间和位置。 Of course, you have to arrange for it to run at least often enough to respond to any server PINGs and keep the socket buffers from filling up. 当然,你必须安排它至少经常运行以响应任何服务器PING并保持套接字缓冲区不被填满。

Actually, Net::IRC does exactly the same thing in taking over your app with its own event loop -- except it's not a named thing like POE or AnyEvent -- it's just "the Net::IRC event loop". 实际上,Net :: IRC在使用自己的事件循环接管您的应用程序时完全一样 - 除了它不是像POE或AnyEvent这样的命名之类 - 它只是“Net :: IRC事件循环”。 It doesn't mean you need a total rewrite to work with Net::IRC, and it doesn't mean you need a total rewrite to work with POE :) 这并不意味着您需要完全重写才能使用Net :: IRC,这并不意味着您需要完全重写才能使用POE :)

Using the answer from MkV, I was able to create a working command-line script: 使用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;

It connects, sends the message, and then disconnects, which is perfect for my needs. 它连接,发送消息,然后断开连接,这完全符合我的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM