簡體   English   中英

如何在Perl中實現簡單的IRC客戶端?

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

我正在研究一種需要將IRC消息發送到內部IRC通道的工具。 這不是一個不斷運行的程序,而是一個偶爾會調用的工具,並且需要能夠在調用時通過一些消息通知該通道。

我查看了Net :: IRC ,但它自2004年以來已經死了。所以我看了它列出的替代品( Bot :: BasicBotPOE :: Component :: IRC ),但這兩個都需要在POE下運行事件循環。 Net :: Async :: IRC之類的問題也出現了同樣的問題,因為它需要在IO :: Async事件循環中運行。

我不是在寫一個需要與任何東西進行交互的完整機器人,我只想登錄到irc服務器,加入頻道,發布一些快速消息然后離開。 我不想重新編寫整個程序以適應一些框架的事件循環只是為了做到這一點。

那么,對於簡單的IRC客戶端的庫的任何建議都不會讓我重寫我的整個應用程序?

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

Net :: IRC仍然是完全可用的,如果你想做的只是你描述的那么簡單,我認為它會做得很好。

也就是說,習慣POE並不是一個壞主意,特別是因為IRC機器人隨着時間的推移往往會增加功能:)

請注意,實際上並沒有什么能阻止您使用PoCo-IRC或BasicBot。 是的,他們POE下運行,但POE 不必有超過你的整個應用程序的控制。

如果您只是連接,在IRC上執行某些操作,斷開連接以及執行其他操作,您可以確保IRC會話在完成時自行銷毀 - 當沒有剩余會話時, POE::Kernel->run將控制權返回給您的程序。

如果您正在處理更長壽命的連接,但仍希望轉向控制,則POE提供run_one_timeslicerun_while方法,使您可以精確控制POE運行的時間和位置。 當然,你必須安排它至少經常運行以響應任何服務器PING並保持套接字緩沖區不被填滿。

實際上,Net :: IRC在使用自己的事件循環接管您的應用程序時完全一樣 - 除了它不是像POE或AnyEvent這樣的命名之類 - 它只是“Net :: IRC事件循環”。 這並不意味着您需要完全重寫才能使用Net :: IRC,這並不意味着您需要完全重寫才能使用POE :)

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

它連接,發送消息,然后斷開連接,這完全符合我的需要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM