X-Git-Url: http://git.ieval.ro/?a=blobdiff_plain;f=lib%2FApp%2FStatsbot.pm;h=fcc79594eefc2656742758b52de94af9b3957aa3;hb=01dcdb6958f188e5aa30f44f06989e4f0cac8e41;hp=6403bee216e20c66937c8d83a37ba28c2fbc888f;hpb=3cdbe25624e004e048af74ae3840af2d5a698e33;p=app-statsbot.git diff --git a/lib/App/Statsbot.pm b/lib/App/Statsbot.pm index 6403bee..fcc7959 100644 --- a/lib/App/Statsbot.pm +++ b/lib/App/Statsbot.pm @@ -4,7 +4,7 @@ use 5.014000; use strict; use warnings; -our $VERSION = '0.001'; +our $VERSION = '0.001002'; use POE; use POE::Component::IRC::State; @@ -13,6 +13,7 @@ use POE::Component::IRC::Plugin::Connector; use POE::Component::IRC::Plugin::CTCP; use IRC::Utils qw/parse_user/; +use Carp; use DBI; use DBD::SQLite; use Text::ParseWords qw/shellwords/; @@ -30,6 +31,15 @@ our $SSL = ''; our @CHANNELS; our $DB = '/var/lib/statsbot/db'; +{ + my %cfg = (debug => \$DEBUG, tick => \$TICK, nickname => \$NICKNAME, server => \$SERVER, port => \$PORT, ssl => \$SSL, channels => \@CHANNELS, db => \$DB); + for my $var (keys %cfg) { + my $key = "STATSBOT_\U$var"; + ${$cfg{$var}} = $ENV{$key} if exists $ENV{$key} && ref $cfg{$var} eq 'SCALAR'; + @{$cfg{$var}} = split ' ', $ENV{$key} if exists $ENV{$key} && ref $cfg{$var} eq 'ARRAY'; + } +} + my $dbh; my $insert; my $update; @@ -37,6 +47,21 @@ my $irc; my %state; +sub _yield { $irc->yield(@_) } +sub _nick_name { $irc->nick_name } + +sub _uptime { + my ($starttime, $nick) = @_; + my $sth=$dbh->prepare('SELECT start,end FROM presence WHERE end > ? AND nick == ?'); + $sth->execute($starttime, $nick); + + my $uptime=0; + while (my ($start, $end)=$sth->fetchrow_array) { + $uptime+=$end-max($start,$starttime) + } + return $uptime +} + sub run { $irc=POE::Component::IRC::State->spawn; POE::Session->create( @@ -53,10 +78,10 @@ sub run { options => { trace => $DEBUG }, ); - $dbh=DBI->connect("dbi:SQLite:dbname=$DB") or die "Cannot connect to database: $!"; + $dbh=DBI->connect("dbi:SQLite:dbname=$DB") or croak "Cannot connect to database: $!"; $dbh->do('CREATE TABLE presence (start INTEGER, end INTEGER, nick TEXT)'); - $insert=$dbh->prepare('INSERT INTO presence (start, end, nick) VALUES (?,?,?)') or die "Cannot prepare query: $!"; - $update=$dbh->prepare('UPDATE presence SET end = ? WHERE start == ? AND nick == ?') or die "Cannot prepare query: $!"; + $insert=$dbh->prepare('INSERT INTO presence (start, end, nick) VALUES (?,?,?)') or croak "Cannot prepare query: $!"; + $update=$dbh->prepare('UPDATE presence SET end = ? WHERE start == ? AND nick == ?') or croak "Cannot prepare query: $!"; $poe_kernel->run(); }; @@ -75,10 +100,12 @@ sub tick{ $_[KERNEL]->delay(tick => $TICK); } -sub bot_start{ +sub bot_start{ ## no critic (RequireArgUnpacking) $_[KERNEL]->delay(tick => $TICK); $irc->plugin_add(CTCP => POE::Component::IRC::Plugin::CTCP->new( + version => "Statsbot/$VERSION", + source => 'https://metacpan.org/pod/App::Statsbot', userinfo => 'A bot which keeps logs and computes channel statistics', clientinfo => 'PING VERSION CLIENTINFO USERINFO SOURCE', )); @@ -92,8 +119,8 @@ sub bot_start{ servers => [ $SERVER ], )); - $irc->yield(register => 'all'); - $irc->yield( + _yield(register => 'all'); + _yield( connect => { Nick => $NICKNAME, Username => 'statsbot', @@ -105,12 +132,20 @@ sub bot_start{ ); } -sub on_fatal{ die "Fatal error: $_[ARG0]" } +sub on_fatal{ croak "Fatal error: $_[ARG0]" } sub on_public{ my ($targets,$message)=@_[ARG1,ARG2]; - my $botnick = $irc->nick_name; - return unless $message =~ /(?:$botnick[:,])?\s*!?presence\s*(.*)/; + my $botnick = _nick_name; + + if ($message =~ /(?:$botnick[:,])?\s*!?help\s*(.*)/sx) { + _yield(privmsg => $targets, 'Try !presence username interval [truncate]'); + _yield(privmsg => $targets, q/For example, !presence mgv '2 days'/); + _yield(privmsg => $targets, q/or !presence mgv '1 year' 4/); + return; + } + + return unless $message =~ /(?:$botnick[:,])?\s*!?presence\s*(.*)/sx; my ($nick, $time, $truncate) = shellwords $1; $truncate//=-1; @@ -123,19 +158,11 @@ sub on_public{ eval { $time = parse_duration $time; } or do { - $irc->yield("cannot parse timespec: $time"); + _yield(privmsg => $targets, "cannot parse timespec: $time"); return; }; - my $starttime=time-$time; - - my $sth=$dbh->prepare('SELECT start,end FROM presence WHERE end > ? AND nick == ?'); - $sth->execute($starttime, $nick); - - my $uptime=0; - while (my ($start, $end)=$sth->fetchrow_array) { - $uptime+=$end-max($start,$starttime) - } + my $uptime=_uptime time-$time, $nick; my $ret; if ($truncate == -1) { @@ -147,7 +174,7 @@ sub on_public{ $time=duration_exact $time; - $irc->yield(privmsg => $targets, "$nick was here $ret during the last $time"); + _yield(privmsg => $targets, "$nick was here $ret during the last $time"); } @@ -180,6 +207,11 @@ a channel. It is able to answer queries of the form "In the last