3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-25 05:19:29 +01:00

Refactor ban/unmute commands

This commit is contained in:
Pragmatic Software 2023-05-04 16:03:24 -07:00
parent c9112ac809
commit b04c06f396
5 changed files with 154 additions and 176 deletions

View File

@ -498,18 +498,20 @@ Bans or mutes a user. If the argument is a nick instead of a hostmask, it will d
The argument can be a comma-separated list of multiple nicks or masks. The argument can be a comma-separated list of multiple nicks or masks.
Usages: Usages:
- `ban <nick or hostmask> [channel [timeout]]` - `ban <mask> [timeout (default: 24h) [reason]] [-c <channel>] [-t <timeout>] [-r <reason>]`
- `mute <nick or hostmask> [channel [timeout]]` - `mute <mask> [timeout (default: 24h) [reason]] [-c <channel>] [-t <timeout>] [-r <reason>]`
If `timeout` is omitted, PBot will ban the user for 24 hours. Timeout can be specified as an relative time in English; for instance, `5 minutes`, `1 month and 2 weeks`, `next thursday`, `friday after next`, `forever` and such. If `timeout` is omitted, PBot will ban the user for 24 hours. Timeout can be specified as an relative time in English; for instance, `5 minutes`, `1 month and 2 weeks`, `next thursday`, `friday after next`, `forever` and such.
If a ban already exists, you may update the timeout or reason at any time.
### unban/unmute ### unban/unmute
Unbans or unmutes a user. If the argument is a nick instead of a hostmask, it will find all bans that match any of that nick's hostmasks or NickServ accounts and unban them. Unbans or unmutes a user. If the argument is a nick instead of a hostmask, it will find all bans that match any of that nick's hostmasks or NickServ accounts and unban them.
The argument can be a comma-separated list of multiple nicks or masks. If the argument is `*` then all bans/mutes for the channel will be removed. The argument can be a comma-separated list of multiple nicks or masks. If the argument is `*` then all bans/mutes for the channel will be removed.
Usages: Usages:
- `unban <nick or hostmask> [channel]` - `unban <nick/hostmask,...> [channel]`
- `unmute <nick or hostmask> [channel]` - `unmute <nick/hostmask,...> [channel]`
### checkban ### checkban
The `checkban` command displays information about an entry in PBot's internal banlist. PBot's internal banlist The `checkban` command displays information about an entry in PBot's internal banlist. PBot's internal banlist
@ -523,7 +525,7 @@ If the `[channel]` option is omitted, the channel in which the command is invoke
Example: Example:
<pragma-> checkban loser!*@* <pragma-> checkban loser!*@*
<PBot> loser!*@* banned in #c on Tue Aug 31 06:41:24 2021 PDT (14d15h ago) by candide!~pbot3@about/c/bot/candide for chat-flooding (2h remaining) <PBot> loser!*@* banned in #c on Tue Aug 31 06:41:24 2021 PDT (14d15h ago) by candide!~pbot3@about/c/bot/candide because chat-flooding (2h remaining)
### checkmute ### checkmute
The `checkmute` command is identical to the [`checkban`](#checkban) command, except for mutes instead of bans. The `checkmute` command is identical to the [`checkban`](#checkban) command, except for mutes instead of bans.
@ -538,8 +540,8 @@ Usage: `invite [channel] <nick>`
### kick ### kick
Removes a user from the channel. `<nick>` can be a comma-separated list of multiple users, optionally containing wildcards. If `[reason]` is omitted, a random insult will be used. Removes a user from the channel. `<nick>` can be a comma-separated list of multiple users, optionally containing wildcards. If `[reason]` is omitted, a random insult will be used.
Usage from channel: `kick <nick> [reason]` Usage from channel: `kick <nick,...> [reason]`
From private message: `kick <channel> <nick> [reason]` From private message: `kick <channel> <nick,...> [reason]`
## Applet-management ## Applet-management
Note that applets are "reloaded" each time they are executed. There is no need to `refresh` after editing an applet. Note that applets are "reloaded" each time they are executed. There is no need to `refresh` after editing an applet.

View File

@ -82,8 +82,8 @@ sub checkban($self, $channel, $mode, $mask) {
$result .= "on $date ($ago) "; $result .= "on $date ($ago) ";
} }
$result .= "by $data->{owner} " if defined $data->{owner}; $result .= "by $data->{owner} " if defined $data->{owner};
$result .= "for $data->{reason} " if defined $data->{reason}; $result .= "because $data->{reason} " if defined $data->{reason};
if (exists $data->{timeout} and $data->{timeout} > 0) { if (exists $data->{timeout} and $data->{timeout} > 0) {
my $duration = concise duration($data->{timeout} - gettimeofday); my $duration = concise duration($data->{timeout} - gettimeofday);

View File

@ -17,15 +17,14 @@ use Time::Duration;
use POSIX qw/strftime/; use POSIX qw/strftime/;
sub initialize($self, %conf) { sub initialize($self, %conf) {
$self->{pbot}->{commands}->register(sub { $self->cmd_banlist(@_) }, "banlist", 0); $self->{pbot}->{commands}->register(sub { $self->cmd_banlist(@_) }, "banlist", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_checkban(@_) }, "checkban", 0); $self->{pbot}->{commands}->register(sub { $self->cmd_checkban(@_) }, "checkban", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_checkmute(@_) }, "checkmute", 0); $self->{pbot}->{commands}->register(sub { $self->cmd_checkmute(@_) }, "checkmute", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_unbanme(@_) }, "unbanme", 0); $self->{pbot}->{commands}->register(sub { $self->cmd_unbanme(@_) }, "unbanme", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_ban_exempt(@_) }, "ban-exempt", 1); $self->{pbot}->{commands}->register(sub { $self->cmd_ban_exempt(@_) }, "ban-exempt", 1);
# add capability to admin group # add capability to admin group
$self->{pbot}->{capabilities}->add('admin', 'can-ban-exempt', 1); $self->{pbot}->{capabilities}->add('admin', 'can-ban-exempt', 1);
} }
sub cmd_banlist($self, $context) { sub cmd_banlist($self, $context) {
@ -48,8 +47,8 @@ sub cmd_banlist($self, $context) {
$result .= "on $date ($ago) "; $result .= "on $date ($ago) ";
} }
$result .= "by $data->{owner} " if defined $data->{owner}; $result .= "by $data->{owner} " if defined $data->{owner};
$result .= "for $data->{reason} " if defined $data->{reason}; $result .= "because $data->{reason} " if defined $data->{reason};
if (defined $data->{timeout} and $data->{timeout} > 0) { if (defined $data->{timeout} and $data->{timeout} > 0) {
my $duration = concise duration($data->{timeout} - gettimeofday); my $duration = concise duration($data->{timeout} - gettimeofday);
$result .= "($duration remaining)"; $result .= "($duration remaining)";
@ -73,8 +72,8 @@ sub cmd_banlist($self, $context) {
$result .= "on $date ($ago) "; $result .= "on $date ($ago) ";
} }
$result .= "by $data->{owner} " if defined $data->{owner}; $result .= "by $data->{owner} " if defined $data->{owner};
$result .= "for $data->{reason} " if defined $data->{reason}; $result .= "because $data->{reason} " if defined $data->{reason};
if (defined $data->{timeout} and $data->{timeout} > 0) { if (defined $data->{timeout} and $data->{timeout} > 0) {
my $duration = concise duration($data->{timeout} - gettimeofday); my $duration = concise duration($data->{timeout} - gettimeofday);
$result .= "($duration remaining)"; $result .= "($duration remaining)";

View File

@ -337,81 +337,7 @@ sub cmd_mode($self, $context) {
} }
sub cmd_ban($self, $context) { sub cmd_ban($self, $context) {
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3); return do_ban_or_mute($self, $context, 'ban');
$channel = '' if not defined $channel;
$length = '' if not defined $length;
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
if ($channel !~ m/^#/) {
$length = "$channel $length";
$length = undef if $length eq ' ';
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
if (not defined $channel or not length $channel) {
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
if (not defined $target) { return "Usage: ban <mask> [channel [timeout (default: 24 hours)]]"; }
my $no_length = 0;
if (not defined $length) {
# TODO: user account length override
$length = $self->{pbot}->{registry}->get_value($channel, 'default_ban_timeout', 0, $context)
// $self->{pbot}->{registry}->get_value('general', 'default_ban_timeout', 0, $context) // 60 * 60 * 24; # 24 hours
$no_length = 1;
} else {
my $error;
($length, $error) = $self->{pbot}->{parsedate}->parsedate($length);
return $error if defined $error;
}
$channel = lc $channel;
$target = lc $target;
my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick');
return "I don't think so." if $target =~ /^\Q$botnick\E!/i;
my $result = '';
my $sep = '';
my @targets = split /,/, $target;
my $immediately = @targets > 1 ? 0 : 1;
my $duration;
foreach my $t (@targets) {
my $mask = lc $self->{pbot}->{banlist}->nick_to_banmask($t);
my $timeout = $self->{pbot}->{banlist}->{banlist}->get_data($channel, $mask, 'timeout') // 0;
if ($no_length && $timeout > 0) {
my $d = duration($timeout - gettimeofday);
$result .= "$sep$mask has $d remaining on their $channel ban";
$sep = '; ';
} else {
$self->{pbot}->{banlist}->ban_user_timed($channel, 'b', $mask, $length, $context->{hostmask}, undef, $immediately);
$duration = $length > 0 ? duration $length : 'all eternity';
if ($immediately) {
$result .= "$sep$mask banned in $channel for $duration";
$sep = '; ';
} else {
$result .= "$sep$mask";
$sep = ', ';
}
}
}
if (not $immediately) {
$result .= " banned in $channel for $duration";
$self->{pbot}->{banlist}->flush_ban_queue;
}
$result = "/msg $context->{nick} $result" if $result !~ m/remaining on their/;
return $result;
} }
sub cmd_unban($self, $context) { sub cmd_unban($self, $context) {
@ -428,7 +354,7 @@ sub cmd_unban($self, $context) {
$channel = $temp; $channel = $temp;
} }
if (not defined $target) { return "Usage: unban <nick/mask> [channel [false value to use unban queue]]"; } if (not defined $target) { return "Usage: unban <nick/mask,...> [channel [false value to use unban queue]]"; }
if (not defined $channel) { if (not defined $channel) {
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from}; $channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
@ -436,7 +362,7 @@ sub cmd_unban($self, $context) {
$immediately = 1 if not defined $immediately; $immediately = 1 if not defined $immediately;
return "Usage for /msg: unban <nick/mask> <channel> [false value to use unban queue]" if $channel !~ /^#/; return "Usage: unban <nick/mask,...> <channel> [false value to use unban queue]" if $channel !~ /^#/;
my @targets = split /,/, $target; my @targets = split /,/, $target;
$immediately = 0 if @targets > 1; $immediately = 0 if @targets > 1;
@ -465,83 +391,7 @@ sub cmd_unban($self, $context) {
} }
sub cmd_mute($self, $context) { sub cmd_mute($self, $context) {
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3); return do_ban_or_mute($self, $context, 'mute');
$channel = '' if not defined $channel;
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
if (not length $channel and $context->{from} !~ m/^#/) {
return "Usage from private message: mute <mask> <channel> [timeout (default: 24 hours)]";
}
if ($channel !~ m/^#/) {
$length = $channel . ' ' . (defined $length ? $length : '');
$length = undef if $length eq ' ';
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from} if not defined $channel;
if ($channel !~ m/^#/) { return "Please specify a channel."; }
if (not defined $target) { return "Usage: mute <mask> [channel [timeout (default: 24 hours)]]"; }
my $no_length = 0;
if (not defined $length) {
$length = $self->{pbot}->{registry}->get_value($channel, 'default_mute_timeout', 0, $context)
// $self->{pbot}->{registry}->get_value('general', 'default_mute_timeout', 0, $context) // 60 * 60 * 24; # 24 hours
$no_length = 1;
} else {
my $error;
($length, $error) = $self->{pbot}->{parsedate}->parsedate($length);
return $error if defined $error;
}
$channel = lc $channel;
$target = lc $target;
my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick');
return "I don't think so." if $target =~ /^\Q$botnick\E!/i;
my $result = '';
my $sep = '';
my @targets = split /,/, $target;
my $immediately = @targets > 1 ? 0 : 1;
my $duration;
foreach my $t (@targets) {
my $mask = lc $self->{pbot}->{banlist}->nick_to_banmask($t);
my $timeout = $self->{pbot}->{banlist}->{quietlist}->get_data($channel, $mask, 'timeout') // 0;
if ($no_length && $timeout > 0) {
my $d = duration($timeout - gettimeofday);
$result .= "$sep$mask has $d remaining on their $channel mute";
$sep = '; ';
} else {
$self->{pbot}->{banlist}->ban_user_timed($channel, 'q', $t, $length, $context->{hostmask}, undef, $immediately);
$duration = $length > 0 ? duration $length : 'all eternity';
if ($immediately) {
$result .= "$sep$mask muted in $channel for $duration";
$sep = '; ';
} else {
$result .= "$sep$mask";
$sep = ', ';
}
}
}
if (not $immediately) {
$result .= " muted in $channel for $duration";
$self->{pbot}->{banlist}->flush_ban_queue;
}
$result = "/msg $context->{nick} $result" if $result !~ m/remaining on their/;
return $result;
} }
sub cmd_unmute($self, $context) { sub cmd_unmute($self, $context) {
@ -558,12 +408,12 @@ sub cmd_unmute($self, $context) {
$channel = $temp; $channel = $temp;
} }
if (not defined $target) { return "Usage: unmute <nick/mask> [channel [false value to use unban queue]]"; } if (not defined $target) { return "Usage: unmute <nick/mask,...> [channel [false value to use unban queue]]"; }
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from} if not defined $channel; $channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from} if not defined $channel;
$immediately = 1 if not defined $immediately; $immediately = 1 if not defined $immediately;
return "Usage for /msg: unmute <nick/mask> <channel> [false value to use unban queue]" if $channel !~ /^#/; return "Usage for /msg: unmute <nick/mask,...> <channel> [false value to use unban queue]" if $channel !~ /^#/;
my @targets = split /,/, $target; my @targets = split /,/, $target;
$immediately = 0 if @targets > 1; $immediately = 0 if @targets > 1;
@ -597,13 +447,13 @@ sub cmd_kick($self, $context) {
if (not $context->{from} =~ /^#/) { if (not $context->{from} =~ /^#/) {
# used in private message # used in private message
if (not $arguments =~ s/^(^#\S+) (\S+)\s*//) { return "Usage from private message: kick <channel> <nick[,nicks...]> [reason]; <nick> may include wildcards"; } if (not $arguments =~ s/^(^#\S+) (\S+)\s*//) { return "Usage from private message: kick <channel> <nick,...> [reason]; <nick> may include wildcards"; }
($channel, $victim) = ($1, $2); ($channel, $victim) = ($1, $2);
} else { } else {
# used in channel # used in channel
if ($arguments =~ s/^(#\S+)\s+(\S+)\s*//) { ($channel, $victim) = ($1, $2); } if ($arguments =~ s/^(#\S+)\s+(\S+)\s*//) { ($channel, $victim) = ($1, $2); }
elsif ($arguments =~ s/^(\S+)\s*//) { ($victim, $channel) = ($1, exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from}); } elsif ($arguments =~ s/^(\S+)\s*//) { ($victim, $channel) = ($1, exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from}); }
else { return "Usage: kick [channel] <nick[,nicks...]> [reason]; <nick> may include wildcards"; } else { return "Usage: kick [channel] <nick,...> [reason]; <nick> may include wildcards"; }
} }
$reason = $arguments; $reason = $arguments;
@ -672,4 +522,131 @@ sub cmd_kick($self, $context) {
return ""; return "";
} }
sub do_ban_or_mute($self, $context, $mode) {
my ($target, $channel, $length, $reason);
my $usage = "usage: $mode <mask,...> [timeout (default: 24h) [reason]] [-c <channel>] [-t <timeout>] [-r <reason>]";
my %opts = (
channel => \$channel,
timeout => \$length,
reason => \$reason,
);
my ($opt_args, $opt_error) = $self->{pbot}->{interpreter}->getopt(
$context->{arguments},
\%opts,
['bundling'],
'channel|c=s',
'timeout|t=s',
'reason|r=s',
);
return "$opt_error -- $usage" if defined $opt_error;
$target = shift @$opt_args;
$length = shift @$opt_args if not defined $length;
$reason = "@$opt_args" if not defined $reason;
$channel = '' if not defined $channel;
$length = '' if not defined $length;
$reason = undef if not length $reason;
if (not defined $target) {
return $usage;
}
if (not length $channel) {
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
if ($channel eq $context->{nick}) {
return "Channel argument is required in private-message; $usage";
}
if ($channel !~ m/^#/) {
return "Bad channel '$channel'; $usage";
}
my $error;
($length, $error) = $self->{pbot}->{parsedate}->parsedate($length);
return $error if defined $error;
$channel = lc $channel;
$target = lc $target;
my $result = '';
my $sep = '';
my @targets = split /,/, $target;
my $immediately = @targets > 1 ? 0 : 1;
my $duration;
foreach my $t (@targets) {
my $mask = lc $self->{pbot}->{banlist}->nick_to_banmask($t);
my $ban = $self->{pbot}->{banlist}->{banlist}->get_data($channel, $mask);
if (defined $ban) {
my $save = 0;
if (defined $reason) {
$ban->{reason} = $reason;
$save = 1;
}
if ($length) {
$ban->{timeout} = gettimeofday + $length;
$save = 1;
}
$self->{pbot}->{banlist}->{banlist}->save if $save;
$result .= "$sep$mask ";
if (not $save) {
$result .= 'is already ';
}
$result .= ($mode eq 'ban' ? 'banned' : 'muted') . " in $channel";
if (defined $ban->{reason}) {
$result .= " because $ban->{reason}";
}
if ($ban->{timeout} > 0) {
my $d = duration($ban->{timeout} - gettimeofday);
$result .= " ($d remaining)";
}
$sep = '; ';
} else {
if (not $length) {
# TODO: user account length override
$length = $self->{pbot}->{registry}->get_value($channel, "default_${mode}_timeout", 0, $context)
// $self->{pbot}->{registry}->get_value('general', "default_${mode}_timeout", 0, $context) // 60 * 60 * 24; # 24 hours
}
$self->{pbot}->{banlist}->ban_user_timed($channel, $mode eq 'ban' ? 'b' : 'q', $mask, $length, $context->{hostmask}, $reason, $immediately);
$duration = $length > 0 ? duration $length : 'all eternity';
if ($immediately) {
$result .= "$sep$mask " . ($mode eq 'ban' ? 'banned' : 'muted') . " in $channel ($duration)";
$result .= " because $reason" if defined $reason;
$sep = '; ';
} else {
$result .= "$sep$mask";
$sep = ', ';
}
}
}
if (not $immediately) {
$result .= ($mode eq 'ban' ? ' banned' : ' muted') . " in $channel for $duration";
$self->{pbot}->{banlist}->flush_ban_queue;
}
$result = "/msg $context->{nick} $result" if $result !~ m/remaining/;
return $result;
}
1; 1;

View File

@ -25,7 +25,7 @@ use PBot::Imports;
# These are set by the /misc/update_version script # These are set by the /misc/update_version script
use constant { use constant {
BUILD_NAME => "PBot", BUILD_NAME => "PBot",
BUILD_REVISION => 4655, BUILD_REVISION => 4656,
BUILD_DATE => "2023-05-04", BUILD_DATE => "2023-05-04",
}; };