2014-05-17 22:08:19 +02:00
|
|
|
# File: RegistryCommands.pm
|
|
|
|
# Author: pragma_
|
|
|
|
#
|
|
|
|
# Purpose: Commands to introspect and update Registry
|
|
|
|
|
2017-03-05 22:33:31 +01:00
|
|
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
2014-05-17 22:08:19 +02:00
|
|
|
package PBot::RegistryCommands;
|
|
|
|
|
|
|
|
use warnings;
|
|
|
|
use strict;
|
|
|
|
|
2019-07-11 03:40:53 +02:00
|
|
|
use feature 'unicode_strings';
|
|
|
|
|
2014-05-17 22:08:19 +02:00
|
|
|
use Carp ();
|
|
|
|
|
|
|
|
sub new {
|
2019-05-28 18:19:42 +02:00
|
|
|
if (ref($_[1]) eq 'HASH') {
|
2014-05-17 22:08:19 +02:00
|
|
|
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
|
|
|
|
}
|
|
|
|
|
|
|
|
my ($class, %conf) = @_;
|
|
|
|
my $self = bless {}, $class;
|
|
|
|
$self->initialize(%conf);
|
|
|
|
return $self;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub initialize {
|
|
|
|
my ($self, %conf) = @_;
|
|
|
|
|
2019-08-25 02:31:24 +02:00
|
|
|
my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
|
2014-05-17 22:08:19 +02:00
|
|
|
$self->{pbot} = $pbot;
|
2019-06-26 18:34:19 +02:00
|
|
|
|
2019-12-28 05:20:07 +01:00
|
|
|
$pbot->{commands}->register(sub { return $self->regset(@_) }, "regset", 60);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regunset(@_) }, "regunset", 60);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regshow(@_) }, "regshow", 0);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regsetmeta(@_) }, "regsetmeta", 60);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regunsetmeta(@_) }, "regunsetmeta", 60);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regchange(@_) }, "regchange", 60);
|
|
|
|
$pbot->{commands}->register(sub { return $self->regfind(@_) }, "regfind", 0);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
sub regset {
|
2014-05-17 22:08:19 +02:00
|
|
|
my $self = shift;
|
2018-08-09 02:38:57 +02:00
|
|
|
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $usage = "Usage: regset <section>.<item> <value>";
|
|
|
|
|
|
|
|
# support "<section>.<key>" syntax in addition to "<section> <key>"
|
|
|
|
my $section = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}) // return $usage;
|
|
|
|
my ($item, $value);
|
|
|
|
if ($section =~ m/^(.+?)\.(.+)$/) {
|
|
|
|
($section, $item) = ($1, $2);
|
|
|
|
($value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 1);
|
|
|
|
} else {
|
|
|
|
($item, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
if (not defined $section or not defined $item or not defined $value) {
|
|
|
|
return $usage;
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
$self->{pbot}->{registry}->add('text', $section, $item, $value);
|
|
|
|
|
|
|
|
$self->{pbot}->{logger}->log("$nick!$user\@$host set registry entry [$section] $item => $value\n");
|
|
|
|
return "$section.$item set to $value";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
sub regunset {
|
2014-05-17 22:08:19 +02:00
|
|
|
my $self = shift;
|
2018-08-09 02:38:57 +02:00
|
|
|
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $usage = "Usage: regunset <section>.<item>";
|
|
|
|
|
|
|
|
# support "<section>.<key>" syntax in addition to "<section> <key>"
|
|
|
|
my $section = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}) // return $usage;
|
|
|
|
my $item;
|
|
|
|
if ($section =~ m/^(.+?)\.(.+)$/) {
|
|
|
|
($section, $item) = ($1, $2);
|
|
|
|
} else {
|
|
|
|
($item) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 1);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
if (not defined $section or not defined $item) {
|
|
|
|
return $usage;
|
|
|
|
}
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
|
|
|
|
if (not exists $self->{pbot}->{registry}->{registry}->{hash}->{$section}) {
|
2020-01-05 06:26:18 +01:00
|
|
|
return "No such registry section $section.";
|
|
|
|
}
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
if (not exists $self->{pbot}->{registry}->{registry}->{hash}->{$section}->{$item}) {
|
2020-01-05 06:26:18 +01:00
|
|
|
return "No such item $item in section $section.";
|
|
|
|
}
|
|
|
|
|
|
|
|
$self->{pbot}->{logger}->log("$nick!$user\@$host removed registry entry $section.$item\n");
|
|
|
|
$self->{pbot}->{registry}->remove($section, $item);
|
|
|
|
return "$section.$item deleted from registry";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
sub regsetmeta {
|
2014-05-17 22:08:19 +02:00
|
|
|
my $self = shift;
|
2018-08-09 02:38:57 +02:00
|
|
|
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $usage = "Usage: regsetmeta <section>.<item> [key [value]]";
|
|
|
|
|
|
|
|
# support "<section>.<key>" syntax in addition to "<section> <key>"
|
|
|
|
my $section = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}) // return $usage;
|
|
|
|
my ($item, $key, $value);
|
|
|
|
if ($section =~ m/^(.+?)\.(.+)$/) {
|
|
|
|
($section, $item) = ($1, $2);
|
|
|
|
($key, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
|
|
|
|
} else {
|
|
|
|
($item, $key, $value) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
if (not defined $section or not defined $item) {
|
|
|
|
return $usage;
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
$key = undef if not length $key;
|
|
|
|
$value = undef if not length $value;
|
|
|
|
|
|
|
|
return $self->{pbot}->{registry}->set($section, $item, $key, $value);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
sub regunsetmeta {
|
2014-05-17 22:08:19 +02:00
|
|
|
my $self = shift;
|
2018-08-09 02:38:57 +02:00
|
|
|
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $usage = "Usage: regunsetmeta <section>.<item> <key>";
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
# support "<section>.<key>" syntax in addition to "<section> <key>"
|
|
|
|
my $section = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}) // return $usage;
|
|
|
|
my ($item, $key);
|
|
|
|
if ($section =~ m/^(.+?)\.(.+)$/) {
|
|
|
|
($section, $item) = ($1, $2);
|
|
|
|
($key) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 1);
|
|
|
|
} else {
|
|
|
|
($item, $key) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
if (not defined $section or not defined $item or not defined $key) {
|
|
|
|
return $usage;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
return $self->{pbot}->{registry}->unset($section, $item, $key);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub regshow {
|
|
|
|
my $self = shift;
|
2018-08-09 02:38:57 +02:00
|
|
|
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
|
2020-01-15 03:10:53 +01:00
|
|
|
my $registry = $self->{pbot}->{registry}->{registry}->{hash};
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $usage = "Usage: regshow <section>.<item>";
|
|
|
|
|
|
|
|
# support "<section>.<key>" syntax in addition to "<section> <key>"
|
|
|
|
my $section = $self->{pbot}->{interpreter}->shift_arg($stuff->{arglist}) // return $usage;
|
|
|
|
my $item;
|
|
|
|
if ($section =~ m/^(.+?)\.(.+)$/) {
|
|
|
|
($section, $item) = ($1, $2);
|
|
|
|
} else {
|
|
|
|
($item) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 1);
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $section or not defined $item) {
|
2020-01-05 06:26:18 +01:00
|
|
|
return $usage;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not exists $registry->{$section}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "No such registry section $section.";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not exists $registry->{$section}->{$item}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "No such registry item $item in section $section.";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($registry->{$section}->{$item}->{private}) {
|
2020-01-05 06:26:18 +01:00
|
|
|
return "$section.$item: <private>";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-05 06:26:18 +01:00
|
|
|
my $result = "$section.$item: $registry->{$section}->{$item}->{value}";
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($registry->{$section}->{$item}->{type} eq 'array') {
|
2014-05-17 22:08:19 +02:00
|
|
|
$result .= ' [array]';
|
|
|
|
}
|
|
|
|
|
|
|
|
return $result;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub regfind {
|
|
|
|
my $self = shift;
|
|
|
|
my ($from, $nick, $user, $host, $arguments) = @_;
|
2020-01-15 03:10:53 +01:00
|
|
|
my $registry = $self->{pbot}->{registry}->{registry}->{hash};
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2014-05-20 05:28:43 +02:00
|
|
|
my $usage = "Usage: regfind [-showvalues] [-section section] <regex>";
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $arguments) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return $usage;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2014-05-20 05:28:43 +02:00
|
|
|
my ($section, $showvalues);
|
2014-05-17 22:08:19 +02:00
|
|
|
|
|
|
|
$section = $1 if $arguments =~ s/-section\s+([^\b\s]+)//i;
|
2020-01-18 08:00:55 +01:00
|
|
|
$showvalues = 1 if $arguments =~ s/-showvalues?//i;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
|
|
|
$arguments =~ s/^\s+//;
|
|
|
|
$arguments =~ s/\s+$//;
|
|
|
|
$arguments =~ s/\s+/ /g;
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($arguments eq "") {
|
2014-05-20 05:28:43 +02:00
|
|
|
return $usage;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-18 08:00:55 +01:00
|
|
|
$section = lc $section if defined $section;;
|
2020-01-15 03:10:53 +01:00
|
|
|
|
2014-05-17 22:08:19 +02:00
|
|
|
my ($text, $last_item, $last_section, $i);
|
|
|
|
$last_section = "";
|
|
|
|
$i = 0;
|
|
|
|
eval {
|
2017-09-10 07:37:11 +02:00
|
|
|
use re::engine::RE2 -strict => 1;
|
2014-05-17 22:08:19 +02:00
|
|
|
foreach my $section_key (sort keys %{ $registry }) {
|
2020-01-15 03:10:53 +01:00
|
|
|
next if defined $section and $section_key ne $section;
|
2014-05-17 22:08:19 +02:00
|
|
|
foreach my $item_key (sort keys %{ $registry->{$section_key} }) {
|
2020-01-15 03:10:53 +01:00
|
|
|
next if $item_key eq '_name';
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($registry->{$section_key}->{$item_key}->{private}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
# do not match on value if private
|
|
|
|
next if $item_key !~ /$arguments/i;
|
|
|
|
} else {
|
|
|
|
next if $registry->{$section_key}->{$item_key}->{value} !~ /$arguments/i and $item_key !~ /$arguments/i;
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
|
|
|
|
$i++;
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($section_key ne $last_section) {
|
2014-05-20 05:28:43 +02:00
|
|
|
$text .= "[$section_key]\n";
|
2014-05-17 22:08:19 +02:00
|
|
|
$last_section = $section_key;
|
|
|
|
}
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($showvalues) {
|
|
|
|
if ($registry->{$section_key}->{$item_key}->{private}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
$text .= " $item_key = <private>\n";
|
|
|
|
} else {
|
|
|
|
$text .= " $item_key = $registry->{$section_key}->{$item_key}->{value}" . ($registry->{$section_key}->{$item_key}->{type} eq 'array' ? " [array]\n" : "\n");
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
$text .= " $item_key\n";
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
$last_item = $item_key;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
return "/msg $nick $arguments: $@" if $@;
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($i == 1) {
|
2014-05-17 22:08:19 +02:00
|
|
|
chop $text;
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($registry->{$last_section}->{$last_item}->{private}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "Found one registry entry: [$last_section] $last_item: <private>";
|
|
|
|
} else {
|
|
|
|
return "Found one registry entry: [$last_section] $last_item: $registry->{$last_section}->{$last_item}->{value}" . ($registry->{$last_section}->{$last_item}->{type} eq 'array' ? ' [array]' : '');
|
|
|
|
}
|
2014-05-17 22:08:19 +02:00
|
|
|
} else {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "Found $i registry entries:\n$text" unless $i == 0;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
|
|
|
my $sections = (defined $section ? "section $section" : 'any sections');
|
2014-05-19 23:34:24 +02:00
|
|
|
return "No matching registry entries found in $sections.";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub regchange {
|
|
|
|
my $self = shift;
|
|
|
|
my ($from, $nick, $user, $host, $arguments) = @_;
|
|
|
|
my ($section, $item, $delim, $tochange, $changeto, $modifier);
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (defined $arguments) {
|
2020-01-05 06:26:18 +01:00
|
|
|
if ($arguments =~ /^(.+?)\.([^\s]+)\s+s(.)/ or $arguments =~ /^([^\s]+) ([^\s]+)\s+s(.)/) {
|
2014-05-17 22:08:19 +02:00
|
|
|
$section = $1;
|
2019-06-26 18:34:19 +02:00
|
|
|
$item = $2;
|
2014-05-17 22:08:19 +02:00
|
|
|
$delim = $3;
|
|
|
|
}
|
2019-06-26 18:34:19 +02:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if ($arguments =~ /$delim(.*?)$delim(.*)$delim(.*)?$/) {
|
2019-06-26 18:34:19 +02:00
|
|
|
$tochange = $1;
|
2014-05-17 22:08:19 +02:00
|
|
|
$changeto = $2;
|
|
|
|
$modifier = $3;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not defined $section or not defined $item or not defined $changeto) {
|
2020-01-05 06:26:18 +01:00
|
|
|
return "Usage: regchange <section>.<item> s/<pattern>/<replacement>/";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2020-01-15 03:10:53 +01:00
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
|
|
|
|
my $registry = $self->{pbot}->{registry}->{registry}->{hash};
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not exists $registry->{$section}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "No such registry section $section.";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not exists $registry->{$section}->{$item}) {
|
2014-05-20 05:28:43 +02:00
|
|
|
return "No such registry item $item in section $section.";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
my $ret = eval {
|
|
|
|
use re::engine::RE2 -strict => 1;
|
2019-05-28 18:19:42 +02:00
|
|
|
if (not $registry->{$section}->{$item}->{value} =~ s|$tochange|$changeto|) {
|
2020-01-05 06:26:18 +01:00
|
|
|
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: failed to change $section.$item 's$delim$tochange$delim$changeto$delim$modifier\n");
|
|
|
|
return "/msg $nick Change $section.$item failed.";
|
2014-05-17 22:08:19 +02:00
|
|
|
} else {
|
2020-01-05 06:26:18 +01:00
|
|
|
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed $section.$item 's/$tochange/$changeto/\n");
|
2014-05-17 22:08:19 +02:00
|
|
|
$self->{pbot}->{registry}->process_trigger($section, $item, 'value', $registry->{$section}->{$item}->{value});
|
|
|
|
$self->{pbot}->{registry}->save;
|
2020-01-05 06:26:18 +01:00
|
|
|
return "$section.$item set to $registry->{$section}->{$item}->{value}";
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
};
|
2020-01-05 06:26:18 +01:00
|
|
|
return "/msg $nick Failed to change $section.$item: $@" if $@;
|
2014-05-17 22:08:19 +02:00
|
|
|
return $ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
1;
|