#!/usr/bin/perl # monbot.pl - example IRC monitoring bot use 5.40.0; use Bot::IRC; my $ch = '#swamp'; # the swamp was important in MUD1 # How long to disable alerts once an alert has gone out. my $shadow_secs = 1789; # Toggle for when the alerts are annoying, or mainly to show how to # setup an interaction with the bot. my $do_checks = 1; # ... but have the checks not happened in a while? my $last_check = time(); # Track when various files have been modified. This could also be done # with an inode change something that gets the news to this bot. my %mtime = ( '/var/mail/someone' => 0, '/etc/passwd' => 0, ); my %shadow; # NOTE the files may not exist, but usually should; in theory you have # configuration management to ensure that the file exist, have the right # permissions, etc. for my $path ( keys %mtime ) { $mtime{$path} = ( stat $path )[9] // 0; $shadow{$path} = 0; } sub checks { my ($bot) = @_; my $now = time; if ( $now > $last_check + $shadow_secs ) { $bot->msg( $ch, "checks $do_checks and no checks in a while..." ); $last_check += $shadow_secs; } return unless $do_checks; my @updates; for my $path ( keys %mtime ) { my $mtime = ( stat $path )[9]; if ( defined $mtime and $mtime != $mtime{$path} ) { if ( $now > $shadow{$path} ) { push @updates, $path; $shadow{$path} = $now + $shadow_secs; } # NOTE no new notifications whilst shadowing is on. Others # may want to be notified about a change that happend during # the shadow peroid when the window drops. $mtime{$path} = $mtime; } } $bot->msg( $ch, "updated: @updates" ) if @updates; $last_check = $now; } sub toggle { my ( $bot, $in, $m ) = @_; my $old = $do_checks; if ( $m->{word} eq 'on' ) { $do_checks = 1; } elsif ( $m->{word} eq 'off' ) { $do_checks = 0; } if ( $do_checks != $old ) { $bot->reply("checks now $m->{word}"); } else { $bot->reply("checks $do_checks"); } } Bot::IRC->new( connect => { nick => 'monbot', name => 'status monitoring bot', server => '192.0.2.42', join => $ch, }, daemon => { stderr_file => 'monbot.out', stdout_file => 'monbot.err', }, plugins => [ { hooks => [ [ { to_me => 1, text => qr{\b(?on|off)\b} }, \&toggle ] ], ticks => [ [ 59, \&checks ] ] } ], )->run;