POE::Component::IRC::CoUoskebrooCko:n:tSreiebnu(t3epd)PPeOrEl::DCoocmupmoennetnatt:i:oInRC::Cookbook::Seen(3p)



NNAAMMEE
       POE::Component::IRC::Cookbook::Seen - Implement the 'seen' command

SSYYNNOOPPSSIISS
       This little bot tracks the whereabouts of users and allows you to
       retrieve that information on command.

        19:59:51 * seen_bot (n=hinrik@pool-71-164-43-32.chrlwv.east.verizon.net) has joined #test_channel1
        19:59:55 <foo> bar
        20:00:16 * seen_bot has quit (Remote closed the connection)
        20:00:27 * seen_bot (n=hinrik@pool-71-164-43-32.chrlwv.east.verizon.net) has joined #test_channel1
        20:00:29 <literal> seen_bot: seen seen_bot
        20:00:29 <seen_bot> literal: I last saw seen_bot at Mon Sep 22 20:00:27 2008 joining #test_channel1
        20:00:34 <literal> seen_bot: seen foo
        20:00:40 <seen_bot> literal: I last saw foo at Mon Sep 22 19:59:56 2008 on #test_channel1 saying: bar
        20:00:45 <literal> seen_bot: seen baz
        20:00:48 <seen_bot> literal: I haven't seen baz

DDEESSCCRRIIPPTTIIOONN
        #!/usr/bin/env perl

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

        use constant {
            USER_DATE     => 0,
            USER_MSG      => 1,
            DATA_FILE     => 'seen',
            SAVE_INTERVAL => 20 * 60,   # save state every 20 mins
        };

        my $seen = { };
        $seen = retrieve(DATA_FILE) if -s DATA_FILE;

        POE::Session->create(
            package_states => [
                main => [ qw(
                    _start
                    irc_botcmd_seen
                    irc_ctcp_action
                    irc_join
                    irc_part
                    irc_public
                    irc_quit
                    save
                )]
            ],
        );

        $poe_kernel->run();

        sub _start {
            my ($kernel, $heap) = @_[KERNEL, HEAP];
            my $irc = POE::Component::IRC::State->spawn(
                Nick   => 'seen_bot',
                Server => 'irc.freenode.net',
            );
            $heap->{irc} = $irc;

            $irc->plugin_add('AutoJoin', POE::Component::IRC::Plugin::AutoJoin->new(
                Channels => [ '#test_channel1', '#test_channel2' ]
            ));

            $irc->plugin_add('BotCommand', POE::Component::IRC::Plugin::BotCommand->new(
                Commands => {
                   seen => 'Usage: seen <nick>'
                }
            ));

            $irc->yield(register => qw(ctcp_action join part public quit botcmd_seen));
            $irc->yield('connect');
            $kernel->delay_set('save', SAVE_INTERVAL);
            return;
        }

        sub save {
            my $kernel = $_[KERNEL];
            warn "storing\n";
            store($seen, DATA_FILE) or die "Can't save state";
            $kernel->delay_set('save', SAVE_INTERVAL);
        }

        sub irc_ctcp_action {
            my $nick = parse_user($_[ARG0]);
            my $chan = $_[ARG1]->[0];
            my $text = $_[ARG2];

            add_nick($nick, "on $chan doing: * $nick $text");
        }

        sub irc_join {
            my $nick = parse_user($_[ARG0]);
            my $chan = $_[ARG1];

            add_nick($nick, "joining $chan");
        }

        sub irc_part {
            my $nick = parse_user($_[ARG0]);
            my $chan = $_[ARG1];
            my $text = $_[ARG2];

            my $msg = 'parting $chan';
            $msg .= " with message '$text'" if defined $text;

            add_nick($nick, $msg);
        }

        sub irc_public {
            my $nick = parse_user($_[ARG0]);
            my $chan = $_[ARG1]->[0];
            my $text = $_[ARG2];

            add_nick($nick, "on $chan saying: $text");
        }

        sub irc_quit {
            my $nick = parse_user($_[ARG0]);
            my $text = $_[ARG1];

            my $msg = 'quitting';
            $msg .= " with message '$text'" if defined $text;

            add_nick($nick, $msg);
        }

        sub add_nick {
            my ($nick, $msg) = @_;
            $seen->{l_irc($nick)} = [time, $msg];
        }

        sub irc_botcmd_seen {
            my ($heap, $nick, $channel, $target) = @_[HEAP, ARG0..$#_];
            $nick = parse_user($nick);
            my $irc = $heap->{irc};

            if ($seen->{l_irc($target)}) {
                my $date = localtime $seen->{l_irc($target)}->[USER_DATE];
                my $msg = $seen->{l_irc($target)}->[USER_MSG];
                $irc->yield(privmsg => $channel, "$nick: I last saw $target at $date $msg");
            }
            else {
                $irc->yield(privmsg => $channel, "$nick: I haven't seen $target");
            }
        }

AAUUTTHHOORR
       Hinrik Oern Sigurd`sson, hinrik.sig@gmail.com



perl v5.12.2                      2010-1P1O-E0:5:Component::IRC::Cookbook::Seen(3p)
