2014-05-17 22:08:19 +02:00
|
|
|
# File: Registry.pm
|
|
|
|
# Author: pragma_
|
|
|
|
#
|
|
|
|
# Purpose: Provides a centralized registry of configuration settings that can
|
|
|
|
# easily be examined and updated via set/unset commands without restarting.
|
|
|
|
|
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::Registry;
|
2020-02-15 23:38:32 +01:00
|
|
|
|
2020-02-08 20:04:13 +01:00
|
|
|
use parent 'PBot::Class';
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-02-08 20:04:13 +01:00
|
|
|
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 Time::HiRes qw(gettimeofday);
|
|
|
|
use PBot::RegistryCommands;
|
|
|
|
|
|
|
|
sub initialize {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, %conf) = @_;
|
|
|
|
my $filename = $conf{filename} // Carp::croak("Missing filename reference in " . __FILE__);
|
|
|
|
$self->{registry} = PBot::DualIndexHashObject->new(name => 'Registry', filename => $filename, pbot => $self->{pbot});
|
|
|
|
$self->{triggers} = {};
|
|
|
|
$self->{pbot}->{atexit}->register(sub { $self->save; return; });
|
|
|
|
PBot::RegistryCommands->new(pbot => $self->{pbot});
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub load {
|
2020-02-15 23:38:32 +01:00
|
|
|
my $self = shift;
|
|
|
|
$self->{registry}->load;
|
|
|
|
foreach my $section ($self->{registry}->get_keys) {
|
|
|
|
foreach my $item ($self->{registry}->get_keys($section)) { $self->process_trigger($section, $item, $self->{registry}->get_data($section, $item, 'value')); }
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
sub save {
|
2020-02-15 23:38:32 +01:00
|
|
|
my $self = shift;
|
|
|
|
$self->{registry}->save;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add_default {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $type, $section, $item, $value) = @_;
|
|
|
|
$self->add($type, $section, $item, $value, 1);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub add {
|
2020-02-15 23:38:32 +01:00
|
|
|
my $self = shift;
|
|
|
|
my ($type, $section, $item, $value, $is_default) = @_;
|
|
|
|
$type = lc $type;
|
|
|
|
|
|
|
|
if ($is_default) { return if $self->{registry}->exists($section, $item); }
|
|
|
|
|
|
|
|
if (not $self->{registry}->exists($section, $item)) {
|
|
|
|
my $data = {
|
|
|
|
value => $value,
|
|
|
|
type => $type,
|
|
|
|
};
|
|
|
|
$self->{registry}->add($section, $item, $data, 1);
|
|
|
|
} else {
|
|
|
|
$self->{registry}->set($section, $item, 'value', $value, 1);
|
|
|
|
$self->{registry}->set($section, $item, 'type', $type, 1) unless $self->{registry}->exists($section, $item, 'type');
|
|
|
|
}
|
|
|
|
$self->process_trigger($section, $item, $value) unless $is_default;
|
|
|
|
$self->save unless $is_default;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub remove {
|
2020-02-15 23:38:32 +01:00
|
|
|
my $self = shift;
|
|
|
|
my ($section, $item) = @_;
|
|
|
|
$self->{registry}->remove($section, $item);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2015-07-06 02:47:12 +02:00
|
|
|
sub set_default {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $section, $item, $key, $value) = @_;
|
|
|
|
$self->set($section, $item, $key, $value, 1);
|
2015-07-06 02:47:12 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub set {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $section, $item, $key, $value, $is_default, $dont_save) = @_;
|
|
|
|
$key = lc $key if defined $key;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
if ($is_default) { return if $self->{registry}->exists($section, $item, $key); }
|
2016-01-29 22:08:40 +01:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
my $oldvalue = $self->get_value($section, $item, 1) if defined $value;
|
|
|
|
$oldvalue = '' if not defined $oldvalue;
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
my $result = $self->{registry}->set($section, $item, $key, $value, 1);
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
if (defined $key and $key eq 'value' and defined $value and $oldvalue ne $value) { $self->process_trigger($section, $item, $value); }
|
2014-05-17 22:08:19 +02:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
$self->save if !$dont_save && $result =~ m/set to/ && not $is_default;
|
|
|
|
return $result;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub unset {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $section, $item, $key) = @_;
|
|
|
|
$key = lc $key;
|
|
|
|
return $self->{registry}->unset($section, $item, $key);
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub get_value {
|
2020-05-02 05:59:51 +02:00
|
|
|
my ($self, $section, $item, $as_text, $context) = @_;
|
2020-02-15 23:38:32 +01:00
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
my $key = $item;
|
|
|
|
|
|
|
|
# TODO: use user-metadata for this
|
2020-05-02 05:59:51 +02:00
|
|
|
if (defined $context and exists $context->{nick}) {
|
|
|
|
my $context_nick = lc $context->{nick};
|
|
|
|
if ($self->{registry}->exists($section, "$item.nick.$context_nick")) { $key = "$item.nick.$context_nick"; }
|
2019-11-25 22:56:55 +01:00
|
|
|
}
|
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
if ($self->{registry}->exists($section, $key)) {
|
|
|
|
if (not $as_text and $self->{registry}->get_data($section, $key, 'type') eq 'array') { return split /\s*,\s*/, $self->{registry}->get_data($section, $key, 'value'); }
|
|
|
|
else { return $self->{registry}->get_data($section, $key, 'value'); }
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
2020-02-15 23:38:32 +01:00
|
|
|
return undef;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
2014-05-19 11:55:47 +02:00
|
|
|
sub get_array_value {
|
2020-05-02 05:59:51 +02:00
|
|
|
my ($self, $section, $item, $index, $context) = @_;
|
2020-02-15 23:38:32 +01:00
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
my $key = $item;
|
|
|
|
|
|
|
|
# TODO: use user-metadata for this
|
2020-05-02 05:59:51 +02:00
|
|
|
if (defined $context and exists $context->{nick}) {
|
|
|
|
my $context_nick = lc $context->{nick};
|
|
|
|
if ($self->{registry}->exists($section, "$item.nick.$context_nick")) { $key = "$item.nick.$context_nick"; }
|
2019-11-25 22:56:55 +01:00
|
|
|
}
|
2014-05-19 11:55:47 +02:00
|
|
|
|
2020-02-15 23:38:32 +01:00
|
|
|
if ($self->{registry}->exists($section, $key)) {
|
|
|
|
if ($self->{registry}->get_data($section, $key, 'type') eq 'array') {
|
|
|
|
my @array = split /\s*,\s*/, $self->{registry}->get_data($section, $key, 'value');
|
|
|
|
return $array[$index >= $#array ? $#array : $index];
|
|
|
|
} else {
|
|
|
|
return $self->{registry}->get_data($section, $key, 'value');
|
|
|
|
}
|
2014-05-19 11:55:47 +02:00
|
|
|
}
|
2020-02-15 23:38:32 +01:00
|
|
|
return undef;
|
2014-05-19 11:55:47 +02:00
|
|
|
}
|
|
|
|
|
2014-05-17 22:08:19 +02:00
|
|
|
sub add_trigger {
|
2020-02-15 23:38:32 +01:00
|
|
|
my ($self, $section, $item, $subref) = @_;
|
|
|
|
$self->{triggers}->{lc $section}->{lc $item} = $subref;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
sub process_trigger {
|
2020-02-15 23:38:32 +01:00
|
|
|
my $self = shift;
|
|
|
|
my ($section, $item) = @_;
|
|
|
|
$section = lc $section;
|
|
|
|
$item = lc $item;
|
|
|
|
if (exists $self->{triggers}->{$section} and exists $self->{triggers}->{$section}->{$item}) { return &{$self->{triggers}->{$section}->{$item}}(@_); }
|
|
|
|
return undef;
|
2014-05-17 22:08:19 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
1;
|