--- trunk/irc-logger.pl 2006/02/27 11:54:38 4 +++ trunk/irc-logger.pl 2006/03/01 22:42:21 8 @@ -2,13 +2,27 @@ use strict; $|++; +=head1 NAME + +irc-logger.pl + +=head1 SYNOPSIS + +./irc-logger.pl + +=head1 DESCRIPTION + +log all conversation on irc channel + +=cut + ## CONFIG -my $NICK = 'irc-logger'; +my $NICK = 'irc-logger-dev'; my $CONNECT = {Server => 'irc.freenode.net', Nick => $NICK, - Ircname => 'logger: ask dpavlin@rot13.org' + Ircname => "try /msg $NICK help", }; my $CHANNEL = '#razmjenavjestina'; my $IRC_ALIAS = "log"; @@ -19,35 +33,180 @@ ERROR => "/var/log/apache/error.log", ); +my $DSN = 'DBI:Pg:dbname=irc-logger'; + ## END CONFIG -my $SKIPPING = 0; # if skipping, how many we've done -my $SEND_QUEUE; # cache + use POE qw(Component::IRC Wheel::FollowTail); +use DBI; +use Encode qw/from_to/; + + +my $dbh = DBI->connect($DSN,"","", { RaiseError => 1, AutoCommit => 1 }) || die $DBI::errstr; + +=for SQL schema + +$dbh->do(qq{ +create table log ( + id serial, + time timestamp default now(), + channel text not null, + nick text not null, + message text not null, + primary key(id) +); + +create index log_time on log(time); +create index log_channel on log(channel); +create index log_nick on log(nick); + +}); + +=cut + +my $sth = $dbh->prepare(qq{ +insert into log + (channel, nick, message) +values (?,?,?) +}); + + +my $SKIPPING = 0; # if skipping, how many we've done +my $SEND_QUEUE; # cache POE::Component::IRC->new($IRC_ALIAS); POE::Session->create (inline_states => {_start => sub { - $_[KERNEL]->post($IRC_ALIAS => register => 'all'); - $_[KERNEL]->post($IRC_ALIAS => connect => $CONNECT); + $_[KERNEL]->post($IRC_ALIAS => register => 'all'); + $_[KERNEL]->post($IRC_ALIAS => connect => $CONNECT); }, irc_255 => sub { # server is done blabbing - $_[KERNEL]->post($IRC_ALIAS => join => $CHANNEL); - $_[KERNEL]->post($IRC_ALIAS => join => '#logger'); - $_[KERNEL]->yield("heartbeat"); # start heartbeat -# $_[KERNEL]->yield("my_add", $_) for keys %FOLLOWS; + $_[KERNEL]->post($IRC_ALIAS => join => $CHANNEL); + $_[KERNEL]->post($IRC_ALIAS => join => '#logger'); + $_[KERNEL]->yield("heartbeat"); # start heartbeat +# $_[KERNEL]->yield("my_add", $_) for keys %FOLLOWS; }, irc_public => sub { - my $kernel = $_[KERNEL]; - my $nick = (split /!/, $_[ARG0])[0]; - my $channel = $_[ARG1]->[0]; - my $msg = $_[ARG2]; + my $kernel = $_[KERNEL]; + my $nick = (split /!/, $_[ARG0])[0]; + my $channel = $_[ARG1]->[0]; + my $msg = $_[ARG2]; + + from_to($msg, 'UTF-8', 'ISO-8859-2'); - print "$channel: <$nick> $msg\n"; + print "$channel: <$nick> $msg\n"; + $sth->execute($channel, $nick, $msg); }, + irc_msg => sub { + my $kernel = $_[KERNEL]; + my $nick = (split /!/, $_[ARG0])[0]; + my $msg = $_[ARG2]; + from_to($msg, 'UTF-8', 'ISO-8859-2'); + + my $res = "unknown command '$msg', try /msg $NICK help!"; + + print "<< $msg\n"; + + if ($msg =~ m/^help/i) { + + $res = "usage: /msg $NICK stat - shows user statistics | /msg $NICK last - show backtrace of conversations"; + + } elsif ($msg =~ m/^stat.*?\s*(\d*)/i) { + + my $nr = $1 || 10; + + my $sth = $dbh->prepare(qq{ + select nick,count(*) from log group by nick order by count desc limit $nr + }); + $sth->execute(); + $res = "Top $nr users: "; + my @users; + while (my $row = $sth->fetchrow_hashref) { + push @users,$row->{nick} . ': ' . $row->{count}; + } + $res .= join(" | ", @users); + } elsif ($msg =~ m/^last.*?\s*(\d*)/i) { + + my $nr = $1 || 10; + + my $sth = $dbh->prepare(qq{ + select + time::date as date, + time::time as time, + channel, + nick, + message + from log order by time desc limit $nr + }); + $sth->execute(); + $res = "Last $nr messages: "; + my $last_row = { + date => '', + time => '', + channel => '', + nick => '', + }; + + my @rows; + + while (my $row = $sth->fetchrow_hashref) { + unshift @rows, $row; + } + + my @msgs; + + foreach my $row (@rows) { + + $row->{time} =~ s#\.\d+##; + + my $t; + $t = $row->{date} . ' ' if ($last_row->{date} ne $row->{date}); + $t .= $row->{time}; + + my $msg = ''; + + $msg .= "($t"; + $msg .= ' ' . $row->{channel} if ($last_row->{channel} ne $row->{channel}); + $msg .= ") "; + + $msg .= $row->{nick} . ': ' if ($last_row->{nick} ne $row->{nick}); + + $msg .= $row->{message}; + + push @msgs, $msg; + + $last_row = $row; + } + + foreach my $res (@msgs) { + print "last: $res\n"; + from_to($res, 'ISO-8859-2', 'UTF-8'); + $_[KERNEL]->post( $IRC_ALIAS => privmsg => $nick, $res ); + } + + $res = ''; + } + + if ($res) { + print ">> [$nick] $res\n"; + from_to($res, 'ISO-8859-2', 'UTF-8'); + $_[KERNEL]->post( $IRC_ALIAS => privmsg => $nick, $res ); + } + + }, + irc_505 => sub { + print "# irc_505: ",$_[ARG1], "\n"; + $_[KERNEL]->post( $IRC_ALIAS => privmsg => 'nickserv', "register $NICK" ); + warn "## register $NICK\n"; + }, + irc_registered => sub { + $_[KERNEL]->post( $IRC_ALIAS => privmsg => 'nickserv', "IDENTIFY $NICK" ); + warn "## indetify $NICK\n"; + }, (map { ;"irc_$_" => sub { }} @@ -56,7 +215,9 @@ connected snotice ctcp_action ping notice mode part quit 001 002 003 004 005 250 251 252 253 254 265 266 - 332 333 353 366 372 375 376)), + 332 333 353 366 372 375 376 + 477 + )), _child => sub {}, _default => sub { printf "%s: session %s caught an unhandled %s event.\n",