psychoticwolf%carolina.rr.com 617f25f554 Bug 470343 - [SEEN] Ignore !seen in some channels. Patch by Cww <cwwmozilla@gmail.com>, r=Wolf
git-svn-id: svn://10.0.0.236/trunk@256276 18797224-902f-48f8-a5cc-f745e15eee43
2009-02-21 01:53:30 +00:00

291 lines
11 KiB
Plaintext
Executable File

# -*- Mode: perl; tab-width: 4; indent-tabs-mode: nil; -*-
################################
# Seen Module #
################################
package BotModules::Seen;
use vars qw(@ISA);
@ISA = qw(BotModules);
use AnyDBM_File;
use Fcntl;
1;
# SpottedNickChange would be a nice one to do if you
# can solve the problem of working out which channel
# to say stuff in...
# database for seen data
our $seen = {'times' => {}, 'states' => {}};
# the times that the relevant nicks were last seen active
tie(%{$seen->{'times'}}, 'AnyDBM_File', 'seen-times', O_RDWR|O_CREAT, 0666);
# what the relevant nicks were last seen doing
tie(%{$seen->{'states'}}, 'AnyDBM_File', 'seen-states', O_RDWR|O_CREAT, 0666);
sub Help {
my $self = shift;
my ($event) = @_;
my %commands = {
'seen' => 'Says how long it\'s been since the last time someone was seen. Syntax: seen victim',
};
if ($self->isAdmin($event)) {
$commands{'mute'} = 'Stop responding to !seen <name> in a channel unless told directly. Syntax: mute seen in <channel>';
$commands{'unmute'} = 'Start responding to !seen <name> in a channel. Syntax: unmute seen in <channel>';
}
return \%commands;
}
# RegisterConfig - Called when initialised, should call registerVariables
sub RegisterConfig {
my $self = shift;
$self->SUPER::RegisterConfig(@_);
$self->registerVariables(
# [ name, save?, settable? ]
['overrides', 1, 1, {'therapist' => 'Look, dude, I\'m feeling fine, mm\'k?'}], # canned responses
['maxLines', 1, 1, 5],
['directOnlyChannels', 1, 1, []], #list of channels where we're only observing and not responding to !seen unless told.
);
}
sub Told {
my $self = shift;
my ($event, $message) = @_;
my $now = $event->{'time'};
$self->{'_lastSpoken'}->{$event->{'user'}} = $now;
if ($event->{'channel'} ne '') {
my $channel = $event->{'channel'};
$seen->{'times'}->{lc $event->{'from'}} = $now;
$seen->{'states'}->{lc $event->{'from'}} = "saying '$message' to me in $channel.";
}
if ($self->isAdmin($event) and $message =~ /^\s*(un)?mute\s+seen\s+in\s+(\S+)\s*$/osi){
my $mute = !defined($1);
my $channel = lc $2;
$channel =~ s/^\#?/\#/; # Add # character if needed.
$self->MuteOrUnmuteChannel($event, $mute, $channel);
}elsif ($message =~ /^\s*!?seen\s+(\S+?)[\s?.!]*$/osi) {
$self->DoSeen($event, $1);
} else {
return $self->SUPER::Told(@_);
}
return 0; # we've dealt with it, no need to do anything else.
}
sub Heard {
my $self = shift;
my ($event, $message) = @_;
if ($event->{'channel'} ne '') {
my $channel = $event->{'channel'};
$seen->{'times'}->{lc $event->{'from'}} = $event->{'time'};
$seen->{'states'}->{lc $event->{'from'}} = "saying '$message' in $channel.";
}
if (!(grep {$event->{'channel'} eq $_} @{$self->{'directOnlyChannels'}}) and $message =~ /^\s*!seen\s+(\S+)\s*$/osi) {
$self->DoSeen($event, $1);
} else {
return $self->SUPER::Heard(@_);
}
return 0; # we've dealt with it, no need to do anything else.
}
sub Felt {
my $self = shift;
my ($event, $message) = @_;
if ($event->{'channel'} ne '') {
my $nick = $event->{'from'};
my $channel = $event->{'channel'};
$seen->{'times'}->{lc $event->{'from'}} = $event->{'time'};
$seen->{'states'}->{lc $event->{'from'}} = "saying '* $nick $message' in $channel.";
} else {
return $self->SUPER::Felt(@_);
}
return 0; # we've dealt with it, no need to do anything else.
}
sub Saw {
my $self = shift;
my ($event, $message) = @_;
if ($event->{'channel'} ne '') {
my $nick = $event->{'from'};
my $channel = $event->{'channel'};
$seen->{'times'}->{lc $event->{'from'}} = $event->{'time'};
$seen->{'states'}->{lc $event->{'from'}} = "saying '* $nick $message' in $channel.";
} else {
return $self->SUPER::Felt(@_);
}
return 0; # we've dealt with it, no need to do anything else.
}
# SpottedNickChange - Called when someone changes nick
sub SpottedNickChange {
my $self = shift;
my ($event, $from, $to) = @_;
$seen->{'times'}->{lc $event->{'from'}} = $event->{'time'};
$seen->{'states'}->{lc $event->{'from'}} = "changing nick to $to.";
return $self->SUPER::SpottedNickChange(@_);
}
sub DoSeen {
my $self = shift;
my ($event, $who) = @_;
my $pattern;
if (lc $who eq lc $event->{'from'}) {
$self->say($event, 'You\'re right here, duh!');
} elsif (lc $who eq lc $event->{'nick'}) {
$self->say($event, 'I\'m right here, duh!');
} elsif (defined($self->{'overrides'}->{$who})) {
$self->say($event, $self->{'overrides'}->{$who});
} else {
my $regexp;
my @nicksToList = ();
if ($who =~ m!^/(\S+)/$!) { # shouldn't allow mix and match or blank RE or spaces.
$regexp = $1;
my $re = $self->sanitizeRegexp($regexp); # security + safety first!
$re = qr/$re/i; #precompile for performance
if ('' =~ $re){ # will match everything, throw error.
$self->say($event, 'That pattern matches everything, please be more specific.');
return;
}
@nicksToList = grep {$_ =~ $re} (keys %{$seen->{'times'}});
$pattern = 1;
} else {
if ($who =~ /\*/){ # no point going through the motions if there's no wildcard.
$regexp = quotemeta(lc $who);
$regexp =~ s/\\\*/\\S*/g; # replace the escaped * from quotemeta with a \S* (XXX wanted: the ? wildcard)
my $re = qr/^$regexp$/;
if ('' =~ $re){ # will match everything, throw error.
$self->say($event, 'That pattern matches everything, please be more specific.');
return;
}
@nicksToList = grep {$_ =~ $re} (keys %{$seen->{'times'}});
} else {
@nicksToList = (lc $who) if defined($seen->{'times'}{lc $who}); # short circuit for the majority of uses
}
$pattern = 0;
}
if (@nicksToList > $self->{'maxLines'}) { # if it's more than the set threshold, don't flood :)
$self->say($event,"There are more than $self->{'maxLines'} nicks matching that wildcard, please be more specific.");
} elsif (@nicksToList > 0) {
foreach my $nick (@nicksToList) {
my $seconds = $seen->{'times'}->{$nick};
$seconds = $event->{'time'} - $seconds;
my $time = '';
if ($seconds > 90) {
my $minutes = int $seconds / 60;
$seconds %= 60;
if ($minutes > 90) {
my $hours = int $minutes / 60;
$minutes %= 60;
if ($hours > 36) {
my $days = int $hours / 24;
$hours %= 24;
if ($days > 10) {
my $weeks = int $days / 7;
$days %= 7;
if ($weeks > 10) {
# good god, nice connection
}
if ($weeks != 0) {
if ($time ne '') {
$time .= ', ';
}
if ($weeks == 1) {
$time .= "$weeks week";
} else {
$time .= "$weeks weeks";
}
}
}
if ($days != 0) {
if ($time ne '') {
$time .= ', ';
}
if ($days == 1) {
$time .= "$days day";
} else {
$time .= "$days days";
}
}
}
if ($hours != 0) {
if ($time ne '') {
$time .= ', ';
}
if ($hours == 1) {
$time .= "$hours hour";
} else {
$time .= "$hours hours";
}
}
}
if ($minutes != 0) {
if ($time ne '') {
$time .= ', ';
}
if ($minutes == 1) {
$time .= "$minutes minute";
} else {
$time .= "$minutes minutes";
}
}
}
if ($seconds == 0) {
if ($time eq '') {
$time .= 'right about now';
} else {
$time .= ' ago';
}
} else {
if ($time ne '') {
$time .= ' and ';
}
if ($seconds == 1) {
$time .= 'a second ago';
} elsif ($seconds == 2) {
$time .= 'a couple of seconds ago';
} else {
$time .= "$seconds seconds ago";
}
}
my $what = $seen->{'states'}->{$nick};
$self->say($event, "$nick was last seen $time, $what");
}
} else {
my $n = '';
if ($who =~ /^[aeiou]/o) {
$n = 'n';
}
if ($pattern == 1) {
$self->say($event, "I've never seen anyone matching the pattern '$who', sorry.");
} else {
$self->say($event, "I've never seen a$n '$who', sorry.");
}
}
}
}
sub Unload {
untie(%{$seen->{'times'}});
untie(%{$seen->{'states'}});
}
sub MuteOrUnmuteChannel {
my $self = shift;
my ($event, $mute, $channel) = @_;
if ($mute){
if (grep {$_ eq $channel} @{$self->{'directOnlyChannels'}}){
$self->say($event,"I'm already ignoring !seen <name> in $channel.");
} else{
push @{$self->{'directOnlyChannels'}}, $channel;
$self->say($event, "I won't respond to !seen <name> in $channel anymore unless told directly.");
$self->saveConfig();
}
} else {
if (grep {$_ eq $channel} @{$self->{'directOnlyChannels'}}){
@{$self->{'directOnlyChannels'}} = map {$_ ne $channel} @{$self->{'directOnlyChannels'}};
$self->say($event,"I'll start responding to !seen <name> in $channel now.");
$self->saveConfig();
} else{
$self->say($event, "I'm already responding to !seen <name> in $channel.");
}
}
}