How do I correctly shutdown a Bot::BasicBot bot (based on POE::Component::IRC)?
Asked Answered
A

2

3

This is a sample script. When I hit Ctrl+C, the bot quits IRC but it reconnects back after some time. How do I shut down the bot correctly?

#!/usr/bin/perl

package main;

my $bot = Perlbot->new (server => 'irc.dal.net');

$SIG{'INT'} = 'Handler';
$SIG{'TERM'} = 'Handler';

sub Handler {
print "\nShutting down bot...\n";
$bot->shutdown('Killed.');
};

$bot->run;

package Perlbot;
use base qw(Bot::BasicBot);

sub connected {
my $self = shift;
$self->join('#codetestchan');
}
Alfreda answered 18/3, 2010 at 16:6 Comment(0)
S
2

I've taken over maintainership of Bot::BasicBot, and as of version 0.82, you can shut it down properly with $bot->shutdown($quit_message).

Snowinsummer answered 30/7, 2010 at 14:41 Comment(0)
S
0

From looking at Bot::BasicBot's documentation and source code, I can't find a graceful way to shut it down. As you demonstrated, calling $bot->shutdown() (which actually sends a shutdown event to POE::Component::IRC) will just cause Bot::BasicBot to reconnect (same with $bot->quit() by the way).

This and other limitations users have run into have caused me to recommend using POE::Component::IRC directly. It has many plugins nowadays for features provided by Bot::BasicBot which were missing when Bot::BasicBot was created. While you may have to type a bit more to get a basic bot up and running, you have much more flexibility. Below is a bot like the one in your example, without using Bot::BasicBot. It will send a quit message to the IRC server when you press CTRL+C, wait until it has been disconnected, then exit:

#!/usr/bin/env perl

use strict;
use warnings;
use POE;
use POE::Component::IRC::State;
use POE::Component::IRC::Common qw(parse_user);
use POE::Component::IRC::Plugin::Connector;
use POE::Component::IRC::Plugin::AutoJoin;

# create our session
POE::Session->create(
    package_states => [
        # event handlers
        (__PACKAGE__) => [qw(_start int irc_join irc_disconnected)]
    ]
);

# start the event loop
POE::Kernel->run();

# session start handler
sub _start {
    my ($kernel, $heap) = @_[KERNEL, HEAP];

    # handle CTRL+C
    $kernel->sig(INT => 'int');

    # create bot object
    my $irc = POE::Component::IRC::State->spawn(
        server => 'irc.freenode.net',
        nick   => 'basic123bot',
        debug  => 1,
    );

    # save $irc in our session's storage heap
    $heap->{irc} = $irc;

    # handle reconnects
    $irc->plugin_add('Connector', POE::Component::IRC::Plugin::Connector->new());

    # handle channel joining
    $irc->plugin_add('AutoJoin', POE::Component::IRC::Plugin::AutoJoin->new(
        Channels => ['#foo123bar'],
    ));

    # connect to IRC
    $irc->yield('connect');
}

# interrupt signal handler
sub int {
    my ($kernel, $heap) = @_[KERNEL, HEAP];

    $heap->{irc}->yield('quit', 'Quitting, bye!');
    $heap->{shutting_down} = 1;
    $kernel->sig_handled();
}

# join handler
sub irc_join {
    my ($who, $chan) = @_[ARG0, ARG1];
    my $irc = $_[HEAP]->{irc};

    my ($nick, $user, $host) = parse_user($who);
    if ($nick eq $irc->nick_name()) {
        # say hello to channel members
        $irc->yield('privmsg', $chan, 'Hello everybody');
    }
}

# disconnect handler
sub irc_disconnected {
    my ($heap) = $_[HEAP];

    # shut down if we disconnected voluntarily
    $heap->{irc}->yield('shutdown') if $heap->{shutting_down};
}
Snowinsummer answered 16/4, 2010 at 11:56 Comment(4)
If you're going to dispense with Bot::BasicBot, might as well look at AnyEvent::IRC or Net::Async::IRC which seem much more performant and have less complicated magic.Heeley
How are they more performant than POE::Component::IRC? Where does it have too much complicated magic? If you have useful information on this, I might be able to improve POE::Component::IRC in this regard.Snowinsummer
It is not really about PoCo-IRC, but about POE, the API is complicated (with Kernels, Loops, Filters, Sessions and Events) requires a lot of boilerplate to get working (compare the size of Poco-IRC, AE-IRC and Net-Async-IRC's modules). As for performance, perhaps this comes down to the complexity of POE, for a useful benchmark see Starman on CPAN, the benchmarks section, Twiggy is the AnyEvent Plack server, and Corona is the Coro (AnyEvent + Coroutines) Plack server.Heeley
From looking at AnyEvent-IRC and Net-Async-IRC, my impression is that their smaller size has very little to do with the event model being used. The core of POE-Component-IRC are the ~1600 lines of code in IRC.pm, most of which deal with mapping the IRC protocol to a useful API for the user. Pretty much everything else in the distro consists of subclasses and plugins that implement optional features on top of that, almost none of which have comparable parts in the other distros you mentioned. They are smaller primarily because they have fewer features.Snowinsummer

© 2022 - 2024 — McMap. All rights reserved.