Bug 131324: Stop the bot from saying the same thing n times in a row.

git-svn-id: svn://10.0.0.236/trunk@147539 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ian%hixie.ch
2003-10-03 21:01:48 +00:00
parent 6a94dcbc5c
commit ca65ee34fb

View File

@@ -184,7 +184,10 @@ my ($server, $port, $localAddr, @nicks, @channels, %channelKeys, $owner,
my $nick = 0;
my $sleepdelay = 60;
my $connectTimeout = 120;
my $delaytime = 1.3;
my $delaytime = 1.3; # amount of time to wait between outputs
my $recentMessageCountLimit = 5; # upper limit
my $recentMessageCountDecrementRate = 0.2; # how much to take off per $delayTime
my $recentMessageCountPenalty = 10; # if we hit the limit, bump it up by this much
my $variablepattern = '[-_:a-zA-Z0-9]+';
my %users = ('admin' => &newPassword('password')); # default password for admin
my %userFlags = ('admin' => 3); # bitmask; 0x1 = admin, 0x2 = delete user a soon as other admin authenticates
@@ -550,6 +553,7 @@ sub on_connect {
# enable the drainmsgqueue
&drainmsgqueue($self);
$self->schedule($delaytime, \&lowerRecentMessageCount);
# signal that we are connected (see next two functions)
$self->{'__mozbot__active'} = 1; # HACK HACK HACK
@@ -831,6 +835,7 @@ sub doLog {
################################
my @msgqueue;
my %recentMessages;
my $timeLastSetAway = 0; # the time since the away flag was last set, so that we don't set it repeatedly.
# Use this routine, always, instead of the standard "privmsg" routine. This
@@ -865,48 +870,50 @@ sub drainmsgqueue {
my $qln = @msgqueue;
if (@msgqueue > 0) {
my ($who, $msg, $do) = getnextmsg();
my $type;
if ($do eq 'msg') {
&debug("->$who: $msg"); # XXX this makes logfiles large quickly...
$self->privmsg($who, $msg); # it seems 'who' can be an arrayref and it works
$type = 'Heard';
} elsif ($do eq 'me') {
&debug("->$who * $msg"); # XXX
$self->me($who, $msg);
$type = 'Saw';
} elsif ($do eq 'notice') {
&debug("=notice=>$who: $msg");
$self->notice($who, $msg);
# $type = 'XXX';
} elsif ($do eq 'ctcpSend') {
{ local $" = ' '; &debug("->$who CTCP PRIVMSG @$msg"); }
my $type = shift @$msg; # @$msg contains (type, args)
$self->ctcp($type, $who, @$msg);
# $type = 'XXX';
} elsif ($do eq 'ctcpReply') {
&debug("->$who CTCP NOTICE $msg");
$self->ctcp_reply($who, $msg);
# $type = 'XXX';
} else {
&debug("Unknown action '$do' intended for '$who' (content: '$msg') ignored.");
}
if (defined($type)) {
&doLog({
'bot' => $self,
'_event' => undef,
'channel' => &toToChannel($self, $who),
'from' => $self->nick,
'target' => $who,
'user' => undef, # XXX
'data' => $msg,
'fulldata' => $msg,
'to' => $who,
'subtype' => undef,
'firsttype' => $type,
'nick' => $self->nick,
'level' => 0,
'type' => $type,
});
unless (weHaveSaidThisTooManyTimesAlready($self, \$who, \$msg, \$do)) {
my $type;
if ($do eq 'msg') {
&debug("->$who: $msg"); # XXX this makes logfiles large quickly...
$self->privmsg($who, $msg); # it seems 'who' can be an arrayref and it works
$type = 'Heard';
} elsif ($do eq 'me') {
&debug("->$who * $msg"); # XXX
$self->me($who, $msg);
$type = 'Saw';
} elsif ($do eq 'notice') {
&debug("=notice=>$who: $msg");
$self->notice($who, $msg);
# $type = 'XXX';
} elsif ($do eq 'ctcpSend') {
{ local $" = ' '; &debug("->$who CTCP PRIVMSG @$msg"); }
my $type = shift @$msg; # @$msg contains (type, args)
$self->ctcp($type, $who, @$msg);
# $type = 'XXX';
} elsif ($do eq 'ctcpReply') {
&debug("->$who CTCP NOTICE $msg");
$self->ctcp_reply($who, $msg);
# $type = 'XXX';
} else {
&debug("Unknown action '$do' intended for '$who' (content: '$msg') ignored.");
}
if (defined($type)) {
&doLog({
'bot' => $self,
'_event' => undef,
'channel' => &toToChannel($self, $who),
'from' => $self->nick,
'target' => $who,
'user' => undef, # XXX
'data' => $msg,
'fulldata' => $msg,
'to' => $who,
'subtype' => undef,
'firsttype' => $type,
'nick' => $self->nick,
'level' => 0,
'type' => $type,
});
}
}
if (@msgqueue > 0) {
if ((@msgqueue % 10 == 0) and (time() - $timeLastSetAway > 5 * $delaytime)) {
@@ -923,6 +930,58 @@ sub drainmsgqueue {
}
}
sub weHaveSaidThisTooManyTimesAlready {
my($self, $who, $msg, $do) = @_;
my $key;
if ($$do eq 'ctcpSend') {
local $" = ',';
$key = "$$who,$$do,@{$$msg}";
} else {
$key = "$$who,$$do,$$msg";
}
my $count = ++$recentMessages{$key};
if ($count >= $recentMessageCountLimit and
$count < $recentMessageCountLimit + 1 and
$$do ne 'ctcpSend') {
$recentMessages{$key} += $recentMessageCountPenalty;
my $text = $$msg;
if (length($msg) > 23) { # arbitrary length (XXX)
$text = substr($text, 0, 20) . '...';
}
$$do = 'me';
$$msg = "was going to say '$text' but has said it too many times today already";
} elsif ($count >= $recentMessageCountLimit) {
if ($$do eq 'msg') {
&debug("MUTED: ->$$who: $$msg");
} elsif ($$do eq 'me') {
&debug("MUTED: ->$$who * $$msg"); # XXX
} elsif ($$do eq 'notice') {
&debug("MUTED: =notice=>$$who: $$msg");
} elsif ($$do eq 'ctcpSend') {
local $" = ' ';
&debug("MUTED: ->$$who CTCP PRIVMSG @{$$msg}");
} elsif ($$do eq 'ctcpReply') {
&debug("MUTED: ->$$who CTCP NOTICE $$msg");
} else {
&debug("MUTED: Unknown action '$$do' intended for '$$who' (content: '$$msg') ignored.");
}
return 1;
}
return 0;
}
sub lowerRecentMessageCount {
my $self = shift;
return unless $self->connected;
foreach my $key (keys %recentMessages) {
$recentMessages{$key} -= $recentMessageCountDecrementRate;
if ($recentMessages{$key} <= 0) {
delete $recentMessages{$key};
}
}
$self->schedule($delaytime, \&lowerRecentMessageCount);
}
# wrap long lines at spaces and hard returns (\n)
# this is for IRC, not for the console -- long can be up to 255
sub splitMessageAcrossLines {