Added command rate limiting. This adds the config options: ratelimit, ratelimit_amount, ratelimit_time
This commit is contained in:
1 parent
cdb957732c
commit
fa76d4524d
5 files changed
+99
-16
No files matched your search
@@ -144,7 +144,7 @@ if (conf_get('die')) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Check for required configuration values.
|
# Check for required configuration values.
|
||||||
my @REQCVALS = qw(locale expire_logs server fantasy_pf);
|
my @REQCVALS = qw(locale expire_logs server fantasy_pf ratelimit);
|
||||||
foreach my $REQCVAL (@REQCVALS) {
|
foreach my $REQCVAL (@REQCVALS) {
|
||||||
if (!conf_get($REQCVAL)) {
|
if (!conf_get($REQCVAL)) {
|
||||||
my $err = 2;
|
my $err = 2;
|
||||||
@@ -174,6 +174,9 @@ if (!-e "$Bin/../etc/auto.db") {
|
|||||||
}
|
}
|
||||||
our $DB = DBI->connect("dbi:SQLite:dbname=$Bin/../etc/auto.db", q{}, q{});
|
our $DB = DBI->connect("dbi:SQLite:dbname=$Bin/../etc/auto.db", q{}, q{});
|
||||||
|
|
||||||
|
# Ratelimit timer.
|
||||||
|
Core::IRC::clear_usercmd_timer();
|
||||||
|
|
||||||
# Parse privileges.
|
# Parse privileges.
|
||||||
our (%PRIVILEGES);
|
our (%PRIVILEGES);
|
||||||
# If there are any privsets.
|
# If there are any privsets.
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ Auto IRC Bot 3.0: Change Log
|
|||||||
|
|
||||||
3.0 Indev
|
3.0 Indev
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
* Added command rate limiting.
|
||||||
* Added module installer to ./install.
|
* Added module installer to ./install.
|
||||||
* Added a module buildsys.
|
* Added a module buildsys.
|
||||||
* Added a QDB module.
|
* Added a QDB module.
|
||||||
|
|||||||
+33
-1
@@ -11,7 +11,7 @@ use base qw(Exporter);
|
|||||||
our (%LANGE, %MODULE, %EVENTS, %HOOKS, %CMDS);
|
our (%LANGE, %MODULE, %EVENTS, %HOOKS, %CMDS);
|
||||||
our @EXPORT_OK = qw(conf_get trans err awarn timer_add timer_del cmd_add
|
our @EXPORT_OK = qw(conf_get trans err awarn timer_add timer_del cmd_add
|
||||||
cmd_del hook_add hook_del rchook_add rchook_del match_user
|
cmd_del hook_add hook_del rchook_add rchook_del match_user
|
||||||
has_priv mod_exists);
|
has_priv mod_exists ratelimit_check);
|
||||||
|
|
||||||
|
|
||||||
# Initialize a module.
|
# Initialize a module.
|
||||||
@@ -415,6 +415,38 @@ sub has_priv
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Ratelimit check subroutine.
|
||||||
|
sub ratelimit_check
|
||||||
|
{
|
||||||
|
my (%src) = @_;
|
||||||
|
|
||||||
|
# Check if ratelimit is set to on.
|
||||||
|
if ((conf_get('ratelimit'))[0][0] == 1) {
|
||||||
|
if (!defined $Core::IRC::usercmd{$src{nick}.'@'.$src{host}.'/'.$src{svr}}) {
|
||||||
|
# Set a usercmd entry for this user.
|
||||||
|
$Core::IRC::usercmd{$src{nick}.'@'.$src{host}.'/'.$src{svr}} = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
# If the user has not passed the rate limit.
|
||||||
|
if ($Core::IRC::usercmd{$src{nick}.'@'.$src{host}.'/'.$src{svr}} <= (conf_get('ratelimit_amount'))[0][0]) {
|
||||||
|
# Increment their uses and return 1.
|
||||||
|
$Core::IRC::usercmd{$src{nick}.'@'.$src{host}.'/'.$src{svr}}++;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Increment their uses and return 0.
|
||||||
|
$Core::IRC::usercmd{$src{nick}.'@'.$src{host}.'/'.$src{svr}}++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# It isn't. Return 1.
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
# Error subroutine.
|
# Error subroutine.
|
||||||
sub err ## no critic qw(Subroutines::ProhibitBuiltinHomonyms)
|
sub err ## no critic qw(Subroutines::ProhibitBuiltinHomonyms)
|
||||||
{
|
{
|
||||||
|
|||||||
+21
-2
@@ -1,13 +1,15 @@
|
|||||||
# lib/Core/IRC.pm - Core IRC hooks.
|
# lib/Core/IRC.pm - Core IRC hooks and timers.
|
||||||
# Copyright (C) 2010-2011 Xelhua Development Group, et al.
|
# Copyright (C) 2010-2011 Xelhua Development Group, et al.
|
||||||
# This program is free software; rights to this code are stated in doc/LICENSE.
|
# This program is free software; rights to this code are stated in doc/LICENSE.
|
||||||
package Core::IRC;
|
package Core::IRC;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use English qw(-no_match_vars);
|
use English qw(-no_match_vars);
|
||||||
use API::Std qw(hook_add conf_get);
|
use API::Std qw(hook_add timer_add conf_get);
|
||||||
use API::IRC qw(notice usrc);
|
use API::IRC qw(notice usrc);
|
||||||
|
|
||||||
|
our (%usercmd);
|
||||||
|
|
||||||
# CTCP VERSION reply.
|
# CTCP VERSION reply.
|
||||||
hook_add("on_uprivmsg", "ctcp_version_reply", sub {
|
hook_add("on_uprivmsg", "ctcp_version_reply", sub {
|
||||||
my (($svr, @ex)) = @_;
|
my (($svr, @ex)) = @_;
|
||||||
@@ -84,6 +86,23 @@ hook_add("on_connect", "autojoin", sub {
|
|||||||
return 1;
|
return 1;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
sub clear_usercmd_timer
|
||||||
|
{
|
||||||
|
# If ratelimit is set to 1 in config, add this timer.
|
||||||
|
if ((conf_get('ratelimit'))[0][0] eq 1) {
|
||||||
|
# Clear usercmd hash every X seconds.
|
||||||
|
timer_add('clear_usercmd', 2, (conf_get('ratelimit_time'))[0][0], sub {
|
||||||
|
foreach (keys %Core::IRC::usercmd) {
|
||||||
|
$Core::IRC::usercmd{$_} = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1;
|
1;
|
||||||
# vim: set ai sw=4 ts=4:
|
# vim: set ai sw=4 ts=4:
|
||||||
+40
-12
@@ -4,7 +4,7 @@
|
|||||||
package Parser::IRC;
|
package Parser::IRC;
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
use API::Std qw(conf_get err awarn);
|
use API::Std qw(conf_get err awarn trans);
|
||||||
use API::IRC;
|
use API::IRC;
|
||||||
|
|
||||||
# Raw parsing hash.
|
# Raw parsing hash.
|
||||||
@@ -531,17 +531,31 @@ sub privmsg
|
|||||||
# It is coming to us in a private message.
|
# It is coming to us in a private message.
|
||||||
$cmd = uc(substr($ex[3], 1));
|
$cmd = uc(substr($ex[3], 1));
|
||||||
if (defined $API::Std::CMDS{$cmd}) {
|
if (defined $API::Std::CMDS{$cmd}) {
|
||||||
|
# If this is indeed a command, continue.
|
||||||
if ($API::Std::CMDS{$cmd}{lvl} == 1 or $API::Std::CMDS{$cmd}{lvl} == 2) {
|
if ($API::Std::CMDS{$cmd}{lvl} == 1 or $API::Std::CMDS{$cmd}{lvl} == 2) {
|
||||||
if ($API::Std::CMDS{$cmd}{priv}) {
|
# Ensure the level is private or all.
|
||||||
if (API::Std::has_priv(API::Std::match_user(%data), $API::Std::CMDS{$cmd}{priv})) {
|
if (!defined $Core::IRC::usercmd{$data{nick}.'@'.$data{host}}) { $Core::IRC::usercmd{$data{nick}.'@'.$data{host}} = 0; }
|
||||||
&{ $API::Std::CMDS{$cmd}{sub} }(%data);
|
if (API::Std::ratelimit_check(%data)) {
|
||||||
|
# Continue if the user has not passed the ratelimit amount.
|
||||||
|
if ($API::Std::CMDS{$cmd}{priv}) {
|
||||||
|
# If this command requires a privilege...
|
||||||
|
if (API::Std::has_priv(API::Std::match_user(%data), $API::Std::CMDS{$cmd}{priv})) {
|
||||||
|
# Make sure they have it.
|
||||||
|
&{ $API::Std::CMDS{$cmd}{'sub'} }(%data);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Else give them the boot.
|
||||||
|
API::IRC::notice($data{svr}, $data{nick}, API::Std::trans("Permission denied").".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
API::IRC::notice($data{svr}, $data{nick}, API::Std::trans("Permission denied").".");
|
# Else execute the command without any extra checks.
|
||||||
|
&{ $API::Std::CMDS{$cmd}{'sub'} }(%data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
&{ $API::Std::CMDS{$cmd}{sub} }(%data);
|
# Send them a notice about their bad deed.
|
||||||
|
API::IRC::notice($data{svr}, $data{nick}, trans('Rate limit exceeded').q{.});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -556,19 +570,33 @@ sub privmsg
|
|||||||
$rprefix = substr($ex[3], 1, 1);
|
$rprefix = substr($ex[3], 1, 1);
|
||||||
$cmd = uc(substr($ex[3], 2));
|
$cmd = uc(substr($ex[3], 2));
|
||||||
if (defined $API::Std::CMDS{$cmd}) {
|
if (defined $API::Std::CMDS{$cmd}) {
|
||||||
|
# If this is indeed a command, continue.
|
||||||
if ($API::Std::CMDS{$cmd}{lvl} == 0 or $API::Std::CMDS{$cmd}{lvl} == 2) {
|
if ($API::Std::CMDS{$cmd}{lvl} == 0 or $API::Std::CMDS{$cmd}{lvl} == 2) {
|
||||||
if ($API::Std::CMDS{$cmd}{priv}) {
|
# Ensure the level is public or all.
|
||||||
if (API::Std::has_priv(API::Std::match_user(%data), $API::Std::CMDS{$cmd}{priv})) {
|
if (!defined $Core::IRC::usercmd{$data{nick}.'@'.$data{host}}) { $Core::IRC::usercmd{$data{nick}.'@'.$data{host}} = 0; }
|
||||||
&{ $API::Std::CMDS{$cmd}{sub} }(%data) if $rprefix eq $cprefix;
|
if (API::Std::ratelimit_check(%data)) {
|
||||||
|
# Continue if the user has not passed the ratelimit amount.
|
||||||
|
if ($API::Std::CMDS{$cmd}{priv}) {
|
||||||
|
# If this command takes a privilege...
|
||||||
|
if (API::Std::has_priv(API::Std::match_user(%data), $API::Std::CMDS{$cmd}{priv})) {
|
||||||
|
# Make sure they have it.
|
||||||
|
&{ $API::Std::CMDS{$cmd}{'sub'} }(%data) if $rprefix eq $cprefix;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
# Else give them the boot.
|
||||||
|
API::IRC::notice($data{svr}, $data{nick}, API::Std::trans("Permission denied").".");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
API::IRC::notice($data{svr}, $data{nick}, API::Std::trans("Permission denied").".");
|
# Else continue executing without any extra checks.
|
||||||
|
&{ $API::Std::CMDS{$cmd}{'sub'} }(%data) if $rprefix eq $cprefix;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
&{ $API::Std::CMDS{$cmd}{sub} }(%data) if $rprefix eq $cprefix;
|
# Send them a notice about their bad deed.
|
||||||
|
API::IRC::notice($data{svr}, $data{nick}, trans('Rate limit exceeded').q{.});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Trigger event on_cprivmsg.
|
# Trigger event on_cprivmsg.
|
||||||
|
|||||||
Reference in new issue
Block a user