From 3da8e22e4efff97a31257b736534ae73e6c68ef8 Mon Sep 17 00:00:00 2001 From: Pragmatic Software Date: Sat, 11 Jan 2020 17:46:44 -0800 Subject: [PATCH] Add `op` and `deop` commands --- PBot/ChanOpCommands.pm | 120 ++++++++++++++++++++++++++++++++++++++++- PBot/Interpreter.pm | 15 ++++++ 2 files changed, 133 insertions(+), 2 deletions(-) diff --git a/PBot/ChanOpCommands.pm b/PBot/ChanOpCommands.pm index dc47a3c0..37e653f6 100644 --- a/PBot/ChanOpCommands.pm +++ b/PBot/ChanOpCommands.pm @@ -47,6 +47,8 @@ sub initialize { $pbot->{commands}->register(sub { return $self->kick_user(@_) }, "kick", 10); $pbot->{commands}->register(sub { return $self->checkban(@_) }, "checkban", 0); $pbot->{commands}->register(sub { return $self->checkmute(@_) }, "checkmute", 0); + $pbot->{commands}->register(sub { return $self->op_user(@_) }, "op", 10); + $pbot->{commands}->register(sub { return $self->deop_user(@_) }, "deop", 10); $pbot->{commands}->register(sub { return $self->mode(@_) }, "mode", 40); $pbot->{commands}->register(sub { return $self->invite(@_) }, "invite", 10); } @@ -61,7 +63,7 @@ sub invite { # add current channel as default channel if ($stuff->{arglist}[0] !~ m/^#/) { if ($from =~ m/^#/) { - unshift @{$stuff->{arglist}}, $from; + $self->{pbot}->{interpreter}->unshift_arg($stuff->{arglist}, $from); } else { return "Usage from private message: invite "; } @@ -73,6 +75,120 @@ sub invite { return ""; } +sub op_user { + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; + my $channel = $from; + my $result = ''; + + if ($channel !~ m/^#/) { + # from message + $channel = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}); + $result = 'Done.'; + if (not defined $channel) { + return "Usage from message: op [nick]"; + } elsif ($channel !~ m/^#/) { + return "$channel is not a channel. Usage from message: op [nick]"; + } + } + + $channel = lc $channel; + if (not $self->{pbot}->{chanops}->can_gain_ops($channel)) { + return "I am not configured as an OP for $channel. See `chanset` command for more information."; + } + + # add $nick to $args if no argument + if (not $self->{pbot}->{interpreter}->arglist_size($stuff->{arglist})) { + $self->{pbot}->{interpreter}->unshift_arg($stuff->{arglist}, $nick); + } + + my $max_modes = $self->{pbot}->{ircd}->{MODES} // 1; + my $mode = '+'; + my $list = ''; + my $i = 0; + + foreach my $targets ($self->{pbot}->{interpreter}->unquoted_args($stuff->{arglist})) { + foreach my $target (split /,/, $targets) { + $mode .= 'o'; + $list .= "$target "; + $i++; + + if ($i >= $max_modes) { + my $args = "$channel $mode $list"; + $stuff->{arglist} = $self->{pbot}->{interpreter}->make_args($args); + $self->mode($from, $nick, $user, $host, $args, $stuff); + $mode = '+'; + $list = ''; + $i = 0; + } + } + } + + if ($i) { + my $args = "$channel $mode $list"; + $stuff->{arglist} = $self->{pbot}->{interpreter}->make_args($args); + $self->mode($from, $nick, $user, $host, $args, $stuff); + } + + return $result; +} + +sub deop_user { + my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; + my $channel = $from; + my $result = ''; + + if ($channel !~ m/^#/) { + # from message + $channel = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}); + $result = 'Done.'; + if (not defined $channel) { + return "Usage from message: deop [nick]"; + } elsif ($channel !~ m/^#/) { + return "$channel is not a channel. Usage from message: deop [nick]"; + } + } + + $channel = lc $channel; + if (not $self->{pbot}->{chanops}->can_gain_ops($channel)) { + return "I am not configured as an OP for $channel. See `chanset` command for more information."; + } + + # add $nick to $args if no argument + if (not $self->{pbot}->{interpreter}->arglist_size($stuff->{arglist})) { + $self->{pbot}->{interpreter}->unshift_arg($stuff->{arglist}, $nick); + } + + my $max_modes = $self->{pbot}->{ircd}->{MODES} // 1; + my $mode = '-'; + my $list = ''; + my $i = 0; + + foreach my $targets ($self->{pbot}->{interpreter}->unquoted_args($stuff->{arglist})) { + foreach my $target (split /,/, $targets) { + $mode .= 'o'; + $list .= "$target "; + $i++; + + if ($i >= $max_modes) { + my $args = "$channel $mode $list"; + $stuff->{arglist} = $self->{pbot}->{interpreter}->make_args($args); + $self->mode($from, $nick, $user, $host, $args, $stuff); + $mode = '-'; + $list = ''; + $i = 0; + } + } + } + + if ($i) { + my $args = "$channel $mode $list"; + $stuff->{arglist} = $self->{pbot}->{interpreter}->make_args($args); + $self->mode($from, $nick, $user, $host, $args, $stuff); + } + + return $result; +} + sub mode { my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; @@ -83,7 +199,7 @@ sub mode { # add current channel as default channel if ($stuff->{arglist}[0] !~ m/^#/) { if ($from =~ m/^#/) { - unshift @{$stuff->{arglist}}, $from; + $self->{pbot}->{interpreter}->unshift_arg($stuff->{arglist}, $from); } else { return "Usage from private message: mode "; } diff --git a/PBot/Interpreter.pm b/PBot/Interpreter.pm index 3b310c39..a222480e 100644 --- a/PBot/Interpreter.pm +++ b/PBot/Interpreter.pm @@ -678,6 +678,14 @@ sub arglist_size { return @$args / 2; } +# unshifts new argument to front +sub unshift_arg { + my ($self, $args, $arg) = @_; + splice @$args, @$args / 2, 0, $arg; # add quoted argument + unshift @$args, $arg; # add first argument + return @$args; +} + # shifts first argument off array of arguments sub shift_arg { my ($self, $args) = @_; @@ -686,6 +694,13 @@ sub shift_arg { return shift @$args; } +# returns list of unquoted arguments +sub unquoted_args { + my ($self, $args) = @_; + return undef if not @$args; + return @$args[0 .. @$args / 2 - 1]; +} + # splits array of arguments into array with overflow arguments filling up last position # split_args(qw/dog cat bird hamster/, 3) => ("dog", "cat", "bird hamster") sub split_args {