mirror of
https://github.com/pragma-/pbot.git
synced 2024-11-23 12:29:27 +01:00
Commands now stored as hash table
This commit is contained in:
parent
2bda82dd4b
commit
6fd4245b2e
@ -7,7 +7,7 @@
|
|||||||
# SPDX-License-Identifier: MIT
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
package PBot::Core::Commands;
|
package PBot::Core::Commands;
|
||||||
use parent 'PBot::Core::Class', 'PBot::Core::Registerable';
|
use parent 'PBot::Core::Class';
|
||||||
|
|
||||||
use PBot::Imports;
|
use PBot::Imports;
|
||||||
|
|
||||||
@ -16,19 +16,24 @@ use PBot::Utils::LoadModules qw/load_modules/;
|
|||||||
sub initialize {
|
sub initialize {
|
||||||
my ($self, %conf) = @_;
|
my ($self, %conf) = @_;
|
||||||
|
|
||||||
# PBot::Core::Commands can register subrefs
|
# registered commands hash table
|
||||||
$self->PBot::Core::Registerable::initialize(%conf);
|
$self->{commands} = {};
|
||||||
|
|
||||||
# command metadata stored as a HashObject
|
# command metadata stored as a HashObject
|
||||||
$self->{metadata} = PBot::Storage::HashObject->new(pbot => $self->{pbot}, name => 'Command metadata', filename => $conf{filename});
|
$self->{metadata} = PBot::Storage::HashObject->new(
|
||||||
|
pbot => $self->{pbot},
|
||||||
|
name => 'Command metadata',
|
||||||
|
filename => $conf{filename},
|
||||||
|
);
|
||||||
|
|
||||||
$self->{metadata}->load;
|
$self->{metadata}->load;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub register_commands {
|
sub load_commands {
|
||||||
my ($self) = @_;
|
my ($self) = @_;
|
||||||
|
|
||||||
# register commands in Commands directory
|
# load commands in Commands directory
|
||||||
$self->{pbot}->{logger}->log("Registering commands:\n");
|
$self->{pbot}->{logger}->log("Loading commands:\n");
|
||||||
load_modules($self, 'PBot::Core::Commands');
|
load_modules($self, 'PBot::Core::Commands');
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -39,15 +44,21 @@ sub register {
|
|||||||
Carp::croak("Missing parameters to Commands::register");
|
Carp::croak("Missing parameters to Commands::register");
|
||||||
}
|
}
|
||||||
|
|
||||||
# register subref
|
$name = lc $name;
|
||||||
my $command = $self->PBot::Core::Registerable::register($subref);
|
|
||||||
|
|
||||||
# update internal metadata
|
if (exists $self->{commands}->{$name}) {
|
||||||
$command->{name} = lc $name;
|
$self->{pbot}->{logger}->log("Commands: warning: overwriting existing command $name\n");
|
||||||
$command->{requires_cap} = $requires_cap // 0;
|
}
|
||||||
|
|
||||||
|
# register command
|
||||||
|
$self->{commands}->{$name} = {
|
||||||
|
requires_cap => $requires_cap // 0,
|
||||||
|
subref => $subref,
|
||||||
|
};
|
||||||
|
|
||||||
# update command metadata
|
# update command metadata
|
||||||
if (not $self->{metadata}->exists($name)) {
|
if (not $self->{metadata}->exists($name)) {
|
||||||
|
# create new metadata
|
||||||
$self->{metadata}->add($name, { requires_cap => $requires_cap, help => '' }, 1);
|
$self->{metadata}->add($name, { requires_cap => $requires_cap, help => '' }, 1);
|
||||||
} else {
|
} else {
|
||||||
# metadata already exists, just update requires_cap unless it's already set.
|
# metadata already exists, just update requires_cap unless it's already set.
|
||||||
@ -60,22 +71,18 @@ sub register {
|
|||||||
if ($requires_cap) {
|
if ($requires_cap) {
|
||||||
$self->{pbot}->{capabilities}->add("can-$name", undef, 1);
|
$self->{pbot}->{capabilities}->add("can-$name", undef, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $command;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub unregister {
|
sub unregister {
|
||||||
my ($self, $name) = @_;
|
my ($self, $name) = @_;
|
||||||
Carp::croak("Missing name parameter to Commands::unregister") if not defined $name;
|
Carp::croak("Missing name parameter to Commands::unregister") if not defined $name;
|
||||||
$name = lc $name;
|
$name = lc $name;
|
||||||
@{$self->{handlers}} = grep { $_->{name} ne $name } @{$self->{handlers}};
|
delete $self->{commands}->{$name};
|
||||||
}
|
}
|
||||||
|
|
||||||
sub exists {
|
sub exists {
|
||||||
my ($self, $keyword) = @_;
|
my ($self, $name) = @_;
|
||||||
$keyword = lc $keyword;
|
return exists $self->{commands}->{lc $name};
|
||||||
foreach my $command (@{$self->{handlers}}) { return 1 if $command->{name} eq $keyword; }
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub set_meta {
|
sub set_meta {
|
||||||
@ -107,6 +114,12 @@ sub interpreter {
|
|||||||
my $keyword = lc $context->{keyword};
|
my $keyword = lc $context->{keyword};
|
||||||
my $from = $context->{from};
|
my $from = $context->{from};
|
||||||
|
|
||||||
|
# alias to the command
|
||||||
|
my $command = $self->{commands}->{$keyword};
|
||||||
|
|
||||||
|
# bail early if the command doesn't exist
|
||||||
|
return undef if not defined $command;
|
||||||
|
|
||||||
# set the channel the command is in reference to
|
# set the channel the command is in reference to
|
||||||
my ($cmd_channel) = $context->{arguments} =~ m/\B(#[^ ]+)/; # assume command is invoked in regards to first channel-like argument
|
my ($cmd_channel) = $context->{arguments} =~ m/\B(#[^ ]+)/; # assume command is invoked in regards to first channel-like argument
|
||||||
$cmd_channel = $from if not defined $cmd_channel; # otherwise command is invoked in regards to the channel the user is in
|
$cmd_channel = $from if not defined $cmd_channel; # otherwise command is invoked in regards to the channel the user is in
|
||||||
@ -124,84 +137,70 @@ sub interpreter {
|
|||||||
$cap_override = $context->{'cap-override'};
|
$cap_override = $context->{'cap-override'};
|
||||||
}
|
}
|
||||||
|
|
||||||
# go through all commands
|
# does this command require capabilities
|
||||||
# TODO: maybe use a hash lookup
|
my $requires_cap = $self->get_meta($keyword, 'requires_cap') // $command->{requires_cap};
|
||||||
foreach my $command (@{$self->{handlers}}) {
|
|
||||||
|
|
||||||
# is this the command
|
# validate can-command capability
|
||||||
if ($command->{name} eq $keyword) {
|
if ($requires_cap) {
|
||||||
|
if (defined $cap_override) {
|
||||||
|
if (not $self->{pbot}->{capabilities}->has($cap_override, "can-$keyword")) {
|
||||||
|
return "/msg $context->{nick} The $keyword command requires the can-$keyword capability, which cap-override $cap_override does not have.";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (not defined $user) {
|
||||||
|
my ($found_chan, $found_mask) = $self->{pbot}->{users}->find_user_account($cmd_channel, $context->{hostmask}, 1);
|
||||||
|
|
||||||
# does this command require capabilities
|
if (not defined $found_chan) {
|
||||||
my $requires_cap = $self->get_meta($keyword, 'requires_cap') // $command->{requires_cap};
|
return "/msg $context->{nick} You must have a user account to use $keyword. You may use the `my` command to create a personal user account. See `help my`.";
|
||||||
|
|
||||||
if ($requires_cap) {
|
|
||||||
if (defined $cap_override) {
|
|
||||||
if (not $self->{pbot}->{capabilities}->has($cap_override, "can-$keyword")) {
|
|
||||||
return "/msg $context->{nick} The $keyword command requires the can-$keyword capability, which cap-override $cap_override does not have.";
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (not defined $user) {
|
return "/msg $context->{nick} You must have a user account in $cmd_channel to use $keyword. (You have an account in $found_chan.)";
|
||||||
my ($found_chan, $found_mask) = $self->{pbot}->{users}->find_user_account($cmd_channel, $context->{hostmask}, 1);
|
|
||||||
|
|
||||||
if (not defined $found_chan) {
|
|
||||||
return "/msg $context->{nick} You must have a user account to use $keyword. You may use the `my` command to create a personal user account. See `help my`.";
|
|
||||||
} else {
|
|
||||||
return "/msg $context->{nick} You must have a user account in $cmd_channel to use $keyword. (You have an account in $found_chan.)";
|
|
||||||
}
|
|
||||||
} elsif (not $user->{loggedin}) {
|
|
||||||
return "/msg $context->{nick} You must be logged into your user account to use $keyword.";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (not $self->{pbot}->{capabilities}->userhas($user, "can-$keyword")) {
|
|
||||||
return "/msg $context->{nick} The $keyword command requires the can-$keyword capability, which your user account does not have.";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
} elsif (not $user->{loggedin}) {
|
||||||
|
return "/msg $context->{nick} You must be logged into your user account to use $keyword.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($self->get_meta($keyword, 'preserve_whitespace')) {
|
if (not $self->{pbot}->{capabilities}->userhas($user, "can-$keyword")) {
|
||||||
$context->{preserve_whitespace} = 1;
|
return "/msg $context->{nick} The $keyword command requires the can-$keyword capability, which your user account does not have.";
|
||||||
}
|
|
||||||
|
|
||||||
unless ($self->get_meta($keyword, 'dont-replace-pronouns')) {
|
|
||||||
$context->{arguments} = $self->{pbot}->{factoids}->expand_factoid_vars($context, $context->{arguments});
|
|
||||||
$context->{arglist} = $self->{pbot}->{interpreter}->make_args($context->{arguments});
|
|
||||||
}
|
|
||||||
|
|
||||||
# $self->{pbot}->{logger}->log("Disabling nickprefix\n");
|
|
||||||
#$context->{nickprefix_disabled} = 1;
|
|
||||||
|
|
||||||
if ($self->get_meta($keyword, 'background-process')) {
|
|
||||||
# execute this command as a backgrounded process
|
|
||||||
|
|
||||||
# set timeout to command metadata value
|
|
||||||
my $timeout = $self->get_meta($keyword, 'process-timeout');
|
|
||||||
|
|
||||||
# otherwise set timeout to default value
|
|
||||||
$timeout //= $self->{pbot}->{registry}->get_value('processmanager', 'default_timeout');
|
|
||||||
|
|
||||||
# execute command in background
|
|
||||||
$self->{pbot}->{process_manager}->execute_process(
|
|
||||||
$context,
|
|
||||||
sub { $context->{result} = $command->{subref}->($context) },
|
|
||||||
$timeout,
|
|
||||||
);
|
|
||||||
|
|
||||||
# return no output since it will be handled by process manager
|
|
||||||
return '';
|
|
||||||
} else {
|
|
||||||
# execute this command normally
|
|
||||||
my $result = $command->{subref}->($context);
|
|
||||||
|
|
||||||
# disregard undesired command output if command is embedded
|
|
||||||
return undef if $context->{referenced} and $result =~ m/(?:usage:|no results)/i;
|
|
||||||
|
|
||||||
# return command output
|
|
||||||
return $result;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return undef;
|
if ($self->get_meta($keyword, 'preserve_whitespace')) {
|
||||||
|
$context->{preserve_whitespace} = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
unless ($self->get_meta($keyword, 'dont-replace-pronouns')) {
|
||||||
|
$context->{arguments} = $self->{pbot}->{factoids}->expand_factoid_vars($context, $context->{arguments});
|
||||||
|
$context->{arglist} = $self->{pbot}->{interpreter}->make_args($context->{arguments});
|
||||||
|
}
|
||||||
|
|
||||||
|
# execute this command as a backgrounded process?
|
||||||
|
if ($self->get_meta($keyword, 'background-process')) {
|
||||||
|
# set timeout to command metadata value
|
||||||
|
my $timeout = $self->get_meta($keyword, 'process-timeout');
|
||||||
|
|
||||||
|
# otherwise set timeout to default value
|
||||||
|
$timeout //= $self->{pbot}->{registry}->get_value('processmanager', 'default_timeout');
|
||||||
|
|
||||||
|
# execute command in background
|
||||||
|
$self->{pbot}->{process_manager}->execute_process(
|
||||||
|
$context,
|
||||||
|
sub { $context->{result} = $command->{subref}->($context) },
|
||||||
|
$timeout,
|
||||||
|
);
|
||||||
|
|
||||||
|
# return no output since it will be handled by process manager
|
||||||
|
return '';
|
||||||
|
} else {
|
||||||
|
# execute this command normally
|
||||||
|
my $result = $command->{subref}->($context);
|
||||||
|
|
||||||
|
# disregard undesired command output if command is embedded
|
||||||
|
return undef if $context->{embedded} and $result =~ m/(?:usage:|no results)/i;
|
||||||
|
|
||||||
|
# return command output
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
@ -94,12 +94,13 @@ sub cmd_list {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ($context->{arguments} =~ /^commands$/i) {
|
if ($context->{arguments} =~ /^commands$/i) {
|
||||||
|
my $commands = $self->{pbot}->{commands}->{commands};
|
||||||
$text = 'Registered commands: ';
|
$text = 'Registered commands: ';
|
||||||
foreach my $command (sort { $a->{name} cmp $b->{name} } @{$self->{pbot}->{commands}->{handlers}}) {
|
foreach my $command (sort keys %$commands) {
|
||||||
if ($command->{requires_cap}) {
|
if ($commands->{$command}->{requires_cap}) {
|
||||||
$text .= "+$command->{name} ";
|
$text .= "+$command ";
|
||||||
} else {
|
} else {
|
||||||
$text .= "$command->{name} ";
|
$text .= "$command ";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user