]>
iEval git - app-statsbot.git/blob - lib/App/Statsbot.pm
7 our $VERSION = '0.001001';
10 use POE
::Component
::IRC
::State
;
11 use POE
::Component
::IRC
::Plugin
::AutoJoin
;
12 use POE
::Component
::IRC
::Plugin
::Connector
;
13 use POE
::Component
::IRC
::Plugin
::CTCP
;
14 use IRC
::Utils qw
/parse_user/;
19 use Text
::ParseWords qw
/shellwords/;
20 use Time
::Duration qw
/duration duration_exact/;
21 use Time
::Duration
::Parse qw
/parse_duration/;
23 use List
::Util qw
/max/;
27 our $NICKNAME = 'statsbot';
28 our $SERVER = 'irc.freenode.net';
32 our $DB = '/var/lib/statsbot/db';
41 sub _yield
{ $irc->yield(@_) }
42 sub _nick_name
{ $irc->nick_name }
45 my ($starttime, $nick) = @_;
46 my $sth=$dbh->prepare('SELECT start,end FROM presence WHERE end > ? AND nick == ?');
47 $sth->execute($starttime, $nick);
50 while (my ($start, $end)=$sth->fetchrow_array) {
51 $uptime+=$end-max
($start,$starttime)
57 $irc=POE
::Component
::IRC
::State
->spawn;
60 _start
=> \
&bot_start
,
61 irc_public
=> \
&on_public
,
63 irc_chan_sync
=> \
&tick
,
66 irc_disconnected
=> \
&on_fatal
,
67 irc_error
=> \
&on_fatal
,
69 options
=> { trace
=> $DEBUG },
72 $dbh=DBI
->connect("dbi:SQLite:dbname=$DB") or croak
"Cannot connect to database: $!";
73 $dbh->do('CREATE TABLE presence (start INTEGER, end INTEGER, nick TEXT)');
74 $insert=$dbh->prepare('INSERT INTO presence (start, end, nick) VALUES (?,?,?)') or croak
"Cannot prepare query: $!";
75 $update=$dbh->prepare('UPDATE presence SET end = ? WHERE start == ? AND nick == ?') or croak
"Cannot prepare query: $!";
80 my %nicks = map {$_ => 1} $irc->nicks;
81 for my $nick (keys %state) {
82 $update->execute(time, $state{$nick}, $nick);
83 delete $state{$nick} unless (exists $nicks{$nick});
89 $insert->execute($state{$_}, $state{$_}, $_);
91 $_[KERNEL
]->delay(tick
=> $TICK);
94 sub bot_start
{ ## no critic (RequireArgUnpacking)
95 $_[KERNEL
]->delay(tick
=> $TICK);
97 $irc->plugin_add(CTCP
=> POE
::Component
::IRC
::Plugin
::CTCP
->new(
98 userinfo
=> 'A bot which keeps logs and computes channel statistics',
99 clientinfo
=> 'PING VERSION CLIENTINFO USERINFO SOURCE',
101 $irc->plugin_add(AutoJoin
=> POE
::Component
::IRC
::Plugin
::AutoJoin
->new(
102 Channels
=> [ @CHANNELS ],
105 Retry_when_banned
=> 60,
107 $irc->plugin_add(Connecter
=> POE
::Component
::IRC
::Plugin
::Connector
->new(
108 servers
=> [ $SERVER ],
111 _yield
(register
=> 'all');
115 Username
=> 'statsbot',
116 Ircname
=> 'Logging and statistics bot',
124 sub on_fatal
{ croak
"Fatal error: $_[ARG0]" }
127 my ($targets,$message)=@_[ARG1
,ARG2
];
128 my $botnick = _nick_name
;
130 if ($message =~ /(?:$botnick[:,])?\s*!?help\s*(.*)/) {
131 _yield
(privmsg
=> $targets, "Try !presence username interval [truncate]");
132 _yield
(privmsg
=> $targets, "For example, !presence mgv '2 days'");
133 _yield
(privmsg
=> $targets, "or !presence mgv '1 year' 4");
137 return unless $message =~ /(?:$botnick[:,])?\s*!?presence\s*(.*)/sx;
138 my ($nick, $time, $truncate) = shellwords
$1;
142 unless (defined $time) {
148 $time = parse_duration
$time;
150 _yield
(privmsg
=> $targets, "cannot parse timespec: $time");
154 my $uptime=_uptime
time-$time, $nick;
157 if ($truncate == -1) {
159 $ret=($uptime/3600).' hours';
161 $ret=duration
$uptime,$truncate;
164 $time=duration_exact
$time;
166 _yield
(privmsg
=> $targets, "$nick was here $ret during the last $time");
177 App::Statsbot - simple IRC bot that tracks time spent in a channel
182 @App::Statsbot::CHANNELS = '#oooes';
183 $App::Statsbot::DEBUG = 1;
186 # Bot will respond to queries of the forms:
187 # < mgv> !presence mgv
188 # < mgv> presence mgv '1 day'
189 # < mgv> BOTNICK: !presence mgv '1 year' 2
190 # < mgv> BOTNICK: presence mgv
194 App::Statsbot is a simple IRC bot that tracks the people that inhabit
195 a channel. It is able to answer queries of the form "In the last <time
196 interval>, how much time did <nick> spend in this channel?".
198 It is configured via global variables in the App::Statsbot package.
204 If true, print some debug information. Defaults to false.
208 How often (in seconds) to poll the channel for nicks. Defaults to 10
213 The nickname of the bot. Defaults to "statsbot".
217 The IRC server. Defaults to "irc.freenode.net".
221 The port. Defaults to 6667.
225 If true, connect via SSL. Defaults to false.
229 Array of channels to connect to. Defaults to an empty array, which is
234 Path to SQLite database. Must be writable. Will be created if it does
235 not exist. Defaults to C</var/lib/statsbot/db>.
239 After configuration, the bot can be started using the B<run> function,
240 which can be called as either a regular function or a method.
248 Marius Gavrilescu, E<lt>marius@ieval.roE<gt>
250 =head1 COPYRIGHT AND LICENSE
252 Copyright (C) 2013-2015 by Marius Gavrilescu
254 This library is free software; you can redistribute it and/or modify
255 it under the same terms as Perl itself, either Perl version 5.20.2 or,
256 at your option, any later version of Perl 5 you may have available.
This page took 0.061302 seconds and 4 git commands to generate.