App-RoboBot
view release on metacpan or search on metacpan
lib/App/RoboBot/Plugin.pm view on Meta::CPAN
sub ns {
my ($self) = @_;
my $ns = lc($self->name);
$ns =~ s{::}{.}g;
return $ns;
}
sub process {
my ($self, $message, $command, $rpl, @args) = @_;
$self->log->debug(sprintf('Processing command %s request (%d arguments).', $command, scalar(@args)));
# Short-circuit if this plugin is disabled on the current message's network.
return if exists $message->network->disabled_plugins->{lc($self->name)};
# Remove namespace from command if present (by the time we reach this point, we
# already know what plugin namespace we're in)
if ($command =~ m{/(.*)$}) {
$command = $1;
}
$command = lc($command);
return $message->response->raise("Invalid command processor executed.")
unless exists $self->commands->{$command};
my $method = $self->commands->{$command}{'method'};
$self->log->debug(sprintf('Command %s handled by plugin method %s.', $command, $method));
# Ensure that the nick is permitted to call the function.
if (exists $message->sender->denied_functions->{$command}) {
$self->log->warn(sprintf('Nick %s has been denied evaluation of the function %s on network %s.',
$message->sender->name, $command, $message->network->name));
return $message->response->raise('You are not permitted to call the function (%s).', $command);
}
# If the function takes "keyed" arguments (e.g. a Symbol followed by an
# expression or value) extract those now into a hash that will be passed
# to the function's implementation separately from any remainder arguments.
my $keyed = {};
if ($self->commands->{$command}{'keyed_args'}) {
($keyed, @args) = $self->extract_keyed_args($message, $rpl, @args);
}
# By default, we pre-process all arguments, but some plugins can opt out
# of this to handle things like conditional evaluations or loops
unless (exists $self->commands->{$command}{'preprocess_args'} && $self->commands->{$command}{'preprocess_args'} == 0) {
$self->log->debug(sprintf('Preprocessing %d arguments for command %s.', scalar(@args), $command));
# TODO: There are much better ways of deciding how to pass a symbol
# that happens to have the name of a function as a function, or
# as a string, than this.
my $pass_funcs = exists $self->commands->{$command}{'take_funcs'} && $self->commands->{$command}{'take_funcs'} == 1 ? 1 : 0;
my @new_args;
foreach my $arg (@args) {
if (blessed($arg) && $arg->can('evaluate')) {
if (($arg->type eq 'Function' || $arg->type eq 'Macro') && !$pass_funcs) {
push(@new_args, $arg->value);
} else {
push(@new_args, $arg->evaluate($message, $rpl));
}
} else {
push(@new_args, $arg);
}
}
@args = @new_args;
}
if ($self->commands->{$command}{'keyed_args'}) {
$self->log->debug(sprintf('Invoking plugin method %s with keyed arguments.', $method));
return $self->$method($message, $command, $rpl, $keyed, @args);
} else {
$self->log->debug(sprintf('Invoking plugin method %s.', $method));
return $self->$method($message, $command, $rpl, @args);
}
}
sub hook_before {
my ($self, $message) = @_;
return $message unless $self->has_before_hook;
my $hook = $self->before_hook;
$self->log->debug(sprintf('Invoking before_hook method %s on message.', $hook));
return $self->$hook($message);
}
sub hook_after {
my ($self, $message) = @_;
return $message unless $self->has_after_hook;
my $hook = $self->after_hook;
$self->log->debug(sprintf('Invoking after_hook method %s on message.', $hook));
return $self->$hook($message);
}
sub extract_keyed_args {
my ($self, $message, $rpl, @args) = @_;
my %keyed = ();
my @remaining;
while (@args) {
my $k = shift(@args);
if ($k->type eq 'Symbol') {
$keyed{$k->value}
= @args && $args[0]->type ne 'Symbol'
? shift(@args)->evaluate($message, $rpl)
: 1;
} else {
push(@remaining, $k);
}
}
( run in 0.500 second using v1.01-cache-2.11-cpan-39bf76dae61 )