Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw

POE::Component::IRC event loop stuck?

by GodEater (Initiate)
on Aug 12, 2015 at 09:32 UTC ( #1138295=perlquestion: print w/replies, xml ) Need Help??

GodEater has asked for the wisdom of the Perl Monks concerning the following question:

I've been tasked with writing an IRC bot which will join channels on the internal IRC system here, and post messages to channels which don't appear to be used anymore, warning any potential users that the channel is about to be retired. Our IRC system has about 6,500 channels which need these messages posted to them, and the IRC server we use (a customised fork of Hybrid) limits concurrent channel joins to 100 per connection. In an attempt not to hit this limit, the code I've got is this :

if ($channel_list->{$channel}{joined}) { # If we're already joined, privmsg immediately $logger->info("Trying to message $channel"); $data_entry->notified('true'); $data_entry->update; $irc->yield(privmsg => $msg_channel, $message); $irc->yield(part => $msg_channel); } else { # Otherwise join, and let the join event do the privmsg $logger->info("Trying to join $channel"); $data_entry->notified('true'); $data_entry->update; $irc->yield(join => $msg_channel); }

i.e. it will see if we're joined already, and if we are, try to post the notification message, and then immediately part. If we're not joined, it tries to join first (and the join event will fire the message sending).

The problem is the code never seems to run the

$irc->yield(part => $msg_channel);

line, as eventually I start getting irc_405 events back from the IRC server saying the code has joined too many channels. Anyone got any idea what am I doing wrong?

Replies are listed 'Best First'.
Re: POE::Component::IRC event loop stuck?
by Corion (Patriarch) on Aug 12, 2015 at 09:42 UTC

    I think you need to limit your join messages. As far as I understand your code, your bot will try to join all channels, and only after that post the message and part the channel.

    Also, your sequence flow seems odd, because in the else branch, you set $data_entry->notified('true'), which seems odd.

    I would try looking at either the following batched sequence:

    $irc->yield(join => $msg_channel); $irc->yield(privmsg => $msg_channel, $message); $irc->yield(part => $msg_channel);

    ... or a sequence that keeps track of all channels and their state:

    my @channels_to_notify = get_unused_channels(); my @joined_channels; my @notified_channels; # in a timer, every minute or so: while(@channels_to_notify) { if( @joined_channels < 100 ) { my $name = shift @channels_to_notify; join_channel( $name ); }; }; # This should trigger on the message when you(r bot) joins a channel sub on_join { my ($name) = @_; $irc->yield(privmsg => $msg_channel, $message); $irc->yield(part => $msg_channel); }; # This should trigger on the message when you(r bot) parts a channel sub on_part { my ($name) = @_; @joined_channels = grep { $_ ne $name } @joined_channels; };

      I was trying to limit the amount of code I posted, but clearly I have left some key pieces out ;). Here is the joina nd part events from the code I'm working with, which try to do some of what you have suggested:

      sub irc_join { my $heap = $_[HEAP]; my $nick = ( split /!/, $_[ARG0] )[0]; my $channel = $_[ARG1]; my $hash_channel = (split /#/, $channel)[1]; my $irc = $_[SENDER]->get_heap(); my $joincount = $heap->{joincount}; my $batch_of_channels = $heap->{batch_of_channels_hash}; my $verbose = $heap->{verbose}; my $message = $heap->{cleanup_message}; my $nickname = $heap->{nickname}; my $channel_db = $heap->{channel_info_db}; $logger->info("Got join event from $channel as $$nickname - person + joining was $nick"); if ( $nick eq $irc->nick_name() ) { # Number of channels joined $$joincount++; $logger->info("Which is $$joincount channels joined now"); # Only send the message if we're the one joining $logger->info("Messaging $channel"); # Mark the channel as joined $batch_of_channels->{$hash_channel}{joined} = 1; # Mark the channel as "being messaged" in the database, so it +won't get selected in by mistake my $data_entry = $channel_db->resultset('Channel')->find({name + => $hash_channel}); $data_entry->being_messaged('true'); $data_entry->update; $irc->yield(privmsg => $channel, $message); $irc->yield(part => $channel); } return; } sub irc_part { my $heap = $_[HEAP]; my $nick = ( split /!/, $_[ARG0] )[0]; my $channel = $_[ARG1]; my $hash_channel = (split /#/, $channel)[1]; my $part_msg = $_[ARG2]; my $irc = $_[SENDER]->get_heap(); my $joincount = $heap->{joincount}; my $batch_of_channels = $heap->{batch_of_channels_hash}; my $verbose = $heap->{verbose}; my $message = $heap->{cleanup_message}; my $nickname = $heap->{nickname}; my $channel_db = $heap->{channel_info_db}; $logger->info("Got part event from $channel as $$nickname - person + leaving was $nick"); if ($nick eq $irc->nick_name()) { $$joincount--; $logger->info("Left a channel, so $$joincount channels joined +now"); $batch_of_channels->{$hash_channel}{joined} = 0; } }

        I've written an extensive bot using Net-IRC...even though this is an out dated and no longer developed Perl Module I have used it since it was originally coded and has run on a good sized IRC network since 2001.

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1138295]
Approved by marto
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others surveying the Monastery: (2)
As of 2022-05-19 03:25 GMT
Find Nodes?
    Voting Booth?
    Do you prefer to work remotely?

    Results (71 votes). Check out past polls.