mirror of
https://github.com/pragma-/pbot.git
synced 2024-11-08 21:19:35 +01:00
124 lines
4.6 KiB
Perl
124 lines
4.6 KiB
Perl
# File: AntiFlood.pm
|
|
# Authoer: pragma_
|
|
#
|
|
# Purpose: Keeps track of which nick has said what and when. Used in
|
|
# conjunction with OperatorStuff and Quotegrabs for kick/quiet on flood
|
|
# and grabbing quotes, respectively.
|
|
|
|
package PBot::AntiFlood;
|
|
|
|
use warnings;
|
|
use strict;
|
|
|
|
BEGIN {
|
|
use vars qw($VERSION);
|
|
$VERSION = $PBot::PBot::VERSION;
|
|
}
|
|
|
|
use Time::HiRes qw(gettimeofday);
|
|
use Carp ();
|
|
|
|
sub new {
|
|
if(ref($_[1]) eq 'HASH') {
|
|
Carp::croak("Options to AntiFlood should be key/value pairs, not hash reference");
|
|
}
|
|
|
|
my ($class, %conf) = @_;
|
|
|
|
my $self = bless {}, $class;
|
|
$self->initialize(%conf);
|
|
return $self;
|
|
}
|
|
|
|
sub initialize {
|
|
my ($self, %conf) = @_;
|
|
|
|
my $pbot = delete $conf{pbot};
|
|
if(not defined $pbot) {
|
|
Carp::croak("Missing pbot reference to AntiFlood");
|
|
}
|
|
|
|
$self->{pbot} = $pbot;
|
|
$self->{FLOOD_CHAT} = 0;
|
|
$self->{FLOOD_JOIN} = 1;
|
|
|
|
$self->{flood_msg_count} = 0;
|
|
$self->{last_timestamp} = gettimeofday;
|
|
$self->{message_history} = {};
|
|
}
|
|
|
|
sub check_flood {
|
|
my ($self, $channel, $nick, $user, $host, $text, $max, $mode) = @_;
|
|
my $now = gettimeofday;
|
|
|
|
$channel = lc $channel;
|
|
|
|
$self->{pbot}->logger->log(sprintf("check flood %-48s %-16s <%10s> %s\n", "$nick!$user\@$host", "[$channel]", , $nick, $text));
|
|
|
|
return if $nick eq $self->{pbot}->botnick;
|
|
|
|
if(exists ${ $self->message_history }{$nick}) {
|
|
#$self->{pbot}->logger->log("nick exists\n");
|
|
|
|
if(not exists ${ $self->message_history }{$nick}{$channel}) {
|
|
#$self->{pbot}->logger->log("adding new channel for existing nick\n");
|
|
${ $self->message_history }{$nick}{$channel}{offenses} = 0;
|
|
${ $self->message_history }{$nick}{$channel}{messages} = [];
|
|
}
|
|
|
|
#$self->{pbot}->logger->log("appending new message\n");
|
|
|
|
push(@{ ${ $self->message_history }{$nick}{$channel}{messages} }, { timestamp => $now, msg => $text, mode => $mode });
|
|
|
|
my $length = $#{ ${ $self->message_history }{$nick}{$channel}{messages} } + 1;
|
|
|
|
#$self->{pbot}->logger->log("length: $length, max nick messages: $MAX_NICK_MESSAGES\n");
|
|
|
|
if($length >= $self->{pbot}->{MAX_NICK_MESSAGES}) {
|
|
my %msg = %{ shift(@{ ${ $self->message_history }{$nick}{$channel}{messages} }) };
|
|
#$self->{pbot}->logger->log("shifting message off top: $msg{msg}, $msg{timestamp}\n");
|
|
$length--;
|
|
}
|
|
|
|
return if not exists ${ $self->{pbot}->channels }{$channel} or ${ $self->{pbot}->channels }{$channel}{is_op} == 0;
|
|
|
|
#$self->{pbot}->logger->log("length: $length, max: $max\n");
|
|
|
|
if($length >= $max) {
|
|
# $self->{pbot}->logger->log("More than $max messages spoken, comparing time differences\n");
|
|
my %msg = %{ @{ ${ $self->message_history }{$nick}{$channel}{messages} }[$length - $max] };
|
|
my %last = %{ @{ ${ $self->message_history }{$nick}{$channel}{messages} }[$length - 1] };
|
|
|
|
#$self->{pbot}->logger->log("Comparing $last{timestamp} against $msg{timestamp}: " . ($last{timestamp} - $msg{timestamp}) . " seconds\n");
|
|
|
|
if($last{timestamp} - $msg{timestamp} <= 10 && not $self->{pbot}->admins->loggedin($channel, "$nick!$user\@$host")) {
|
|
${ $self->message_history }{$nick}{$channel}{offenses}++;
|
|
my $length = ${ $self->message_history }{$nick}{$channel}{offenses} * ${ $self->message_history }{$nick}{$channel}{offenses} * 30;
|
|
if($channel =~ /^#/) { #channel flood (opposed to private message or otherwise)
|
|
if($mode == $self->{FLOOD_CHAT}) {
|
|
# PBot::OperatorStuff::quiet_nick_timed($nick, $channel, $length);
|
|
$self->{pbot}->conn->privmsg($nick, "You have been quieted due to flooding. Please use a web paste service such as http://codepad.org for lengthy pastes. You will be allowed to speak again in $length seconds.");
|
|
$self->{pbot}->logger->log("$nick $channel flood offense ${ $self->message_history }{$nick}{$channel}{offenses} earned $length second quiet\n");
|
|
}
|
|
} else { # private message flood
|
|
$self->{pbot}->logger->log("$nick msg flood offense ${ $self->message_history }{$nick}{$channel}{offenses} earned $length second ignore\n");
|
|
$self->{pbot}->ignorelist->ignore_user("", "floodcontrol", "", "$nick" . '@' . "$host $channel $length");
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
#$self->{pbot}->logger->log("brand new nick addition\n");
|
|
# new addition
|
|
${ $self->message_history }{$nick}{$channel}{offenses} = 0;
|
|
${ $self->message_history }{$nick}{$channel}{messages} = [];
|
|
push(@{ ${ $self->message_history }{$nick}{$channel}{messages} }, { timestamp => $now, msg => $text, mode => $mode });
|
|
}
|
|
}
|
|
|
|
sub message_history {
|
|
my $self = shift;
|
|
return $self->{message_history};
|
|
}
|
|
|
|
1;
|