3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-29 23:39:24 +01:00

No longer directly access HashObject internals

This commit is contained in:
Pragmatic Software 2020-02-11 21:49:43 -08:00
parent a490f65525
commit afe4638b0a
6 changed files with 130 additions and 183 deletions

View File

@ -44,8 +44,7 @@ sub has {
return 0; return 0;
} }
foreach my $c (keys %{$cap_data}) { foreach my $c ($self->{caps}->get_keys($cap)) {
next if $c eq '_name';
return 1 if $c eq $subcap and $cap_data->{$c}; return 1 if $c eq $subcap and $cap_data->{$c};
return 1 if $self->has($c, $subcap, $depth); return 1 if $self->has($c, $subcap, $depth);
} }
@ -56,7 +55,7 @@ sub userhas {
my ($self, $user, $cap) = @_; my ($self, $user, $cap) = @_;
return 0 if not defined $user; return 0 if not defined $user;
return 1 if $user->{$cap}; return 1 if $user->{$cap};
foreach my $key (keys %{$user}) { foreach my $key (keys %$user) {
next if $key eq '_name'; next if $key eq '_name';
next if not $user->{$key}; next if not $user->{$key};
return 1 if $self->has($key, $cap); return 1 if $self->has($key, $cap);
@ -67,10 +66,9 @@ sub userhas {
sub exists { sub exists {
my ($self, $cap) = @_; my ($self, $cap) = @_;
$cap = lc $cap; $cap = lc $cap;
foreach my $c (keys %{$self->{caps}->{hash}}) { foreach my $c ($self->{caps}->get_keys) {
next if $c eq '_name';
return 1 if $c eq $cap; return 1 if $c eq $cap;
foreach my $sub_cap (keys %{$self->{caps}->{hash}->{$c}}) { foreach my $sub_cap ($self->{caps}->get_keys($c)) {
return 1 if $sub_cap eq $cap; return 1 if $sub_cap eq $cap;
} }
} }
@ -95,43 +93,30 @@ sub add {
sub remove { sub remove {
my ($self, $cap, $subcap) = @_; my ($self, $cap, $subcap) = @_;
$cap = lc $cap; $cap = lc $cap;
if (not defined $subcap) { if (not defined $subcap) {
foreach my $c (keys %{$self->{caps}->{hash}}) { foreach my $c ($self->{caps}->get_keys) {
next if $c eq '_name'; foreach my $sub_cap ($self->{caps}->get_keys($c)) {
foreach my $sub_cap (keys %{$self->{caps}->{hash}->{$c}}) { $self->{caps}->remove($c, $sub_cap, 1) if $sub_cap eq $cap;
delete $self->{caps}->{hash}->{$c}->{$sub_cap} if $sub_cap eq $cap;
}
if ($c eq $cap) {
delete $self->{caps}->{hash}->{$c};
} }
$self->{caps}->remove($c, undef, 1) if $c eq $cap;
} }
} else { } else {
$subcap = lc $subcap; $self->{caps}->remove($cap, $subcap, 1) if $self->{caps}->exists($cap);
if (exists $self->{caps}->{hash}->{$cap}) {
delete $self->{caps}->{hash}->{$cap}->{$subcap};
}
if (keys %{$self->{caps}->{hash}->{$cap}} == 1) {
delete $self->{caps}->{hash}->{$cap};
}
} }
$self->{caps}->save; $self->{caps}->save;
} }
sub rebuild_botowner_capabilities { sub rebuild_botowner_capabilities {
my ($self) = @_; my ($self) = @_;
$self->{caps}->remove('botowner'); $self->{caps}->remove('botowner', undef, 1);
foreach my $cap (keys %{$self->{caps}->{hash}}) { foreach my $cap ($self->{caps}->get_keys) {
next if $cap eq '_name';
$self->add('botowner', $cap, 1); $self->add('botowner', $cap, 1);
} }
} }
sub list { sub list {
my ($self, $capability) = @_; my ($self, $capability) = @_;
$capability = lc $capability if defined $capability; return "No such capability $capability." if defined $capability and not $self->{caps}->exists($capability);
return "No such capability $capability." if defined $capability and not exists $self->{caps}->{hash}->{$capability};
my @caps; my @caps;
my @groups; my @groups;
@ -139,19 +124,18 @@ sub list {
my $result; my $result;
if (not defined $capability) { if (not defined $capability) {
@caps = sort keys %{$self->{caps}->{hash}}; @caps = sort $self->{caps}->get_keys;
$result = 'Capabilities: '; $result = 'Capabilities: ';
} else { } else {
@caps = sort keys %{$self->{caps}->{hash}->{$capability}}; @caps = sort $self->{caps}->get_keys($capability);
return "Capability $capability has no grouped capabilities." if not @caps or @caps == 1; return "Capability $capability has no grouped capabilities." if not @caps;
$result = "Grouped capabilities for $capability: "; $result = "Grouped capabilities for $capability: ";
} }
# first list all capabilities that have sub-capabilities (i.e. grouped capabilities) # first list all capabilities that have sub-capabilities (i.e. grouped capabilities)
# then list stand-alone capabilities # then list stand-alone capabilities
foreach my $cap (@caps) { foreach my $cap (@caps) {
next if $cap eq '_name'; my $count = $self->{caps}->get_keys($cap);
my $count = keys(%{$self->{caps}->{hash}->{$cap}}) - 1;
if ($count > 0) { if ($count > 0) {
push @groups, "$cap ($count cap" . ($count == 1 ? '' : 's') . ")" if $count; push @groups, "$cap ($count cap" . ($count == 1 ? '' : 's') . ")" if $count;
} else { } else {
@ -225,7 +209,7 @@ sub capcmd {
foreach my $key (sort keys %{$u}) { foreach my $key (sort keys %{$u}) {
next if $key eq '_name'; next if $key eq '_name';
next if not $self->exists($key); next if not $self->exists($key);
my $count = keys (%{$self->{caps}->{hash}->{$key}}) - 1; my $count = $self->{caps}->get_keys;
if ($count > 0) { if ($count > 0) {
push @groups, "$key ($count cap" . ($count == 1 ? '' : 's') . ")"; push @groups, "$key ($count cap" . ($count == 1 ? '' : 's') . ")";
} else { } else {

View File

@ -16,7 +16,7 @@ use feature 'unicode_strings';
sub initialize { sub initialize {
my ($self, %conf) = @_; my ($self, %conf) = @_;
$self->{channels} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Channels', filename => $conf{filename}); $self->{channels} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Channels', filename => $conf{filename});
$self->load_channels; $self->{channels}->load;
$self->{pbot}->{commands}->register(sub { $self->join(@_) }, "join", 1); $self->{pbot}->{commands}->register(sub { $self->join(@_) }, "join", 1);
$self->{pbot}->{commands}->register(sub { $self->part(@_) }, "part", 1); $self->{pbot}->{commands}->register(sub { $self->part(@_) }, "part", 1);
@ -33,25 +33,20 @@ sub initialize {
sub join { sub join {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
foreach my $channel (split /[\s+,]/, $arguments) { foreach my $channel (split /[\s+,]/, $arguments) {
$self->{pbot}->{logger}->log("$nick!$user\@$host made me join $channel\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host made me join $channel\n");
$self->{pbot}->{chanops}->join_channel($channel); $self->{pbot}->{chanops}->join_channel($channel);
} }
return "/msg $nick Joining $arguments"; return "/msg $nick Joining $arguments";
} }
sub part { sub part {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
$arguments = $from if not $arguments; $arguments = $from if not $arguments;
foreach my $channel (split /[\s+,]/, $arguments) { foreach my $channel (split /[\s+,]/, $arguments) {
$self->{pbot}->{logger}->log("$nick!$user\@$host made me part $channel\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host made me part $channel\n");
$self->{pbot}->{chanops}->part_channel($channel); $self->{pbot}->{chanops}->part_channel($channel);
} }
return "/msg $nick Parting $arguments"; return "/msg $nick Parting $arguments";
} }
@ -71,10 +66,7 @@ sub unset {
sub add { sub add {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
return "Usage: chanadd <channel>" if not defined $arguments or not length $arguments;
if (not defined $arguments or not length $arguments) {
return "Usage: chanadd <channel>";
}
my $data = { my $data = {
enabled => 1, enabled => 1,
@ -87,39 +79,30 @@ sub add {
sub remove { sub remove {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
return "Usage: chanrem <channel>" if not defined $arguments or not length $arguments;
if (not defined $arguments or not length $arguments) {
return "Usage: chanrem <channel>";
}
$arguments = lc $arguments;
# clear unban timeouts # clear unban timeouts
if (exists $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$arguments}) { if ($self->{pbot}->{chanops}->{unban_timeout}->exists($arguments)) {
delete $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$arguments}; $self->{pbot}->{chanops}->{unban_timeout}->remove($arguments);
$self->{pbot}->{chanops}->{unban_timeout}->save;
} }
# clear unmute timeouts # clear unmute timeouts
if (exists $self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{$arguments}) { if ($self->{pbot}->{chanops}->{unmute_timeout}->exists($arguments)) {
delete $self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{$arguments}; $self->{pbot}->{chanops}->{unmute_timeout}->remove($arguments);
$self->{pbot}->{chanops}->{unmute_timeout}->save;
} }
# TODO: ignores, etc? # TODO: ignores, etc?
return $self->{channels}->remove($arguments); return $self->{channels}->remove($arguments);
} }
sub list { sub list {
my ($self, $from, $nick, $user, $host, $arguments) = @_; my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $result; my $result;
foreach my $channel (sort $self->{channels}->get_keys) {
foreach my $index (sort keys %{ $self->{channels}->{hash} }) { $result .= $self->{channels}->get_data($channel, '_name') . ': {';
$result .= "$self->{channels}->{hash}->{$index}->{_name}: {";
my $comma = ' '; my $comma = ' ';
foreach my $key (sort keys %{ $self->{channels}->{hash}->{$index} }) { foreach my $key (sort $self->{channels}->get_keys($channel)) {
$result .= "$comma$key => $self->{channels}->{hash}->{$index}->{$key}"; $result .= "$comma$key => " . $self->{channels}->get_data($channel, $key);
$comma = ', '; $comma = ', ';
} }
$result .= " }\n"; $result .= " }\n";
@ -130,43 +113,31 @@ sub list {
sub autojoin { sub autojoin {
my ($self) = @_; my ($self) = @_;
return if $self->{pbot}->{joined_channels}; return if $self->{pbot}->{joined_channels};
my $chans; my $channels;
foreach my $chan (keys %{ $self->{channels}->{hash} }) { foreach my $channel ($self->{channels}->get_keys) {
if ($self->{channels}->{hash}->{$chan}->{enabled}) { if ($self->{channels}->get_data($channel, 'enabled')) {
$chans .= "$self->{channels}->{hash}->{$chan}->{_name},"; $channels .= $self->{channels}->get_data($channel, '_name') . ',';
} }
} }
$self->{pbot}->{logger}->log("Joining channels: $chans\n"); $self->{pbot}->{logger}->log("Joining channels: $channels\n");
$self->{pbot}->{chanops}->join_channel($chans); $self->{pbot}->{chanops}->join_channel($channels);
$self->{pbot}->{joined_channels} = 1; $self->{pbot}->{joined_channels} = 1;
} }
sub is_active { sub is_active {
my ($self, $channel) = @_; my ($self, $channel) = @_;
my $lc_channel = lc $channel; # returns undef if channel doesn't exist; otherwise, the value of 'enabled'
return exists $self->{channels}->{hash}->{$lc_channel} && $self->{channels}->{hash}->{$lc_channel}->{enabled}; return $self->{channels}->get_data($channel, 'enabled');
} }
sub is_active_op { sub is_active_op {
my ($self, $channel) = @_; my ($self, $channel) = @_;
return $self->is_active($channel) && $self->{channels}->{hash}->{lc $channel}->{chanop}; return $self->is_active($channel) && $self->{channels}->get_data($channel, 'chanop');
} }
sub get_meta { sub get_meta {
my ($self, $channel, $key) = @_; my ($self, $channel, $key) = @_;
$channel = lc $channel; return $self->{channels}->get_data($channel, $key);
return undef if not exists $self->{channels}->{hash}->{$channel};
return $self->{channels}->{hash}->{$channel}->{$key};
}
sub load_channels {
my ($self) = @_;
$self->{channels}->load;
}
sub save_channels {
my ($self) = @_;
$self->{channels}->save;
} }
1; 1;

View File

@ -22,7 +22,7 @@ sub initialize {
$self->PBot::Registerable::initialize(%conf); $self->PBot::Registerable::initialize(%conf);
$self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Commands', filename => $conf{filename}); $self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Commands', filename => $conf{filename});
$self->load_metadata; $self->{metadata}->load;
$self->register(sub { $self->cmdset(@_) }, "cmdset", 1); $self->register(sub { $self->cmdset(@_) }, "cmdset", 1);
$self->register(sub { $self->cmdunset(@_) }, "cmdunset", 1); $self->register(sub { $self->cmdunset(@_) }, "cmdunset", 1);
@ -131,28 +131,14 @@ sub interpreter {
sub set_meta { sub set_meta {
my ($self, $command, $key, $value, $save) = @_; my ($self, $command, $key, $value, $save) = @_;
$command = lc $command; return undef if not $self->{metadata}->exists($command);
return undef if not exists $self->{metadata}->{hash}->{$command}; $self->{metadata}->set($command, $key, $value, !$save);
$self->{metadata}->{hash}->{$command}->{$key} = $value;
$self->save_metadata if $save;
return 1; return 1;
} }
sub get_meta { sub get_meta {
my ($self, $command, $key) = @_; my ($self, $command, $key) = @_;
$command = lc $command; return $self->{metadata}->get_data($command, $key);
return undef if not exists $self->{metadata}->{hash}->{$command};
return $self->{metadata}->{hash}->{$command}->{$key};
}
sub load_metadata {
my ($self) = @_;
$self->{metadata}->load;
}
sub save_metadata {
my ($self) = @_;
$self->{metadata}->save;
} }
sub cmdset { sub cmdset {
@ -180,15 +166,12 @@ sub help {
# check built-in commands first # check built-in commands first
if ($self->exists($keyword)) { if ($self->exists($keyword)) {
if (exists $self->{metadata}->{hash}->{$keyword}) { if ($self->{metadata}->exists($keyword)) {
my $name = $self->{metadata}->{hash}->{$keyword}->{_name}; my $name = $self->{metadata}->get_data($keyword, '_name');
my $requires_cap = $self->{metadata}->{hash}->{$keyword}->{requires_cap}; my $requires_cap = $self->{metadata}->get_data($keyword, 'requires_cap');
my $help = $self->{metadata}->{hash}->{$keyword}->{help}; my $help = $self->{metadata}->get_data($keyword, 'help');
my $result = "/say $name: "; my $result = "/say $name: ";
$result .= "[Requires can-$keyword] " if $requires_cap;
if ($requires_cap) {
$result .= "[Requires can-$keyword] ";
}
if (not defined $help or not length $help) { if (not defined $help or not length $help) {
$result .= "I have no help for this command yet."; $result .= "I have no help for this command yet.";

View File

@ -31,6 +31,8 @@ sub load {
my $filename; my $filename;
if (@_) { $filename = shift; } else { $filename = $self->{filename}; } if (@_) { $filename = shift; } else { $filename = $self->{filename}; }
$self->clear;
if (not defined $filename) { if (not defined $filename) {
Carp::carp "No $self->{name} filename specified -- skipping loading from file"; Carp::carp "No $self->{name} filename specified -- skipping loading from file";
return; return;
@ -53,7 +55,7 @@ sub load {
# update existing entries to use _name to preserve case # update existing entries to use _name to preserve case
# and lowercase any non-lowercased entries # and lowercase any non-lowercased entries
foreach my $index (keys %{ $self->{hash} }) { foreach my $index (keys %{$self->{hash}}) {
if (not exists $self->{hash}->{$index}->{_name}) { if (not exists $self->{hash}->{$index}->{_name}) {
if (lc $index eq $index) { if (lc $index eq $index) {
$self->{hash}->{$index}->{_name} = $index; $self->{hash}->{$index}->{_name} = $index;
@ -100,7 +102,7 @@ sub levenshtein_matches {
my $comma = ''; my $comma = '';
my $result = ""; my $result = "";
foreach my $index (sort keys %{ $self->{hash} }) { foreach my $index (sort keys %{$self->{hash}}) {
my $distance = fastdistance($keyword, $index); my $distance = fastdistance($keyword, $index);
my $length = (length $keyword > length $index) ? length $keyword : length $index; my $length = (length $keyword > length $index) ? length $keyword : length $index;
@ -128,7 +130,7 @@ sub set {
if (not defined $key) { if (not defined $key) {
my $result = "[$self->{name}] $self->{hash}->{$lc_index}->{_name} keys: "; my $result = "[$self->{name}] $self->{hash}->{$lc_index}->{_name} keys: ";
my $comma = ''; my $comma = '';
foreach my $k (sort keys %{ $self->{hash}->{$lc_index} }) { foreach my $k (sort keys %{$self->{hash}->{$lc_index}}) {
next if $k eq '_name'; next if $k eq '_name';
$result .= $comma . "$k => " . $self->{hash}->{$lc_index}->{$k}; $result .= $comma . "$k => " . $self->{hash}->{$lc_index}->{$k};
$comma = "; "; $comma = "; ";
@ -143,7 +145,6 @@ sub set {
$self->{hash}->{$lc_index}->{$key} = $value; $self->{hash}->{$lc_index}->{$key} = $value;
$self->save unless $dont_save; $self->save unless $dont_save;
} }
return "[$self->{name}] $self->{hash}->{$lc_index}->{_name}: $key " . (defined $value ? "set to $value" : "is not set."); return "[$self->{name}] $self->{hash}->{$lc_index}->{_name}: $key " . (defined $value ? "set to $value" : "is not set.");
} }
@ -159,18 +160,27 @@ sub unset {
delete $self->{hash}->{$lc_index}->{$key}; delete $self->{hash}->{$lc_index}->{$key};
$self->save; $self->save;
return "[$self->{name}] $self->{hash}->{$lc_index}->{_name}: $key unset."; return "[$self->{name}] $self->{hash}->{$lc_index}->{_name}: $key unset.";
} }
sub exists { sub exists {
my ($self, $index, $data_index) = @_;
return exists $self->{hash}->{lc $index} if not defined $data_index;
return exists $self->{hash}->{lc $index}->{$data_index};
}
sub get_keys {
my ($self, $index) = @_; my ($self, $index) = @_;
return exists $self->{hash}->{lc $index}; return keys %{$self->{hash}} if not defined $index;
return grep { $_ ne '_name' } keys %{$self->{hash}->{lc $index}};
} }
sub get_data { sub get_data {
my ($self, $index) = @_; my ($self, $index, $data_index) = @_;
return $self->{hash}->{lc $index}; my $lc_index = lc $index;
return undef if not exists $self->{hash}->{$lc_index};
return $self->{hash}->{$lc_index} if not defined $data_index;
return $self->{hash}->{$lc_index}->{$data_index};
} }
sub add { sub add {
@ -188,7 +198,7 @@ sub add {
} }
sub remove { sub remove {
my ($self, $index) = @_; my ($self, $index, $data_index, $dont_save) = @_;
my $lc_index = lc $index; my $lc_index = lc $index;
if (not exists $self->{hash}->{$lc_index}) { if (not exists $self->{hash}->{$lc_index}) {
@ -197,9 +207,15 @@ sub remove {
return $result; return $result;
} }
my $data = delete $self->{hash}->{$lc_index}; if (defined $data_index) {
$self->save; delete $self->{hash}->{$lc_index}->{$data_index};
delete $self->{hash}->{$lc_index} if keys(%{$self->{hash}->{$lc_index}}) == 1;
$self->save unless $dont_save;
return "$self->{hash}->{$lc_index}->{_name}.$data_index removed from $self->{name}";
}
my $data = delete $self->{hash}->{$lc_index};
$self->save unless $dont_save;
return "$data->{_name} removed from $self->{name}."; return "$data->{_name} removed from $self->{name}.";
} }

View File

@ -416,12 +416,12 @@ sub reload {
my %reloadables = ( my %reloadables = (
'capabilities' => sub { 'capabilities' => sub {
$self->{capabilities}->load; $self->{capabilities}->{caps}->load;
return "Capabilities reloaded."; return "Capabilities reloaded.";
}, },
'commands' => sub { 'commands' => sub {
$self->{commands}->load_metadata; $self->{commands}->{metadata}->load;
return "Commands metadata reloaded."; return "Commands metadata reloaded.";
}, },
@ -449,8 +449,7 @@ sub reload {
}, },
'channels' => sub { 'channels' => sub {
$self->{channels}->{channels}->clear; $self->{channels}->{channels}->load;
$self->{channels}->load_channels;
return "Channels reloaded."; return "Channels reloaded.";
}, },

View File

@ -55,14 +55,15 @@ sub initialize {
$self->{stats_filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/spinach/stats.sqlite'; $self->{stats_filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/spinach/stats.sqlite';
$self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Spinach Metadata', filename => $self->{metadata_filename}); $self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Spinach Metadata', filename => $self->{metadata_filename});
$self->load_metadata(); $self->{metadata}->load;
$self->set_metadata_defaults;
$self->{stats} = Plugins::Spinach::Stats->new(pbot => $self->{pbot}, filename => $self->{stats_filename}); $self->{stats} = Plugins::Spinach::Stats->new(pbot => $self->{pbot}, filename => $self->{stats_filename});
$self->{rankcmd} = Plugins::Spinach::Rank->new(pbot => $self->{pbot}, channel => $self->{channel}, filename => $self->{stats_filename}); $self->{rankcmd} = Plugins::Spinach::Rank->new(pbot => $self->{pbot}, channel => $self->{channel}, filename => $self->{stats_filename});
$self->create_states(); $self->create_states;
$self->load_questions(); $self->load_questions;
$self->load_stopwords(); $self->load_stopwords;
$self->{choosecategory_max_count} = 4; $self->{choosecategory_max_count} = 4;
$self->{picktruth_max_count} = 4; $self->{picktruth_max_count} = 4;
@ -182,10 +183,8 @@ sub load_stopwords {
close $fh; close $fh;
} }
sub load_metadata { sub set_metadata_defaults {
my $self = shift; my ($self) = @_;
$self->{metadata}->load;
my $defaults = { my $defaults = {
category_choices => 7, category_choices => 7,
category_autopick => 0, category_autopick => 0,
@ -198,22 +197,17 @@ sub load_metadata {
debug_state => 0, debug_state => 0,
}; };
if (not exists $self->{metadata}->{hash}->{settings}) { if ($self->{metadata}->exists('settings')) {
$self->{metadata}->{hash}->{settings} = $defaults; $self->{metadata}->add('settings', $defaults, 1);
} else { } else {
foreach my $key (keys %$defaults) { foreach my $key (keys %$defaults) {
if (not exists $self->{metadata}->{hash}->{settings}->{$key}) { if (not $self->{metadata}->exists('settings', $key)) {
$self->{metadata}->{hash}->{settings}->{$key} = $defaults->{$key}; $self->{metadata}->set('settings', $key, $defaults->{$key}, 1);
} }
} }
} }
} }
sub save_metadata {
my $self = shift;
$self->{metadata}->save;
}
my %color = ( my %color = (
white => "\x0300", white => "\x0300",
black => "\x0301", black => "\x0301",
@ -880,33 +874,31 @@ sub spinach_cmd {
return "Bad filter: No categories match. Try again."; return "Bad filter: No categories match. Try again.";
} }
$self->{metadata}->{hash}->{filter}->{"category_" . $_ . "_filter"} = $args; $self->{metadata}->set('filter', "category_" . $_ . "_filter", $args);
$self->save_metadata;
return "Spinach $_ filter set."; return "Spinach $_ filter set.";
} }
when ('clear') { when ('clear') {
delete $self->{metadata}->{hash}->{filter}; $self->{metadata}->remove('filter');
$self->save_metadata;
return "Spinach filter cleared."; return "Spinach filter cleared.";
} }
when ('show') { when ('show') {
if (not exists $self->{metadata}->{hash}->{filter}->{category_include_filter} if (not $self->{metadata}->exists('filter', 'category_include_filter')
and not exists $self->{metadata}->{hash}->{filter}->{category_exclude_filter}) { and not $self->{metadata}->exists('filter', 'category_exclude_filter')) {
return "There is no Spinach filter set."; return "There is no Spinach filter set.";
} }
my $text = "Spinach "; my $text = "Spinach ";
my $comma = ""; my $comma = "";
if (exists $self->{metadata}->{hash}->{filter}->{category_include_filter}) { if ($self->{metadata}->exists('filter', 'category_include_filter')) {
$text .= "include filter set to: " . $self->{metadata}->{hash}->{filter}->{category_include_filter}; $text .= "include filter set to: " . $self->{metadata}->get_data('filter', 'category_include_filter');
$comma = "; "; $comma = "; ";
} }
if (exists $self->{metadata}->{hash}->{filter}->{category_exclude_filter}) { if ($self->{metadata}->exists('filter', 'category_exclude_filter')) {
$text .= $comma . "exclude filter set to: " . $self->{metadata}->{hash}->{filter}->{category_exclude_filter}; $text .= $comma . "exclude filter set to: " . $self->{metadata}->get_data('filter', 'category_exclude_filter');
} }
return $text; return $text;
@ -1083,7 +1075,7 @@ sub run_one_state {
if ($self->{current_state} =~ /r\dq\d/) { if ($self->{current_state} =~ /r\dq\d/) {
my $removed = 0; my $removed = 0;
for (my $i = 0; $i < @{$self->{state_data}->{players}}; $i++) { for (my $i = 0; $i < @{$self->{state_data}->{players}}; $i++) {
if ($self->{state_data}->{players}->[$i]->{missedinputs} >= $self->{metadata}->{hash}->{settings}->{max_missed_inputs}) { if ($self->{state_data}->{players}->[$i]->{missedinputs} >= $self->{metadata}->get_data('settings', 'max_missed_inputs')) {
$self->send_message($self->{channel}, "$color{red}$self->{state_data}->{players}->[$i]->{name} has missed too many prompts and has been ejected from the game!$color{reset}"); $self->send_message($self->{channel}, "$color{red}$self->{state_data}->{players}->[$i]->{name} has missed too many prompts and has been ejected from the game!$color{reset}");
splice @{$self->{state_data}->{players}}, $i--, 1; splice @{$self->{state_data}->{players}}, $i--, 1;
$removed = 1; $removed = 1;
@ -1127,7 +1119,7 @@ sub run_one_state {
} }
# dump new state data for logging/debugging # dump new state data for logging/debugging
if ($state_data->{newstate} and $self->{metadata}->{hash}->{settings}->{debug_state}) { if ($state_data->{newstate} and $self->{metadata}->get_data('settings', 'debug_state')) {
$self->{pbot}->{logger}->log("Spinach: New state: $self->{previous_state} ($state_data->{previous_result}) --> $self->{current_state}\n" . Dumper $state_data); $self->{pbot}->{logger}->log("Spinach: New state: $self->{previous_state} ($state_data->{previous_result}) --> $self->{current_state}\n" . Dumper $state_data);
} }
@ -1645,14 +1637,16 @@ sub choosecategory {
my @choices; my @choices;
my @categories; my @categories;
if (exists $self->{metadata}->{hash}->{filter}->{category_include_filter} and length $self->{metadata}->{hash}->{filter}->{category_include_filter}) { if ($self->{metadata}->exists('filter', 'category_include_filter') and length $self->{metadata}->get_data('filter', 'category_include_filter')) {
@categories = grep { /$self->{metadata}->{hash}->{filter}->{category_include_filter}/i } keys %{$self->{categories}}; my $filter = $self->{metadata}->get_data('filter', 'category_include_filter');
@categories = grep { /$filter/i } keys %{$self->{categories}};
} else { } else {
@categories = keys %{$self->{categories}}; @categories = keys %{$self->{categories}};
} }
if (exists $self->{metadata}->{hash}->{filter}->{category_exclude_filter} and length $self->{metadata}->{hash}->{filter}->{category_exclude_filter}) { if ($self->{metadata}->exists('filter', 'category_exclude_filter') and length $self->{metadata}->get_data('filter', 'category_exclude_filter')) {
@categories = grep { $_ !~ /$self->{metadata}->{hash}->{filter}->{category_exclude_filter}/i } @categories; my $filter = $self->{metadata}->get_data('filter', 'category_exclude_filter');
@categories = grep { $_ !~ /$filter/i } @categories;
} }
my $no_infinite_loops = 0; my $no_infinite_loops = 0;
@ -1667,17 +1661,17 @@ sub choosecategory {
next; next;
} }
if (exists $self->{metadata}->{hash}->{settings}->{min_difficulty}) { if ($self->{metadata}->exists('settings', 'min_difficulty')) {
@questions = grep { $self->{categories}{$cat}{$_}->{value} >= $self->{metadata}->{hash}->{settings}->{min_difficulty} } @questions; @questions = grep { $self->{categories}{$cat}{$_}->{value} >= $self->{metadata}->get_data('settings', 'min_difficulty') } @questions;
} }
if (exists $self->{metadata}->{hash}->{settings}->{max_difficulty}) { if ($self->{metadata}->exists('settings', 'max_difficulty')) {
@questions = grep { $self->{categories}{$cat}{$_}->{value} <= $self->{metadata}->{hash}->{settings}->{max_difficulty} } @questions; @questions = grep { $self->{categories}{$cat}{$_}->{value} <= $self->{metadata}->get_data('settings', 'max_difficulty') } @questions;
} }
if (exists $self->{metadata}->{hash}->{settings}->{seen_expiry}) { if ($self->{metadata}->exists('settings', 'seen_expiry')) {
my $now = time; my $now = time;
@questions = grep { $now - $self->{categories}{$cat}{$_}->{seen_timestamp} >= $self->{metadata}->{hash}->{settings}->{seen_expiry} } @questions; @questions = grep { $now - $self->{categories}{$cat}{$_}->{seen_timestamp} >= $self->{metadata}->get_data('settings', 'seen_expiry') } @questions;
} }
next if not @questions; next if not @questions;
@ -1686,7 +1680,7 @@ sub choosecategory {
push @choices, $cat; push @choices, $cat;
} }
last if @choices == $self->{metadata}->{hash}->{settings}->{category_choices} or @categories < $self->{metadata}->{hash}->{settings}->{category_choices};; last if @choices == $self->{metadata}->get_data('settings', 'category_choices') or @categories < $self->{metadata}->get_data('settings', 'category_choices');
} }
if (not @choices) { if (not @choices) {
@ -1706,7 +1700,7 @@ sub choosecategory {
$comma = "; "; $comma = "; ";
} }
if ($state->{reroll_category} and not $self->{metadata}->{hash}->{settings}->{category_autopick}) { if ($state->{reroll_category} and not $self->{metadata}->get_data('settings', 'category_autopick')) {
$self->send_message($self->{channel}, "$state->{categories_text}"); $self->send_message($self->{channel}, "$state->{categories_text}");
} }
@ -1730,7 +1724,7 @@ sub choosecategory {
if ($state->{ticks} % $tock == 0) { if ($state->{ticks} % $tock == 0) {
$state->{tocked} = 1; $state->{tocked} = 1;
if (exists $state->{random_category} or $self->{metadata}->{hash}->{settings}->{category_autopick}) { if (exists $state->{random_category} or $self->{metadata}->get_data('settings', 'category_autopick')) {
delete $state->{random_category}; delete $state->{random_category};
my $category = $state->{category_options}->[rand (@{$state->{category_options}} - 2)]; my $category = $state->{category_options}->[rand (@{$state->{category_options}} - 2)];
my $questions = scalar keys %{ $self->{categories}{$category} }; my $questions = scalar keys %{ $self->{categories}{$category} };
@ -1788,14 +1782,14 @@ sub getnewquestion {
@questions = sort { $self->{categories}{$state->{current_category}}{$a}->{seen_timestamp} <=> $self->{categories}{$state->{current_category}}{$b}->{seen_timestamp} } @questions; @questions = sort { $self->{categories}{$state->{current_category}}{$a}->{seen_timestamp} <=> $self->{categories}{$state->{current_category}}{$b}->{seen_timestamp} } @questions;
my $now = time; my $now = time;
@questions = grep { $now - $self->{categories}{$state->{current_category}}{$_}->{seen_timestamp} >= $self->{metadata}->{hash}->{settings}->{seen_expiry} } @questions; @questions = grep { $now - $self->{categories}{$state->{current_category}}{$_}->{seen_timestamp} >= $self->{metadata}->get_data('settings', 'seen_expiry') } @questions;
if (exists $self->{metadata}->{hash}->{settings}->{min_difficulty}) { if ($self->{metadata}->exists('settings', 'min_difficulty')) {
@questions = grep { $self->{categories}{$state->{current_category}}{$_}->{value} >= $self->{metadata}->{hash}->{settings}->{min_difficulty} } @questions; @questions = grep { $self->{categories}{$state->{current_category}}{$_}->{value} >= $self->{metadata}->get_data('settings', 'min_difficulty') } @questions;
} }
if (exists $self->{metadata}->{hash}->{settings}->{max_difficulty}) { if ($self->{metadata}->exists('settings', 'max_difficulty')) {
@questions = grep { $self->{categories}{$state->{current_category}}{$_}->{value} <= $self->{metadata}->{hash}->{settings}->{max_difficulty} } @questions; @questions = grep { $self->{categories}{$state->{current_category}}{$_}->{value} <= $self->{metadata}->get_data('settings', 'max_difficulty') } @questions;
} }
if (not @questions) { if (not @questions) {
@ -2116,7 +2110,7 @@ sub showlies {
last if @liars; last if @liars;
if ($player->{truth} ne $state->{correct_answer}) { if ($player->{truth} ne $state->{correct_answer}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel}); my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel});
my $player_data = $self->{stats}->get_player_data($player_id); my $player_data = $self->{stats}->get_player_data($player_id);
$player_data->{bad_guesses}++; $player_data->{bad_guesses}++;
@ -2143,7 +2137,7 @@ sub showlies {
my $comma = ''; my $comma = '';
foreach my $liar (@liars) { foreach my $liar (@liars) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
my $player_id = $self->{stats}->get_player_id($liar->{name}, $self->{channel}); my $player_id = $self->{stats}->get_player_id($liar->{name}, $self->{channel});
my $player_data = $self->{stats}->get_player_data($player_id); my $player_data = $self->{stats}->get_player_data($player_id);
$player_data->{players_deceived}++; $player_data->{players_deceived}++;
@ -2157,7 +2151,7 @@ sub showlies {
$liar->{good_lie} = 1; $liar->{good_lie} = 1;
} }
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel}); my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel});
my $player_data = $self->{stats}->get_player_data($player_id); my $player_data = $self->{stats}->get_player_data($player_id);
$player_data->{bad_guesses}++; $player_data->{bad_guesses}++;
@ -2193,7 +2187,7 @@ sub showtruth {
my $comma = ''; my $comma = '';
my $count = 0; my $count = 0;
foreach my $player (@{$state->{players}}) { foreach my $player (@{$state->{players}}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel}); $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel});
$player_data = $self->{stats}->get_player_data($player_id); $player_data = $self->{stats}->get_player_data($player_id);
@ -2202,14 +2196,14 @@ sub showtruth {
} }
if (exists $player->{deceived}) { if (exists $player->{deceived}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$self->{stats}->update_player_data($player_id, $player_data); $self->{stats}->update_player_data($player_id, $player_data);
} }
next; next;
} }
if (exists $player->{truth} and $player->{truth} eq $state->{correct_answer}) { if (exists $player->{truth} and $player->{truth} eq $state->{correct_answer}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$player_data->{good_guesses}++; $player_data->{good_guesses}++;
$self->{stats}->update_player_data($player_id, $player_data); $self->{stats}->update_player_data($player_id, $player_data);
} }
@ -2246,7 +2240,7 @@ sub reveallies {
$comma = '; '; $comma = '; ';
if ($player->{good_lie}) { if ($player->{good_lie}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel}); my $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel});
my $player_data = $self->{stats}->get_player_data($player_id); my $player_data = $self->{stats}->get_player_data($player_id);
$player_data->{good_lies}++; $player_data->{good_lies}++;
@ -2295,7 +2289,7 @@ sub showfinalscore {
my $i = @{$state->{players}}; my $i = @{$state->{players}};
$state->{finalscores} = []; $state->{finalscores} = [];
foreach my $player (sort { $a->{score} <=> $b->{score} } @{$state->{players}}) { foreach my $player (sort { $a->{score} <=> $b->{score} } @{$state->{players}}) {
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel}); $player_id = $self->{stats}->get_player_id($player->{name}, $self->{channel});
$player_data = $self->{stats}->get_player_data($player_id); $player_data = $self->{stats}->get_player_data($player_id);
@ -2319,7 +2313,7 @@ sub showfinalscore {
$mentions = "Honorable mentions: $mentions"; $mentions = "Honorable mentions: $mentions";
} }
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$self->{stats}->update_player_data($player_id, $player_data); $self->{stats}->update_player_data($player_id, $player_data);
} }
@ -2336,7 +2330,7 @@ sub showfinalscore {
$text = sprintf("%15s%-13s%7s", "WINNER: ", $player->{name}, $self->commify($player->{score})); $text = sprintf("%15s%-13s%7s", "WINNER: ", $player->{name}, $self->commify($player->{score}));
} }
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$self->{stats}->update_player_data($player_id, $player_data); $self->{stats}->update_player_data($player_id, $player_data);
} }
@ -2408,7 +2402,7 @@ sub getplayers {
} }
} }
my $min_players = $self->{metadata}->{hash}->{settings}->{min_players} // 2; my $min_players = $self->{metadata}->get_data('settings', 'min_players') // 2;
if (@$players >= $min_players and not $unready) { if (@$players >= $min_players and not $unready) {
$self->send_message($self->{channel}, "All players ready!"); $self->send_message($self->{channel}, "All players ready!");
@ -2460,7 +2454,7 @@ sub getplayers {
sub round1 { sub round1 {
my ($self, $state) = @_; my ($self, $state) = @_;
if ($self->{metadata}->{hash}->{settings}->{stats}) { if ($self->{metadata}->get_data('settings', 'stats')) {
$self->{stats}->begin; $self->{stats}->begin;
$self->{stats_running} = 1; $self->{stats_running} = 1;
} }