3
0
mirror of https://github.com/pragma-/pbot.git synced 2024-11-26 22:09:26 +01:00

No longer directly access DualIndexHashObject internals

This commit is contained in:
Pragmatic Software 2020-02-13 13:31:36 -08:00
parent fae9e866ee
commit 21c1eba0a0
18 changed files with 502 additions and 608 deletions

View File

@ -92,12 +92,11 @@ sub ban_exempt {
given ($command) { given ($command) {
when ($_ eq 'list') { when ($_ eq 'list') {
my $text = 'Ban-evasion exemptions:\n'; my $text = "Ban-evasion exemptions:\n";
my $entries = 0; my $entries = 0;
foreach my $channel (keys %{ $self->{'ban-exemptions'}->{hash} }) { foreach my $channel ($self->{'ban-exemptions'}->get_keys) {
$text .= " $self->{'ban-exemptions'}->{hash}->{$channel}->{_name}:\n"; $text .= ' ' . $self->{'ban-exemptions'}->get_data($channel, '_name') . ":\n";
foreach my $mask (keys %{ $self->{'ban-exemptions'}->{hash}->{$channel} }) { foreach my $mask ($self->{'ban-exemptions'}->get_keys($channel)) {
next if $mask eq '_name';
$text .= " $mask,\n"; $text .= " $mask,\n";
$entries++; $entries++;
} }

View File

@ -38,10 +38,9 @@ sub is_spam {
return 0 if $self->{pbot}->{registry}->get_value($namespace, 'dont_enforce_antispam'); return 0 if $self->{pbot}->{registry}->get_value($namespace, 'dont_enforce_antispam');
my $ret = eval { my $ret = eval {
foreach my $space (keys %{ $self->{keywords}->{hash} }) { foreach my $space ($self->{keywords}->get_keys) {
if ($all_namespaces or $lc_namespace eq $space) { if ($all_namespaces or $lc_namespace eq $space) {
foreach my $keyword (keys %{ $self->{keywords}->{hash}->{$space} }) { foreach my $keyword ($self->{keywords}->get_keys($space)) {
next if $keyword eq '_name';
return 1 if $text =~ m/$keyword/i; return 1 if $text =~ m/$keyword/i;
} }
} }
@ -70,11 +69,10 @@ sub antispam_cmd {
when ($_ eq "list" or $_ eq "show") { when ($_ eq "list" or $_ eq "show") {
my $text = "Spam keywords:\n"; my $text = "Spam keywords:\n";
my $entries = 0; my $entries = 0;
foreach my $namespace (keys %{ $self->{keywords}->{hash} }) { foreach my $namespace ($self->{keywords}->get_keys) {
$text .= " $self->{keywords}->{hash}->{$namespace}->{_name}:\n"; $text .= ' ' . $self->{keywords}->get_data($namespace, '_name') . ":\n";
foreach my $keyword (keys %{ $self->{keywords}->{hash}->{$namespace} }) { foreach my $keyword ($self->{keywords}->get_keys($namespace)) {
next if $keyword eq '_name'; $text .= ' ' . $self->{keywords}->get_data($namespace, $keyword, '_name') . ",\n";
$text .= " $self->{keywords}->{hash}->{$namespace}->{$keyword}->{_name},\n";
$entries++; $entries++;
} }
} }
@ -85,23 +83,23 @@ sub antispam_cmd {
my ($namespace, $keyword, $flag, $value) = $self->{pbot}->{interpreter}->split_args($arglist, 4); my ($namespace, $keyword, $flag, $value) = $self->{pbot}->{interpreter}->split_args($arglist, 4);
return "Usage: antispam set <namespace> <regex> [flag [value]]" if not defined $namespace or not defined $keyword; return "Usage: antispam set <namespace> <regex> [flag [value]]" if not defined $namespace or not defined $keyword;
if (not exists $self->{keywords}->{hash}->{lc $namespace}) { if (not $self->{keywords}->exists($namespace)) {
return "There is no such namespace `$namespace`."; return "There is no such namespace `$namespace`.";
} }
if (not exists $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}) { if (not $self->{keywords}->exists($namespace, $keyword)) {
return "There is no such regex `$keyword` for namespace `$self->{keywords}->{hash}->{$namespace}->{_name}`."; return "There is no such regex `$keyword` for namespace `" . $self->{keywords}->get_data($namespace, '_name') . '`.';
} }
if (not defined $flag) { if (not defined $flag) {
my $text = "Flags:\n"; my $text = "Flags:\n";
my $comma = ''; my $comma = '';
foreach $flag (keys %{ $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword} }) { foreach $flag ($self->{keywords}->get_keys($namespace, $keyword)) {
if ($flag eq 'created_on') { if ($flag eq 'created_on') {
my $timestamp = strftime "%a %b %e %H:%M:%S %Z %Y", localtime $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag}; my $timestamp = strftime "%a %b %e %H:%M:%S %Z %Y", localtime $self->{keywords}->get_data($namespace, $keyword, $flag);
$text .= $comma . "created_on: $timestamp"; $text .= $comma . "created_on: $timestamp";
} else { } else {
$value = $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag}; $value = $self->{keywords}->get_data($namespace, $keyword, $flag);
$text .= $comma . "$flag: $value"; $text .= $comma . "$flag: $value";
} }
$comma = ",\n "; $comma = ",\n ";
@ -110,37 +108,32 @@ sub antispam_cmd {
} }
if (not defined $value) { if (not defined $value) {
$value = $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag}; $value = $self->{keywords}->get_data($namespace, $keyword, $flag);
if (not defined $value) { if (not defined $value) {
return "/say $flag is not set."; return "/say $flag is not set.";
} else { } else {
return "/say $flag is set to $value"; return "/say $flag is set to $value";
} }
} }
$self->{keywords}->set($namespace, $keyword, $flag, $value);
$self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag} = $value;
$self->{keywords}->save;
return "Flag set."; return "Flag set.";
} }
when ("unset") { when ("unset") {
my ($namespace, $keyword, $flag) = $self->{pbot}->{interpreter}->split_args($arglist, 3); my ($namespace, $keyword, $flag) = $self->{pbot}->{interpreter}->split_args($arglist, 3);
return "Usage: antispam unset <namespace> <regex> <flag>" if not defined $namespace or not defined $keyword or not defined $flag; return "Usage: antispam unset <namespace> <regex> <flag>" if not defined $namespace or not defined $keyword or not defined $flag;
if (not exists $self->{keywords}->{hash}->{lc $namespace}) { if (not $self->{keywords}->exists($namespace)) {
return "There is no such namespace `$namespace`."; return "There is no such namespace `$namespace`.";
} }
if (not exists $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}) { if (not $self->{keywords}->exists($namespace, $keyword)) {
return "There is no such keyword `$keyword` for namespace `$namespace`."; return "There is no such keyword `$keyword` for namespace `$namespace`.";
} }
if (not exists $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag}) { if (not $self->{keywords}->exists($namespace, $keyword, $flag)) {
return "There is no such flag `$flag` for regex `$keyword` for namespace `$namespace`."; return "There is no such flag `$flag` for regex `$keyword` for namespace `$namespace`.";
} }
return $self->{keywords}->remove($namespace, $keyword, $flag);
delete $self->{keywords}->{hash}->{lc $namespace}->{lc $keyword}->{$flag};
$self->{keywords}->save;
return "Flag unset.";
} }
when ("add") { when ("add") {
my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args($arglist, 2); my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args($arglist, 2);

View File

@ -72,16 +72,17 @@ sub on_banlist_entry {
} }
if ($timeout && $self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($timeout && $self->{pbot}->{chanops}->can_gain_ops($channel)) {
if (not exists $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$target}) { if (not $self->{pbot}->{chanops}->{unban_timeout}->exists($channel, $target)) {
$self->{pbot}->{logger}->log("Temp ban for $target in $channel.\n"); $self->{pbot}->{logger}->log("Temp ban for $target in $channel.\n");
$self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$target}->{timeout} = gettimeofday + $timeout; my $data = {
$self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$target}->{owner} = $source; timeout => gettimeofday + $timeout,
$self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$target}->{reason} = 'Temp ban on *!*@... or *!...@gateway/web'; owner => $source,
$self->{pbot}->{chanops}->{unban_timeout}->save; reason => 'Temp ban on *!*@... or *!...@gateway/web'
};
$self->{pbot}->{chanops}->{unban_timeout}->add($channel, $target, $data);
} }
} }
} }
return 0; return 0;
} }

View File

@ -163,19 +163,17 @@ sub capcmd {
return "No such capability $cap." if not $self->exists($cap); return "No such capability $cap." if not $self->exists($cap);
my $result = "Users with capability $cap: "; my $result = "Users with capability $cap: ";
my $matched = 0; my $matched = 0;
my $users = $self->{pbot}->{users}->{users}->{hash}; my $users = $self->{pbot}->{users}->{users};
foreach my $channel (sort keys %$users) { foreach my $channel (sort $users->get_keys) {
my @matches; my @matches;
next if $channel eq '_name'; foreach my $hostmask (sort $users->get_keys($channel)) {
foreach my $hostmask (sort keys %{$users->{$channel}}) { my $u = $users->get_data($channel, $hostmask);
next if $hostmask eq '_name';
my $u = $users->{$channel}->{$hostmask};
push @matches, $u->{name} if $self->userhas($u, $cap); push @matches, $u->{name} if $self->userhas($u, $cap);
} }
if (@matches) { if (@matches) {
$result .= '; ' if $matched; $result .= '; ' if $matched;
my $global = $matched ? 'global: ' : ''; my $global = $matched ? 'global: ' : '';
$result .= $users->{$channel}->{_name} eq '.*' ? $global : "$users->{$channel}->{_name}: "; $result .= $users->get_data($channel, '_name') eq '.*' ? $global : $users->get_data($channel, '_name') . ': ';
$result .= join ', ', @matches; $result .= join ', ', @matches;
$matched = 1; $matched = 1;
} }

View File

@ -429,9 +429,8 @@ sub ban_user {
foreach my $t (@targets) { foreach my $t (@targets) {
my $mask = lc $self->{pbot}->{chanops}->nick_to_banmask($t); my $mask = lc $self->{pbot}->{chanops}->nick_to_banmask($t);
if ($no_length && exists $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel} if ($no_length && $self->{pbot}->{chanops}->{unban_timeout}->exists($channel, $mask)) {
&& exists $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$mask}) { my $timeout = $self->{pbot}->{chanops}->{unban_timeout}->get_data($channel, $mask, 'timeout');
my $timeout = $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{$channel}->{$mask}->{timeout};
my $d = duration($timeout - gettimeofday); my $d = duration($timeout - gettimeofday);
$result .= "$sep$mask has $d remaining on their $channel ban"; $result .= "$sep$mask has $d remaining on their $channel ban";
$sep = '; '; $sep = '; ';
@ -563,9 +562,8 @@ sub mute_user {
foreach my $t (@targets) { foreach my $t (@targets) {
my $mask = lc $self->{pbot}->{chanops}->nick_to_banmask($t); my $mask = lc $self->{pbot}->{chanops}->nick_to_banmask($t);
if ($no_length && exists $self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{$channel} if ($no_length && $self->{pbot}->{chanops}->{unmute_timeout}->exists($channel, $mask)) {
&& exists $self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{$channel}->{$mask}) { my $timeout = $self->{pbot}->{chanops}->{unmute_timeout}->get_data($channel, $mask, 'timeout');
my $timeout = $self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{$channel}->{$mask}->{timeout};
my $d = duration($timeout - gettimeofday); my $d = duration($timeout - gettimeofday);
$result .= "$sep$mask has $d remaining on their $channel mute"; $result .= "$sep$mask has $d remaining on their $channel mute";
$sep = '; '; $sep = '; ';

View File

@ -56,9 +56,9 @@ sub initialize {
sub can_gain_ops { sub can_gain_ops {
my ($self, $channel) = @_; my ($self, $channel) = @_;
$channel = lc $channel; $channel = lc $channel;
return exists $self->{pbot}->{channels}->{channels}->{hash}->{$channel} return $self->{pbot}->{channels}->{channels}->exists($channel)
&& $self->{pbot}->{channels}->{channels}->{hash}->{$channel}->{chanop} && $self->{pbot}->{channels}->{channels}->get_data($channel, 'chanop')
&& $self->{pbot}->{channels}->{channels}->{hash}->{$channel}->{enabled}; && $self->{pbot}->{channels}->{channels}->get_data($channel, 'enabled');
} }
sub gain_ops { sub gain_ops {
@ -124,9 +124,7 @@ sub perform_op_commands {
sub ban_user { sub ban_user {
my $self = shift; my $self = shift;
my ($mask, $channel, $immediately) = @_; my ($mask, $channel, $immediately) = @_;
$self->add_to_ban_queue($channel, 'b', $mask); $self->add_to_ban_queue($channel, 'b', $mask);
if (not defined $immediately or $immediately != 0) { if (not defined $immediately or $immediately != 0) {
$self->check_ban_queue; $self->check_ban_queue;
} }
@ -157,7 +155,6 @@ sub get_bans {
} }
} }
} }
return $masks return $masks
} }
@ -184,7 +181,6 @@ sub unmode_user {
$unbanned{$baninfo->{banmask}} = 1; $unbanned{$baninfo->{banmask}} = 1;
$self->add_to_unban_queue($channel, $mode, $baninfo->{banmask}); $self->add_to_unban_queue($channel, $mode, $baninfo->{banmask});
} }
$self->check_unban_queue if $immediately; $self->check_unban_queue if $immediately;
} }
@ -234,22 +230,20 @@ sub ban_user_timed {
$data->{reason} = $reason if defined $reason; $data->{reason} = $reason if defined $reason;
$self->{unban_timeout}->add($channel, $mask, $data); $self->{unban_timeout}->add($channel, $mask, $data);
} else { } else {
if ($self->{unban_timeout}->exists($channel, $mask)) {
$self->{unban_timeout}->remove($channel, $mask); $self->{unban_timeout}->remove($channel, $mask);
} }
}
} }
sub checkban { sub checkban {
my ($self, $channel, $target) = @_; my ($self, $channel, $target) = @_;
$channel = lc $channel; my $mask = $self->nick_to_banmask($target);
$target = lc $target;
my $mask = lc $self->nick_to_banmask($target); if ($self->{unban_timeout}->exists($channel, $mask)) {
my $timeout = $self->{unban_timeout}->get_data($channel, $mask, 'timeout');
if (exists $self->{unban_timeout}->{hash}->{$channel} my $owner = $self->{unban_timeout}->get_data($channel, $mask, 'owner');
&& exists $self->{unban_timeout}->{hash}->{$channel}->{$mask}) { my $reason = $self->{unban_timeout}->get_data($channel, $mask, 'reason');
my $timeout = $self->{unban_timeout}->{hash}->{$channel}->{$mask}->{timeout};
my $owner = $self->{unban_timeout}->{hash}->{$channel}->{$mask}->{owner};
my $reason = $self->{unban_timeout}->{hash}->{$channel}->{$mask}->{reason};
my $duration = concise duration($timeout - gettimeofday); my $duration = concise duration($timeout - gettimeofday);
my $result = "$mask banned in $channel "; my $result = "$mask banned in $channel ";
@ -265,9 +259,7 @@ sub checkban {
sub mute_user { sub mute_user {
my $self = shift; my $self = shift;
my ($mask, $channel, $immediately) = @_; my ($mask, $channel, $immediately) = @_;
$self->add_to_ban_queue($channel, 'q', $mask); $self->add_to_ban_queue($channel, 'q', $mask);
if (not defined $immediately or $immediately != 0) { if (not defined $immediately or $immediately != 0) {
$self->check_ban_queue; $self->check_ban_queue;
} }
@ -285,9 +277,6 @@ sub mute_user_timed {
my $self = shift; my $self = shift;
my ($owner, $reason, $mask, $channel, $length, $immediately) = @_; my ($owner, $reason, $mask, $channel, $length, $immediately) = @_;
$channel = lc $channel;
$mask = lc $mask;
$mask = $self->nick_to_banmask($mask); $mask = $self->nick_to_banmask($mask);
$self->mute_user($mask, $channel, $immediately); $self->mute_user($mask, $channel, $immediately);
@ -299,23 +288,20 @@ sub mute_user_timed {
$data->{reason} = $reason if defined $reason; $data->{reason} = $reason if defined $reason;
$self->{unmute_timeout}->add($channel, $mask, $data); $self->{unmute_timeout}->add($channel, $mask, $data);
} else { } else {
if ($self->{unmute_timeout}->exists($channel, $mask)) {
$self->{unmute_timeout}->remove($channel, $mask); $self->{unmute_timeout}->remove($channel, $mask);
} }
}
} }
sub checkmute { sub checkmute {
my ($self, $channel, $target) = @_; my ($self, $channel, $target) = @_;
my $mask = $self->nick_to_banmask($target);
$channel = lc $channel; if ($self->{unmute_timeout}->exists($channel, $mask)) {
$target = lc $target; my $timeout = $self->{unmute_timeout}->get_data($channel, $mask, 'timeout');
my $owner = $self->{unmute_timeout}->get_data($channel, $mask, 'owner');
my $mask = lc $self->nick_to_banmask($target); my $reason = $self->{unmute_timeout}->get_data($channel, $mask, 'reason');
if (exists $self->{unmute_timeout}->{hash}->{$channel}
&& exists $self->{unmute_timeout}->{hash}->{$channel}->{$mask}) {
my $timeout = $self->{unmute_timeout}->{hash}->{$channel}->{$mask}->{timeout};
my $owner = $self->{unmute_timeout}->{hash}->{$channel}->{$mask}->{owner};
my $reason = $self->{unmute_timeout}->{hash}->{$channel}->{$mask}->{reason};
my $duration = concise duration($timeout - gettimeofday); my $duration = concise duration($timeout - gettimeofday);
my $result = "$mask muted in $channel "; my $result = "$mask muted in $channel ";
@ -341,8 +327,8 @@ sub join_channel {
delete $self->{is_opped}->{$channel}; delete $self->{is_opped}->{$channel};
delete $self->{op_requested}->{$channel}; delete $self->{op_requested}->{$channel};
if (exists $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel} if ($self->{pbot}->{channels}->{channels}->exists($channel)
and $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel}->{permop}) { and $self->{pbot}->{channels}->{channels}->get_data($channel, 'permop')) {
$self->gain_ops($channel); $self->gain_ops($channel);
} }
@ -352,24 +338,21 @@ sub join_channel {
sub part_channel { sub part_channel {
my ($self, $channel) = @_; my ($self, $channel) = @_;
$channel = lc $channel; $channel = lc $channel;
$self->{pbot}->{event_dispatcher}->dispatch_event('pbot.part', { channel => $channel }); $self->{pbot}->{event_dispatcher}->dispatch_event('pbot.part', { channel => $channel });
$self->{pbot}->{conn}->part($channel); $self->{pbot}->{conn}->part($channel);
delete $self->{is_opped}->{$channel}; delete $self->{is_opped}->{$channel};
delete $self->{op_requested}->{$channel}; delete $self->{op_requested}->{$channel};
} }
sub has_ban_timeout { sub has_ban_timeout {
my ($self, $channel, $mask) = @_; my ($self, $channel, $mask) = @_;
return exists $self->{unban_timeout}->{hash}->{lc $channel}->{lc $mask}; return $self->{unban_timeout}->exists($channel, $mask);
} }
sub has_mute_timeout { sub has_mute_timeout {
my ($self, $channel, $mask) = @_; my ($self, $channel, $mask) = @_;
return exists $self->{unmute_timeout}->{hash}->{lc $channel}->{lc $mask}; return $self->{unmute_timeout}->exists($channel, $mask);
} }
sub add_to_ban_queue { sub add_to_ban_queue {
@ -474,16 +457,12 @@ sub check_unban_queue {
sub check_unban_timeouts { sub check_unban_timeouts {
my $self = shift; my $self = shift;
return if not $self->{pbot}->{joined_channels}; return if not $self->{pbot}->{joined_channels};
my $now = gettimeofday(); my $now = gettimeofday();
foreach my $channel ($self->{unban_timeout}->get_keys) {
foreach my $channel (keys %{ $self->{unban_timeout}->{hash} }) { foreach my $mask ($self->{unban_timeout}->get_keys($channel)) {
foreach my $mask (keys %{ $self->{unban_timeout}->{hash}->{$channel} }) { if ($self->{unban_timeout}->get_data($channel, $mask, 'timeout') < $now) {
next if $mask eq '_name'; $self->{unban_timeout}->set($channel, $mask, 'timeout', $now + 7200);
if ($self->{unban_timeout}->{hash}->{$channel}->{$mask}->{timeout} < $now) {
$self->{unban_timeout}->{hash}->{$channel}->{$mask}->{timeout} = $now + 7200;
$self->unban_user($mask, $channel); $self->unban_user($mask, $channel);
} }
} }
@ -492,16 +471,12 @@ sub check_unban_timeouts {
sub check_unmute_timeouts { sub check_unmute_timeouts {
my $self = shift; my $self = shift;
return if not $self->{pbot}->{joined_channels}; return if not $self->{pbot}->{joined_channels};
my $now = gettimeofday(); my $now = gettimeofday();
foreach my $channel ($self->{unmute_timeout}->get_keys) {
foreach my $channel (keys %{ $self->{unmute_timeout}->{hash} }) { foreach my $mask ($self->{unmute_timeout}->get_keys($channel)) {
foreach my $mask (keys %{ $self->{unmute_timeout}->{hash}->{$channel} }) { if ($self->{unmute_timeout}->get_data($channel, $mask, 'timeout') < $now) {
next if $mask eq '_name'; $self->{unmute_timeout}->set($channel, $mask, 'timeout', $now + 7200);
if ($self->{unmute_timeout}->{hash}->{$channel}->{$mask}->{timeout} < $now) {
$self->{unmute_timeout}->{hash}->{$channel}->{$mask}->{timeout} = $now + 7200;
$self->unmute_user($mask, $channel); $self->unmute_user($mask, $channel);
} }
} }
@ -511,11 +486,10 @@ sub check_unmute_timeouts {
sub check_opped_timeouts { sub check_opped_timeouts {
my $self = shift; my $self = shift;
my $now = gettimeofday(); my $now = gettimeofday();
foreach my $channel (keys %{ $self->{is_opped} }) { foreach my $channel (keys %{ $self->{is_opped} }) {
if ($self->{is_opped}->{$channel}{timeout} < $now) { if ($self->{is_opped}->{$channel}{timeout} < $now) {
unless (exists $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel} unless ($self->{pbot}->{channels}->{channels}->exists($channel)
and $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel}->{permop}) { and $self->{pbot}->{channels}->{channels}->get_data($channel, 'permop')) {
$self->lose_ops($channel); $self->lose_ops($channel);
} }
} }
@ -523,8 +497,8 @@ sub check_opped_timeouts {
foreach my $channel (keys %{ $self->{op_requested} }) { foreach my $channel (keys %{ $self->{op_requested} }) {
if ($now - $self->{op_requested}->{$channel} > 60 * 5) { if ($now - $self->{op_requested}->{$channel} > 60 * 5) {
if (exists $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel} if ($self->{pbot}->{channels}->{channels}->exists($channel)
and $self->{pbot}->{channels}->{channels}->{hash}->{lc $channel}->{enabled}) { and $self->{pbot}->{channels}->{channels}->get_data($channel, 'enabled')) {
$self->{pbot}->{logger}->log("5 minutes since OP request for $channel and no OP yet; trying again ...\n"); $self->{pbot}->{logger}->log("5 minutes since OP request for $channel and no OP yet; trying again ...\n");
delete $self->{op_requested}->{$channel}; delete $self->{op_requested}->{$channel};
$self->gain_ops($channel); $self->gain_ops($channel);

View File

@ -211,8 +211,8 @@ sub help {
($channel, $trigger) = ($factoids[0]->[0], $factoids[0]->[1]); ($channel, $trigger) = ($factoids[0]->[0], $factoids[0]->[1]);
} }
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global channel' if $channel_name eq '.*'; $channel_name = 'global channel' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
@ -220,7 +220,7 @@ sub help {
$result .= "[$channel_name] " if $channel ne $from and $channel ne '.*'; $result .= "[$channel_name] " if $channel ne $from and $channel ne '.*';
$result .= "$trigger_name: "; $result .= "$trigger_name: ";
my $help = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{help}; my $help = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'help');
if (not defined $help or not length $help) { if (not defined $help or not length $help) {
return "/say $trigger_name is a factoid for $channel_name, but I have no help for it yet."; return "/say $trigger_name is a factoid for $channel_name, but I have no help for it yet.";

View File

@ -247,25 +247,55 @@ sub unset {
return $result; return $result;
} }
delete $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{$key};
$self->save();
my $name2 = $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{_name}; my $name2 = $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{_name};
$name2 = "\"$name2\"" if $name2 =~ / /; $name2 = "\"$name2\"" if $name2 =~ / /;
if (defined delete $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{$key}) {
$self->save;
return "$self->{name}: [$name1] $name2: $key unset."; return "$self->{name}: [$name1] $name2: $key unset.";
} else {
return "$self->{name}: [$name1] $name2: $key does not exist.";
}
$self->save;
}
sub exists {
my ($self, $primary_index, $secondary_index, $data_index) = @_;
$primary_index = lc $primary_index;
return 0 if not exists $self->{hash}->{$primary_index};
return 1 if not defined $secondary_index;
$secondary_index = lc $secondary_index;
return 0 if not exists $self->{hash}->{$primary_index}->{$secondary_index};
return 1 if not defined $data_index;
return exists $self->{hash}->{$primary_index}->{$secondary_index}->{$data_index};
}
sub get_keys {
my ($self, $primary_index, $secondary_index) = @_;
return keys %{$self->{hash}} if not defined $primary_index;
if (not defined $secondary_index) {
return grep { $_ ne '_name' } keys %{$self->{hash}->{lc $primary_index}};
}
return grep { $_ ne '_name' } keys %{$self->{hash}->{lc $primary_index}->{lc $secondary_index}};
}
sub get_data {
my ($self, $primary_index, $secondary_index, $data_index) = @_;
$primary_index = lc $primary_index if defined $primary_index;
$secondary_index = lc $secondary_index if defined $secondary_index;
return undef if not exists $self->{hash}->{$primary_index};
return $self->{hash}->{$primary_index} if not defined $secondary_index;
return $self->{hash}->{$primary_index}->{$secondary_index} if not defined $data_index;
return $self->{hash}->{$primary_index}->{$secondary_index}->{$data_index};
} }
sub add { sub add {
my ($self, $primary_index, $secondary_index, $data, $dont_save) = @_; my ($self, $primary_index, $secondary_index, $data, $dont_save, $quiet) = @_;
my $lc_primary_index = lc $primary_index; my $lc_primary_index = lc $primary_index;
my $lc_secondary_index = lc $secondary_index; my $lc_secondary_index = lc $secondary_index;
if (exists $self->{hash}->{$lc_primary_index} and exists $self->{$lc_primary_index}->{$lc_secondary_index}) {
$self->{pbot}->{logger}->log("Entry $lc_primary_index/$lc_secondary_index already exists.\n");
return "Error: entry already exists";
}
if (not exists $self->{hash}->{$lc_primary_index}) { if (not exists $self->{hash}->{$lc_primary_index}) {
$self->{hash}->{$lc_primary_index}->{_name} = $primary_index; # preserve case $self->{hash}->{$lc_primary_index}->{_name} = $primary_index; # preserve case
} }
@ -278,12 +308,12 @@ sub add {
my $name2 = $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{_name}; my $name2 = $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{_name};
$name1 = 'global' if $name1 eq '.*'; $name1 = 'global' if $name1 eq '.*';
$name2 = "\"$name2\"" if $name2 =~ / /; $name2 = "\"$name2\"" if $name2 =~ / /;
$self->{pbot}->{logger}->log("$self->{name}: [$name1]: $name2 added.\n"); $self->{pbot}->{logger}->log("$self->{name}: [$name1]: $name2 added.\n") unless $dont_save or $quiet;
return "$self->{name}: [$name1]: $name2 added."; return "$self->{name}: [$name1]: $name2 added.";
} }
sub remove { sub remove {
my ($self, $primary_index, $secondary_index) = @_; my ($self, $primary_index, $secondary_index, $data_index, $dont_save) = @_;
my $lc_primary_index = lc $primary_index; my $lc_primary_index = lc $primary_index;
my $lc_secondary_index = lc $secondary_index; my $lc_secondary_index = lc $secondary_index;
@ -293,12 +323,16 @@ sub remove {
return $result; return $result;
} }
if (not $secondary_index) { if (not defined $secondary_index) {
my $data = delete $self->{hash}->{$lc_primary_index}; my $data = delete $self->{hash}->{$lc_primary_index};
if (defined $data) {
my $name = $data->{_name}; my $name = $data->{_name};
$name = 'global' if $name eq '.*'; $name = 'global' if $name eq '.*';
$self->save; $self->save unless $dont_save;
return "$self->{name}: $name removed."; return "$self->{name}: $name removed.";
} else {
return "$self->{name}: $primary_index does not exist.";
}
} }
my $name1 = $self->{hash}->{$lc_primary_index}->{_name}; my $name1 = $self->{hash}->{$lc_primary_index}->{_name};
@ -310,7 +344,9 @@ sub remove {
return $result; return $result;
} }
if (not defined $data_index) {
my $data = delete $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}; my $data = delete $self->{hash}->{$lc_primary_index}->{$lc_secondary_index};
if (defined $data) {
my $name2 = $data->{_name}; my $name2 = $data->{_name};
$name2 = "\"$name2\"" if $name2 =~ / /; $name2 = "\"$name2\"" if $name2 =~ / /;
@ -319,15 +355,19 @@ sub remove {
delete $self->{hash}->{$lc_primary_index}; delete $self->{hash}->{$lc_primary_index};
} }
$self->save(); $self->save unless $dont_save;
return "$self->{name}: [$name1] $name2 removed."; return "$self->{name}: [$name1] $name2 removed.";
} } else {
return "$self->{name}: [$name1] $secondary_index does not exist.";
}
}
sub exists { my $name2 = $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{_name};
my ($self, $primary_index, $secondary_index) = @_; if (defined delete $self->{hash}->{$lc_primary_index}->{$lc_secondary_index}->{$data_index}) {
$primary_index = lc $primary_index; return "$self->{name}: [$name1] $name2.$data_index removed.";
$secondary_index = lc $secondary_index; } else {
return (exists $self->{hash}->{$primary_index} and exists $self->{hash}->{$primary_index}->{$secondary_index}); return "$self->{name}: [$name1] $name2.$data_index does not exist.";
}
} }
1; 1;

View File

@ -135,8 +135,8 @@ sub log_factoid {
}; };
} }
# TODO: use registry instead of hardcoded 20... meh my $max_undos = $self->{pbot}->{registry}->get_value('factoids', 'max_undos') // 20;
if (@{$undos->{list}} > 20) { if (@{$undos->{list}} > $max_undos) {
shift @{$undos->{list}}; shift @{$undos->{list}};
$undos->{idx}--; $undos->{idx}--;
} }
@ -145,7 +145,7 @@ sub log_factoid {
splice @{$undos->{list}}, $undos->{idx} + 1; splice @{$undos->{list}}, $undos->{idx} + 1;
} }
push @{$undos->{list}}, $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}; push @{$undos->{list}}, $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger);
$undos->{idx}++; $undos->{idx}++;
eval { store $undos, "$path/$trigger_safe.$channel_path_safe.undo"; }; eval { store $undos, "$path/$trigger_safe.$channel_path_safe.undo"; };
@ -162,7 +162,6 @@ sub find_factoid_with_optional_channel {
); );
%opts = (%default_opts, %opts); %opts = (%default_opts, %opts);
my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); my $arglist = $self->{pbot}->{interpreter}->make_args($arguments);
my ($from_chan, $from_trigger, $remaining_args) = $self->{pbot}->{interpreter}->split_args($arglist, 3, 0, 1); my ($from_chan, $from_trigger, $remaining_args) = $self->{pbot}->{interpreter}->split_args($arglist, 3, 0, 1);
@ -172,7 +171,6 @@ sub find_factoid_with_optional_channel {
} }
my $needs_disambig; my $needs_disambig;
if (not defined $from_trigger) { if (not defined $from_trigger) {
# cmd arg1, so insert $from as channel # cmd arg1, so insert $from as channel
$from_trigger = $from_chan; $from_trigger = $from_chan;
@ -243,25 +241,22 @@ sub find_factoid_with_optional_channel {
$from_chan = '.*' if $channel eq 'global'; $from_chan = '.*' if $channel eq 'global';
if ($opts{explicit} and $channel =~ /^#/ and $from_chan =~ /^#/ and $channel ne $from_chan) { if ($opts{explicit} and $channel =~ /^#/ and $from_chan =~ /^#/ and $channel ne $from_chan) {
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
return "/say $trigger_name belongs to $channel_name, not $from_chan. Please switch to or explicitly specify $channel_name."; return "/say $trigger_name belongs to $channel_name, not $from_chan. Please switch to or explicitly specify $channel_name.";
} }
return ($channel, $trigger, $remaining_args); return ($channel, $trigger, $remaining_args);
} }
sub hash_differences_as_string { sub hash_differences_as_string {
my ($self, $old, $new) = @_; my ($self, $old, $new) = @_;
my @exclude = qw/created_on last_referenced_in last_referenced_on ref_count ref_user edited_by edited_on/; my @exclude = qw/created_on last_referenced_in last_referenced_on ref_count ref_user edited_by edited_on/;
my %diff; my %diff;
foreach my $key (keys %$new) { foreach my $key (keys %$new) {
next if grep { $key eq $_ } @exclude; next if grep { $key eq $_ } @exclude;
if (not exists $old->{$key} or $old->{$key} ne $new->{$key}) { if (not exists $old->{$key} or $old->{$key} ne $new->{$key}) {
$diff{$key} = $new->{$key}; $diff{$key} = $new->{$key};
} }
@ -269,18 +264,14 @@ sub hash_differences_as_string {
foreach my $key (keys %$old) { foreach my $key (keys %$old) {
next if grep { $key eq $_ } @exclude; next if grep { $key eq $_ } @exclude;
if (not exists $new->{$key}) { if (not exists $new->{$key}) {
$diff{"deleted $key"} = undef; $diff{"deleted $key"} = undef;
} }
} }
if (not keys %diff) { return "No change." if not keys %diff;
return "No change.";
}
my $changes = ""; my $changes = "";
my $comma = ""; my $comma = "";
foreach my $key (sort keys %diff) { foreach my $key (sort keys %diff) {
if (defined $diff{$key}) { if (defined $diff{$key}) {
@ -290,7 +281,6 @@ sub hash_differences_as_string {
} }
$comma = ", "; $comma = ", ";
} }
return $changes return $changes
} }
@ -328,13 +318,11 @@ sub list_undo_history {
$result .= $self->hash_differences_as_string($undos->{list}->[$i - 1], $undos->{list}->[$i]); $result .= $self->hash_differences_as_string($undos->{list}->[$i - 1], $undos->{list}->[$i]);
$result .= ";\n\n"; $result .= ";\n\n";
} }
return $result; return $result;
} }
sub factundo { sub factundo {
my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_; my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_;
my $usage = "Usage: factundo [-l [N]] [-r N] [channel] <keyword> (-l list undo history, optionally starting from N; -r jump to revision N)"; my $usage = "Usage: factundo [-l [N]] [-r N] [channel] <keyword> (-l list undo history, optionally starting from N; -r jump to revision N)";
my $getopt_error; my $getopt_error;
@ -375,11 +363,11 @@ sub factundo {
my $channel_path_safe = safe_filename $channel_path; my $channel_path_safe = safe_filename $channel_path;
my $trigger_safe = safe_filename $trigger; my $trigger_safe = safe_filename $trigger;
my $path = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/factlog'; my $path = $self->{pbot}->{registry}->get_data('general', 'data_dir') . '/factlog';
my $undos = eval { retrieve("$path/$trigger_safe.$channel_path_safe.undo"); }; my $undos = eval { retrieve("$path/$trigger_safe.$channel_path_safe.undo"); };
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
@ -392,12 +380,12 @@ sub factundo {
return $self->list_undo_history($undos, $list_undos); return $self->list_undo_history($undos, $list_undos);
} }
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host"); my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids->{$channel}->{$trigger}->{'locked'}) { if ($factoids->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked and cannot be reverted." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin'); return "/say $trigger_name is locked and cannot be reverted." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids->{$channel}->{$trigger}->{'cap-override'} and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) { if ($factoids->exists($channel, $trigger, 'cap-override') and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
return "/say $trigger_name is locked with a cap-override and cannot be reverted. Unlock the factoid first."; return "/say $trigger_name is locked with a cap-override and cannot be reverted. Unlock the factoid first.";
} }
} }
@ -428,7 +416,7 @@ sub factundo {
} }
} }
$self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger} = $undos->{list}->[$undos->{idx}]; $self->{pbot}->{factoids}->{factoids}->add($channel, $trigger, $undos->{list}->[$undos->{idx}], 0, 1);
my $changes = $self->hash_differences_as_string($undos->{list}->[$undos->{idx} + 1], $undos->{list}->[$undos->{idx}]); my $changes = $self->hash_differences_as_string($undos->{list}->[$undos->{idx} + 1], $undos->{list}->[$undos->{idx}]);
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "reverted (undo): $changes", 1); $self->log_factoid($channel, $trigger, "$nick!$user\@$host", "reverted (undo): $changes", 1);
@ -467,8 +455,8 @@ sub factredo {
my $channel_path_safe = safe_filename $channel_path; my $channel_path_safe = safe_filename $channel_path;
my $trigger_safe = safe_filename $trigger; my $trigger_safe = safe_filename $trigger;
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
@ -484,12 +472,12 @@ sub factredo {
return $self->list_undo_history($undos, $list_undos); return $self->list_undo_history($undos, $list_undos);
} }
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host"); my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids->{$channel}->{$trigger}->{'locked'}) { if ($factoids->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked and cannot be reverted." if not defined $self->{pbot}->{capabilities}->userhas($userinfo, 'admin'); return "/say $trigger_name is locked and cannot be reverted." if not defined $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids->{$channel}->{$trigger}->{'cap-override'} and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) { if ($factoids->exists($channel, $trigger, 'cap-override') and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
return "/say $trigger_name is locked with a cap-override and cannot be reverted. Unlock the factoid first."; return "/say $trigger_name is locked with a cap-override and cannot be reverted. Unlock the factoid first.";
} }
} }
@ -521,7 +509,7 @@ sub factredo {
$self->{pbot}->{logger}->log("Error storing undo: $@\n") if $@; $self->{pbot}->{logger}->log("Error storing undo: $@\n") if $@;
} }
$self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger} = $undos->{list}->[$undos->{idx}]; $self->{pbot}->{factoids}->{factoids}->add($channel, $trigger, $undos->{list}->[$undos->{idx}], 0, 1);
my $changes = $self->hash_differences_as_string($undos->{list}->[$undos->{idx} - 1], $undos->{list}->[$undos->{idx}]); my $changes = $self->hash_differences_as_string($undos->{list}->[$undos->{idx} - 1], $undos->{list}->[$undos->{idx}]);
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "reverted (redo): $changes", 1); $self->log_factoid($channel, $trigger, "$nick!$user\@$host", "reverted (redo): $changes", 1);
@ -535,7 +523,7 @@ sub factset {
my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factset', usage => 'Usage: factset [channel] <factoid> [key [value]]', explicit => 1); my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factset', usage => 'Usage: factset [channel] <factoid> [key [value]]', explicit => 1);
return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $arglist = $self->{pbot}->{interpreter}->make_args($arguments); my $arglist = $self->{pbot}->{interpreter}->make_args($arguments);
@ -563,7 +551,7 @@ sub factset {
} }
} }
if (defined $value and !$self->{pbot}->{capabilities}->userhas($userinfo, 'admin') and $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'locked'}) { if (defined $value and !$self->{pbot}->{capabilities}->userhas($userinfo, 'admin') and $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked; unlock before setting."; return "/say $trigger_name is locked; unlock before setting.";
} }
@ -574,7 +562,7 @@ sub factset {
$self->{pbot}->{factoids}->{factoids}->set($channel, $trigger, 'locked', '1'); $self->{pbot}->{factoids}->{factoids}->set($channel, $trigger, 'locked', '1');
} }
if (lc $key eq 'locked' and exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'cap-override'}) { if (lc $key eq 'locked' and $self->{pbot}->{factoids}->{factoids}->exists($channel, $trigger, 'cap-override')) {
if (not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) { if (not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
return "/say $trigger_name has a cap-override and cannot be unlocked until the override is removed."; return "/say $trigger_name has a cap-override and cannot be unlocked until the override is removed.";
} }
@ -582,7 +570,7 @@ sub factset {
} }
if (defined $owner_channel) { if (defined $owner_channel) {
my $factoid = $self->{pbot}->{factoids}->{factoids}->{hash}->{$owner_channel}->{$owner_trigger}; my $factoid = $self->{pbot}->{factoids}->{factoids}->get_data($owner_channel, $owner_trigger);
my $owner; my $owner;
my $mask; my $mask;
@ -613,18 +601,13 @@ sub factset {
sub factunset { sub factunset {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $args) = @_; my ($from, $nick, $user, $host, $args) = @_;
my $usage = 'Usage: factunset [channel] <factoid> <key>'; my $usage = 'Usage: factunset [channel] <factoid> <key>';
my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factunset', usage => $usage, explicit => 1); my ($channel, $trigger, $arguments) = $self->find_factoid_with_optional_channel($from, $args, 'factunset', usage => $usage, explicit => 1);
return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message
my ($key) = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1); my ($key) = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1);
return $usage if not length $key; return $usage if not length $key;
my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, exact_channel => 1, exact_trigger => 1); my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, exact_channel => 1, exact_trigger => 1);
my $userinfo; my $userinfo;
if (defined $owner_channel) { if (defined $owner_channel) {
$userinfo = $self->{pbot}->{users}->loggedin($owner_channel, "$nick!$user\@$host"); $userinfo = $self->{pbot}->{users}->loggedin($owner_channel, "$nick!$user\@$host");
@ -643,38 +626,33 @@ sub factunset {
} }
} }
if (exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'cap-override'}) { if ($self->{pbot}->{factoids}->{factoids}->exists($channel, $trigger, 'cap-override')) {
if (lc $key eq 'locked') { if (lc $key eq 'locked') {
if ($self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) { if ($self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
$self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, 'cap-override'); $self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, 'cap-override', 1);
} else { } else {
return "You cannot unlock this factoid because it has a cap-override. Remove the override first."; return "You cannot unlock this factoid because it has a cap-override. Remove the override first.";
} }
} }
} }
my $oldvalue; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name};
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name};
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $oldvalue;
if (defined $owner_channel) { if (defined $owner_channel) {
my $factoid = $self->{pbot}->{factoids}->{factoids}->{hash}->{$owner_channel}->{$owner_trigger}; my $factoid = $self->{pbot}->{factoids}->{factoids}->get_data($owner_channel, $owner_trigger);
my ($owner) = $factoid->{'owner'} =~ m/([^!]+)/; my ($owner) = $factoid->{'owner'} =~ m/([^!]+)/;
if ($key ne 'action_with_args' and lc $nick ne lc $owner and not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin')) { if ($key ne 'action_with_args' and lc $nick ne lc $owner and not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin')) {
return "You are not the owner of $trigger_name."; return "You are not the owner of $trigger_name.";
} }
$oldvalue = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{$key}; $oldvalue = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, $key);
} }
return "[$channel_name] $trigger_name: key '$key' does not exist." if not defined $oldvalue; return "[$channel_name] $trigger_name: key '$key' does not exist." if not defined $oldvalue;
my $result = $self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, $key); my $result = $self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, $key);
if ($result =~ m/unset/) { if ($result =~ m/unset/) {
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "unset $key (value: $oldvalue)"); $self->log_factoid($channel, $trigger, "$nick!$user\@$host", "unset $key (value: $oldvalue)");
} }
@ -685,18 +663,13 @@ sub factmove {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my ($src_channel, $source, $target_channel, $target) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5); my ($src_channel, $source, $target_channel, $target) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5);
my $usage = "Usage: factmove <source channel> <source factoid> <target channel/factoid> [target factoid]"; my $usage = "Usage: factmove <source channel> <source factoid> <target channel/factoid> [target factoid]";
return $usage if not defined $target_channel;
if (not defined $target_channel) {
return $usage;
}
if ($target_channel !~ /^#/ and $target_channel ne '.*') { if ($target_channel !~ /^#/ and $target_channel ne '.*') {
if (defined $target) { if (defined $target) {
return "Unexpected argument '$target' when renaming to '$target_channel'. Perhaps '$target_channel' is missing #s? $usage"; return "Unexpected argument '$target' when renaming to '$target_channel'. Perhaps '$target_channel' is missing #s? $usage";
} }
$target = $target_channel; $target = $target_channel;
$target_channel = $src_channel; $target_channel = $src_channel;
} else { } else {
@ -719,14 +692,13 @@ sub factmove {
return "Source factoid $source not found in channel $src_channel"; return "Source factoid $source not found in channel $src_channel";
} }
my $source_channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$found_src_channel}->{_name}; my $source_channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($found_src_channel, '_name');
my $source_trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$found_src_channel}->{$found_source}->{_name}; my $source_trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($found_src_channel, $found_source, '_name');
$source_channel_name = 'global' if $source_channel_name eq '.*'; $source_channel_name = 'global' if $source_channel_name eq '.*';
$source_trigger_name = "\"$source_trigger_name\"" if $source_trigger_name =~ / /; $source_trigger_name = "\"$source_trigger_name\"" if $source_trigger_name =~ / /;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($owner) = $factoids->get_data($found_src_channel, $found_source, 'owner') =~ m/([^!]+)/;
my ($owner) = $factoids->{$found_src_channel}->{$found_source}->{'owner'} =~ m/([^!]+)/;
if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($found_src_channel, "$nick!$user\@$host"))) { if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($found_src_channel, "$nick!$user\@$host"))) {
$self->{pbot}->{logger}->log("$nick!$user\@$host attempted to move [$found_src_channel] $found_source (not owner)\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host attempted to move [$found_src_channel] $found_source (not owner)\n");
@ -734,24 +706,24 @@ sub factmove {
return "You are not the owner of $source_trigger_name for $source_channel_name."; return "You are not the owner of $source_trigger_name for $source_channel_name.";
} }
if ($factoids->{$found_src_channel}->{$found_source}->{'locked'}) { if ($factoids->get_data($found_src_channel, $found_source, 'locked')) {
return "/say $source_trigger_name is locked; unlock before moving."; return "/say $source_trigger_name is locked; unlock before moving.";
} }
my ($found_target_channel, $found_target) = $self->{pbot}->{factoids}->find_factoid($target_channel, $target, exact_channel => 1, exact_trigger => 1); my ($found_target_channel, $found_target) = $self->{pbot}->{factoids}->find_factoid($target_channel, $target, exact_channel => 1, exact_trigger => 1);
if (defined $found_target_channel) { if (defined $found_target_channel) {
my $target_channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$found_target_channel}->{_name}; my $target_channel_name = $factoids->get_data($found_target_channel, '_name');
my $target_trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$found_target_channel}->{$found_target}->{_name}; my $target_trigger_name = $factoids->get_data($found_target_channel, $found_target, '_name');
$target_channel_name = 'global' if $target_channel_name eq '.*'; $target_channel_name = 'global' if $target_channel_name eq '.*';
$target_trigger_name = "\"$target_trigger_name\"" if $target_trigger_name =~ / /; $target_trigger_name = "\"$target_trigger_name\"" if $target_trigger_name =~ / /;
return "Target factoid $target_trigger_name already exists in channel $target_channel_name."; return "Target factoid $target_trigger_name already exists in channel $target_channel_name.";
} }
my ($overchannel, $overtrigger) = $self->{pbot}->{factoids}->find_factoid('.*', $target, exact_channel => 1, exact_trigger => 1); my ($overchannel, $overtrigger) = $self->{pbot}->{factoids}->find_factoid('.*', $target, exact_channel => 1, exact_trigger => 1);
if (defined $overtrigger and $self->{pbot}->{factoids}->{factoids}->{hash}->{'.*'}->{$overtrigger}->{'nooverride'}) { if (defined $overtrigger and $factoids->get_data('.*', $overtrigger, 'nooverride')) {
my $override_channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$overchannel}->{_name}; my $override_channel_name = $factoids->get_data($overchannel, '_name');
my $override_trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$overchannel}->{$overtrigger}->{_name}; my $override_trigger_name = $factoids->get_data($overchannel, $overtrigger, '_name');
$override_channel_name = 'global' if $override_channel_name eq '.*'; $override_channel_name = 'global' if $override_channel_name eq '.*';
$override_trigger_name = "\"$override_trigger_name\"" if $override_trigger_name =~ / /; $override_trigger_name = "\"$override_trigger_name\"" if $override_trigger_name =~ / /;
$self->{pbot}->{logger}->log("$nick!$user\@$host attempt to override $target\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host attempt to override $target\n");
@ -764,10 +736,9 @@ sub factmove {
$target_channel = '.*' if $target_channel !~ /^#/; $target_channel = '.*' if $target_channel !~ /^#/;
$factoids->{lc $target_channel}->{lc $target} = delete $factoids->{$found_src_channel}->{$found_source}; my $data = $factoids->get_data($found_src_channel, $found_source);
$factoids->{lc $target_channel}->{lc $target}->{_name} = $target; $factoids->remove($found_src_channel, $found_source, undef, 1);
$factoids->{lc $target_channel}->{_name} = $target_channel if not exists $factoids->{lc $target_channel}->{_name}; $factoids->add($target_channel, $target, $data, 0, 1);
$self->{pbot}->{factoids}->save_factoids;
$found_src_channel = 'global' if $found_src_channel eq '.*'; $found_src_channel = 'global' if $found_src_channel eq '.*';
$target_channel = 'global' if $target_channel eq '.*'; $target_channel = 'global' if $target_channel eq '.*';
@ -786,7 +757,6 @@ sub factmove {
sub factalias { sub factalias {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my ($chan, $alias, $command) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3, 0, 1); my ($chan, $alias, $command) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 3, 0, 1);
if (defined $chan and not ($chan eq '.*' or $chan =~ m/^#/)) { if (defined $chan and not ($chan eq '.*' or $chan =~ m/^#/)) {
@ -802,10 +772,7 @@ sub factalias {
} }
$chan = '.*' if $chan !~ /^#/; $chan = '.*' if $chan !~ /^#/;
return "Usage: factalias [channel] <keyword> <command>" if not length $alias or not length $command;
if (not length $alias or not length $command) {
return "Usage: factalias [channel] <keyword> <command>";
}
if (length $alias > $self->{pbot}->{registry}->get_value('factoids', 'max_name_length')) { if (length $alias > $self->{pbot}->{registry}->get_value('factoids', 'max_name_length')) {
return "/say $nick: I don't think the factoid name needs to be that long."; return "/say $nick: I don't think the factoid name needs to be that long.";
@ -816,18 +783,17 @@ sub factalias {
} }
my ($channel, $alias_trigger) = $self->{pbot}->{factoids}->find_factoid($chan, $alias, exact_channel => 1, exact_trigger => 1); my ($channel, $alias_trigger) = $self->{pbot}->{factoids}->find_factoid($chan, $alias, exact_channel => 1, exact_trigger => 1);
if (defined $alias_trigger) { if (defined $alias_trigger) {
my $alias_channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $alias_channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $alias_trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$alias_trigger}->{_name}; my $alias_trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $alias_trigger, '_name');
$alias_channel_name = 'global' if $alias_channel_name eq '.*'; $alias_channel_name = 'global' if $alias_channel_name eq '.*';
$alias_trigger_name = "\"$alias_trigger_name\"" if $alias_trigger_name =~ / /; $alias_trigger_name = "\"$alias_trigger_name\"" if $alias_trigger_name =~ / /;
return "$alias_trigger_name already exists for $alias_channel_name."; return "$alias_trigger_name already exists for $alias_channel_name.";
} }
my ($overchannel, $overtrigger) = $self->{pbot}->{factoids}->find_factoid('.*', $alias, exact_channel => 1, exact_trigger => 1); my ($overchannel, $overtrigger) = $self->{pbot}->{factoids}->find_factoid('.*', $alias, exact_channel => 1, exact_trigger => 1);
if (defined $overtrigger and $self->{pbot}->{factoids}->{factoids}->{hash}->{'.*'}->{$overtrigger}->{'nooverride'}) { if (defined $overtrigger and $self->{pbot}->{factoids}->{factoids}->get_data('.*', $overtrigger, 'nooverride')) {
my $override_trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$overchannel}->{$overtrigger}->{_name}; my $override_trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($overchannel, $overtrigger, '_name');
$override_trigger_name = "\"$override_trigger_name\"" if $override_trigger_name =~ / /; $override_trigger_name = "\"$override_trigger_name\"" if $override_trigger_name =~ / /;
return "/say $override_trigger_name already exists for the global channel and cannot be overridden for " . ($chan eq '.*' ? 'the global channel' : $chan) . "."; return "/say $override_trigger_name already exists for the global channel and cannot be overridden for " . ($chan eq '.*' ? 'the global channel' : $chan) . ".";
} }
@ -837,7 +803,6 @@ sub factalias {
} }
$self->{pbot}->{factoids}->add_factoid('text', $chan, "$nick!$user\@$host", $alias, "/call $command"); $self->{pbot}->{factoids}->add_factoid('text', $chan, "$nick!$user\@$host", $alias, "/call $command");
$self->{pbot}->{logger}->log("$nick!$user\@$host [$chan] aliased $alias => $command\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host [$chan] aliased $alias => $command\n");
$self->{pbot}->{factoids}->save_factoids(); $self->{pbot}->{factoids}->save_factoids();
return "$alias aliases `$command` for " . ($chan eq '.*' ? 'the global channel' : $chan); return "$alias aliases `$command` for " . ($chan eq '.*' ? 'the global channel' : $chan);
@ -846,16 +811,15 @@ sub factalias {
sub add_regex { sub add_regex {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($keyword, $text) = $arguments =~ /^(.*?)\s+(.*)$/ if defined $arguments; my ($keyword, $text) = $arguments =~ /^(.*?)\s+(.*)$/ if defined $arguments;
$from = '.*' if not defined $from or $from !~ /^#/; $from = '.*' if not defined $from or $from !~ /^#/;
if (not defined $keyword) { if (not defined $keyword) {
$text = ""; $text = "";
foreach my $trigger (sort keys %{ $factoids->{lc $from} }) { foreach my $trigger (sort $factoids->get_keys($from)) {
next if $trigger eq '_name'; if ($factoids->get_data($from, $trigger, 'type') eq 'regex') {
if ($factoids->{$from}->{$trigger}->{type} eq 'regex') {
$text .= $trigger . " "; $text .= $trigger . " ";
} }
} }
@ -965,22 +929,21 @@ sub factadd {
my ($channel, $trigger) = $self->{pbot}->{factoids}->find_factoid($from_chan, $keyword, exact_channel => 1, exact_trigger => 1); my ($channel, $trigger) = $self->{pbot}->{factoids}->find_factoid($from_chan, $keyword, exact_channel => 1, exact_trigger => 1);
if (defined $trigger) { if (defined $trigger) {
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
if (not $force) { if (not $force) {
return "/say $trigger_name already exists for $channel_name."; return "/say $trigger_name already exists for $channel_name.";
} else { } else {
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
if ($factoids->{$channel}->{$trigger}->{'locked'}) { if ($factoids->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked; unlock before overwriting."; return "/say $trigger_name is locked; unlock before overwriting.";
} }
my ($owner) = $factoids->{$channel}->{$trigger}->{'owner'} =~ m/([^!]+)/; my ($owner) = $factoids->get_data($channel, $trigger, 'owner') =~ m/([^!]+)/;
if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host"))) { if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host"))) {
return "You are not the owner of $trigger_name for $channel_name; cannot force overwrite."; return "You are not the owner of $trigger_name for $channel_name; cannot force overwrite.";
} }
@ -988,8 +951,8 @@ sub factadd {
} }
($channel, $trigger) = $self->{pbot}->{factoids}->find_factoid('.*', $keyword, exact_channel => 1, exact_trigger => 1); ($channel, $trigger) = $self->{pbot}->{factoids}->find_factoid('.*', $keyword, exact_channel => 1, exact_trigger => 1);
if (defined $trigger and $self->{pbot}->{factoids}->{factoids}->{hash}->{'.*'}->{$trigger}->{'nooverride'}) { if (defined $trigger and $self->{pbot}->{factoids}->{factoids}->get_data('.*', $trigger, 'nooverride')) {
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
return "/say $trigger_name already exists for the global channel and cannot be overridden for " . ($from_chan eq '.*' ? 'the global channel' : $from_chan) . "."; return "/say $trigger_name already exists for the global channel and cannot be overridden for " . ($from_chan eq '.*' ? 'the global channel' : $from_chan) . ".";
} }
@ -999,7 +962,6 @@ sub factadd {
} }
$self->{pbot}->{factoids}->add_factoid('text', $from_chan, "$nick!$user\@$host", $keyword, $text); $self->{pbot}->{factoids}->add_factoid('text', $from_chan, "$nick!$user\@$host", $keyword, $text);
$self->{pbot}->{logger}->log("$nick!$user\@$host added [$from_chan] $keyword_text => $text\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host added [$from_chan] $keyword_text => $text\n");
return "/say $keyword_text added to " . ($from_chan eq '.*' ? 'global channel' : $from_chan) . "."; return "/say $keyword_text added to " . ($from_chan eq '.*' ? 'global channel' : $from_chan) . ".";
} }
@ -1007,7 +969,7 @@ sub factadd {
sub factrem { sub factrem {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($from_chan, $from_trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); my ($from_chan, $from_trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
@ -1022,12 +984,12 @@ sub factrem {
$channel = '.*' if $channel eq 'global'; $channel = '.*' if $channel eq 'global';
$from_chan = '.*' if $channel eq 'global'; $from_chan = '.*' if $channel eq 'global';
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $factoids->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $factoids->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
if ($factoids->{$channel}->{$trigger}->{type} eq 'module') { if ($factoids->get_data($channel, $trigger, 'type') eq 'module') {
return "/say $trigger_name is not a factoid."; return "/say $trigger_name is not a factoid.";
} }
@ -1035,17 +997,17 @@ sub factrem {
return "/say $trigger_name belongs to $channel_name, but this is $from_chan. Please switch to $channel_name or use /msg to remove this factoid."; return "/say $trigger_name belongs to $channel_name, but this is $from_chan. Please switch to $channel_name or use /msg to remove this factoid.";
} }
my ($owner) = $factoids->{$channel}->{$trigger}->{'owner'} =~ m/([^!]+)/; my ($owner) = $factoids->get_data($channel, $trigger, 'owner') =~ m/([^!]+)/;
if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host"))) { if ((lc $nick ne lc $owner) and (not $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host"))) {
return "You are not the owner of $trigger_name for $channel_name."; return "You are not the owner of $trigger_name for $channel_name.";
} }
if ($factoids->{$channel}->{$trigger}->{'locked'}) { if ($factoids->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked; unlock before deleting."; return "/say $trigger_name is locked; unlock before deleting.";
} }
$self->{pbot}->{logger}->log("$nick!$user\@$host removed [$channel][$trigger][" . $factoids->{$channel}->{$trigger}->{action} . "]\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host removed [$channel][$trigger][" . $factoids->get_data($channel, $trigger, 'action') . "]\n");
$self->{pbot}->{factoids}->remove_factoid($channel, $trigger); $self->{pbot}->{factoids}->remove_factoid($channel, $trigger);
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "deleted", 1); $self->log_factoid($channel, $trigger, "$nick!$user\@$host", "deleted", 1);
return "/say $trigger_name removed from $channel_name."; return "/say $trigger_name removed from $channel_name.";
@ -1054,14 +1016,13 @@ sub factrem {
sub histogram { sub histogram {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my %hash; my %hash;
my $factoid_count = 0; my $factoid_count = 0;
foreach my $channel (keys %$factoids) { foreach my $channel ($factoids->get_keys) {
foreach my $command (keys %{ $factoids->{$channel} }) { foreach my $command ($factoids->get_keys($channel)) {
next if $command eq '_name'; if ($factoids->get_data($channel, $command, 'type') eq 'text') {
if ($factoids->{$channel}->{$command}->{type} eq 'text') {
$hash{$factoids->{$channel}->{$command}->{owner}}++; $hash{$factoids->{$channel}->{$command}->{owner}}++;
$factoid_count++; $factoid_count++;
} }
@ -1070,7 +1031,6 @@ sub histogram {
my $text; my $text;
my $i = 0; my $i = 0;
foreach my $owner (sort {$hash{$b} <=> $hash{$a}} keys %hash) { foreach my $owner (sort {$hash{$b} <=> $hash{$a}} keys %hash) {
my $percent = int($hash{$owner} / $factoid_count * 100); my $percent = int($hash{$owner} / $factoid_count * 100);
$text .= "$owner: $hash{$owner} ($percent". "%)\n"; $text .= "$owner: $hash{$owner} ($percent". "%)\n";
@ -1083,10 +1043,8 @@ sub histogram {
sub factshow { sub factshow {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
$stuff->{preserve_whitespace} = 1; $stuff->{preserve_whitespace} = 1;
my $usage = "Usage: factshow [-p] [channel] <keyword>; -p to paste"; my $usage = "Usage: factshow [-p] [channel] <keyword>; -p to paste";
return $usage if not $arguments; return $usage if not $arguments;
@ -1105,35 +1063,27 @@ sub factshow {
return "Missing argument -- $usage" if not @$args; return "Missing argument -- $usage" if not @$args;
my ($chan, $trig) = @$args; my ($chan, $trig) = @$args;
$chan = $from if not defined $trig;
if (not defined $trig) {
$chan = $from;
}
$args = join(' ', map { $_ = "'$_'" if $_ =~ m/ /; $_; } @$args); $args = join(' ', map { $_ = "'$_'" if $_ =~ m/ /; $_; } @$args);
my ($channel, $trigger) = $self->find_factoid_with_optional_channel($from, $args, 'factshow', usage => $usage); my ($channel, $trigger) = $self->find_factoid_with_optional_channel($from, $args, 'factshow', usage => $usage);
return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $factoids->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $factoids->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $result = "$trigger_name: "; my $result = "$trigger_name: ";
if ($paste) { if ($paste) {
$result .= $self->{pbot}->{webpaste}->paste($factoids->{$channel}->{$trigger}->{action}, no_split => 1); $result .= $self->{pbot}->{webpaste}->paste($factoids->get_data($channel, $trigger, 'action'), no_split => 1);
$result = "[$channel_name] $result" if $channel ne lc $chan; $result = "[$channel_name] $result" if $channel ne lc $chan;
return $result; return $result;
} }
$result .= $factoids->{$channel}->{$trigger}->{action}; $result .= $factoids->get_data($channel, $trigger, 'action');
$result .= ' [module]' if $factoids->get_data($channel, $trigger, 'type') eq 'module';
if ($factoids->{$channel}->{$trigger}->{type} eq 'module') {
$result .= ' [module]';
}
$result = "[$channel_name] $result" if $channel ne lc $chan; $result = "[$channel_name] $result" if $channel ne lc $chan;
return $result; return $result;
} }
@ -1198,24 +1148,17 @@ sub factlog {
return ($h->{ts}, $h->{hm}, $h->{msg}); return ($h->{ts}, $h->{hm}, $h->{msg});
}; };
if ($@) { ($timestamp, $hostmask, $msg) = split /\s+/, $line, 3 if $@;
($timestamp, $hostmask, $msg) = split /\s+/, $line, 3; $hostmask =~ s/!.*$// if not $show_hostmask;
}
if (not $show_hostmask) {
$hostmask =~ s/!.*$//;
}
if ($actual_timestamp) { if ($actual_timestamp) {
$timestamp = strftime "%a %b %e %H:%M:%S %Z %Y", localtime $timestamp; $timestamp = strftime "%a %b %e %H:%M:%S %Z %Y", localtime $timestamp;
} else { } else {
$timestamp = concise ago gettimeofday - $timestamp; $timestamp = concise ago gettimeofday - $timestamp;
} }
push @entries, "[$timestamp] $hostmask $msg\n"; push @entries, "[$timestamp] $hostmask $msg\n";
} }
close $fh; close $fh;
my $result = join "", reverse @entries; my $result = join "", reverse @entries;
return $result; return $result;
} }
@ -1223,8 +1166,7 @@ sub factlog {
sub factinfo { sub factinfo {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($chan, $trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2); my ($chan, $trig) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
if (not defined $trig) { if (not defined $trig) {
@ -1235,29 +1177,29 @@ sub factinfo {
my ($channel, $trigger) = $self->find_factoid_with_optional_channel($from, $arguments, 'factinfo'); my ($channel, $trigger) = $self->find_factoid_with_optional_channel($from, $arguments, 'factinfo');
return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message return $channel if not defined $trigger; # if $trigger is not defined, $channel is an error message
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $factoids->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $factoids->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $created_ago = ago(gettimeofday - $factoids->{$channel}->{$trigger}->{created_on}); my $created_ago = ago(gettimeofday - $factoids->get_data($channel, $trigger, 'created_on'));
my $ref_ago = ago(gettimeofday - $factoids->{$channel}->{$trigger}->{last_referenced_on}) if defined $factoids->{$channel}->{$trigger}->{last_referenced_on}; my $ref_ago = ago(gettimeofday - $factoids->get_data($channel, $trigger, 'last_referenced_on')) if defined $factoids->get_data($channel, $trigger, 'last_referenced_on');
# factoid # factoid
if ($factoids->{$channel}->{$trigger}->{type} eq 'text') { if ($factoids->get_data($channel, $trigger, 'type') eq 'text') {
return "/say $trigger_name: Factoid submitted by " . $factoids->{$channel}->{$trigger}->{owner} . " for $channel_name on " . localtime($factoids->{$channel}->{$trigger}->{created_on}) . " [$created_ago], " . (defined $factoids->{$channel}->{$trigger}->{edited_by} ? "last edited by $factoids->{$channel}->{$trigger}->{edited_by} on " . localtime($factoids->{$channel}->{$trigger}->{edited_on}) . " [" . ago(gettimeofday - $factoids->{$channel}->{$trigger}->{edited_on}) . "], " : "") . "referenced " . $factoids->{$channel}->{$trigger}->{ref_count} . " times (last by " . $factoids->{$channel}->{$trigger}->{ref_user} . (exists $factoids->{$channel}->{$trigger}->{last_referenced_on} ? " on " . localtime($factoids->{$channel}->{$trigger}->{last_referenced_on}) . " [$ref_ago]" : "") . ")"; return "/say $trigger_name: Factoid submitted by " . $factoids->get_data($channel, $trigger, 'owner') . " for $channel_name on " . localtime($factoids->get_data($channel, $trigger, 'created_on')) . " [$created_ago], " . (defined $factoids->get_data($channel, $trigger, 'edited_by') ? 'last edited by ' . $factoids->get_data($channel, $trigger, 'edited_by') . ' on ' . localtime($factoids->get_data($channel, $trigger, 'edited_on')) . " [" . ago(gettimeofday - $factoids->get_data($channel, $trigger, 'edited_on')) . "], " : "") . "referenced " . $factoids->get_data($channel, $trigger, 'ref_count') . ' times (last by ' . $factoids->get_data($channel, $trigger, 'ref_user') . ($factoids->exists($channel, $trigger, 'last_referenced_on') ? ' on ' . localtime($factoids->get_data($channel, $trigger, 'last_referenced_on')) . " [$ref_ago]" : '') . ')';
} }
# module # module
if ($factoids->{$channel}->{$trigger}->{type} eq 'module') { if ($factoids->get_data($channel, $trigger, 'type') eq 'module') {
my $module_repo = $self->{pbot}->{registry}->get_value('general', 'module_repo'); my $module_repo = $self->{pbot}->{registry}->get_value('general', 'module_repo');
$module_repo .= "$factoids->{$channel}->{$trigger}->{workdir}/" if exists $factoids->{$channel}->{$trigger}->{workdir}; $module_repo .= $factoids->get_data($channel, $trigger, 'workdir'). '/' if $factoids->exists($channel, $trigger, 'workdir');
return "/say $trigger_name: Module loaded by " . $factoids->{$channel}->{$trigger}->{owner} . " for $channel_name on " . localtime($factoids->{$channel}->{$trigger}->{created_on}) . " [$created_ago] -> $module_repo" . $factoids->{$channel}->{$trigger}->{action} . ", used " . $factoids->{$channel}->{$trigger}->{ref_count} . " times (last by " . $factoids->{$channel}->{$trigger}->{ref_user} . (exists $factoids->{$channel}->{$trigger}->{last_referenced_on} ? " on " . localtime($factoids->{$channel}->{$trigger}->{last_referenced_on}) . " [$ref_ago]" : "") . ")"; return "/say $trigger_name: Module loaded by " . $factoids->get_data($channel, $trigger, 'owner') . " for $channel_name on " . localtime($factoids->get_data($channel, $trigger, 'created_on')) . " [$created_ago] -> $module_repo" . $factoids->get_data($channel, $trigger, 'action') . ', used ' . $factoids->get_data($channel, $trigger, 'ref_count') . ' times (last by ' . $factoids->get_data($channel, $trigger, 'ref_user') . ($factoids->exists($channel, $trigger, 'last_referenced_on') ? ' on ' . localtime($factoids->get_data($channel, $trigger, 'last_referenced_on')) . " [$ref_ago]" : '') . ')';
} }
# regex # regex
if ($factoids->{$channel}->{$trigger}->{type} eq 'regex') { if ($factoids->get_data($channel, $trigger, 'type') eq 'regex') {
return "/say $trigger_name: Regex created by " . $factoids->{$channel}->{$trigger}->{owner} . " for $channel_name on " . localtime($factoids->{$channel}->{$trigger}->{created_on}) . " [$created_ago], " . (defined $factoids->{$channel}->{$trigger}->{edited_by} ? "last edited by $factoids->{$channel}->{$trigger}->{edited_by} on " . localtime($factoids->{$channel}->{$trigger}->{edited_on}) . " [" . ago(gettimeofday - $factoids->{$channel}->{$trigger}->{edited_on}) . "], " : "") . " used " . $factoids->{$channel}->{$trigger}->{ref_count} . " times (last by " . $factoids->{$channel}->{$trigger}->{ref_user} . (exists $factoids->{$channel}->{$trigger}->{last_referenced_on} ? " on " . localtime($factoids->{$channel}->{$trigger}->{last_referenced_on}) . " [$ref_ago]" : "") . ")"; return "/say $trigger_name: Regex created by " . $factoids->get_data($channel, $trigger, 'owner') . " for $channel_name on " . localtime($factoids->get_data($channel, $trigger, 'created_on')) . " [$created_ago], " . (defined $factoids->get_data($channel, $trigger, 'edited_by') ? 'last edited by ' . $factoids->get_data($channel, $trigger, 'edited_by') . ' on ' . localtime($factoids->get_data($channel, $trigger, 'edited_on')) . " [" . ago(gettimeofday - $factoids->get_data($channel, $trigger, 'edited_on')) . "], " : "") . ' used ' . $factoids->get_data($channel, $trigger, 'ref_count') . ' times (last by ' . $factoids->get_data($channel, $trigger, 'ref_user') . ($factoids->exists($channel, $trigger, 'last_referenced_on') ? ' on ' . localtime($factoids->get_data($channel, $trigger, 'last_referenced_on')) . " [$ref_ago]" : '') . ')';
} }
return "/say $arguments is not a factoid or a module."; return "/say $arguments is not a factoid or a module.";
@ -1266,7 +1208,7 @@ sub factinfo {
sub top20 { sub top20 {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my %hash = (); my %hash = ();
my $text = ""; my $text = "";
my $i = 0; my $i = 0;
@ -1278,12 +1220,11 @@ sub top20 {
} }
if (not defined $args) { if (not defined $args) {
foreach my $chan (sort keys %{ $factoids }) { foreach my $chan (sort $factoids->get_keys) {
next if lc $chan ne lc $channel; next if lc $chan ne lc $channel;
foreach my $command (sort {$factoids->{$chan}->{$b}->{ref_count} <=> $factoids->{$chan}->{$a}->{ref_count}} keys %{ $factoids->{$chan} }) { foreach my $command (sort {$factoids->get_data($chan, $b, 'ref_count') <=> $factoids->get_data($chan, $a, 'ref_count')} $factoids->get_keys($chan)) {
next if $command eq '_name'; if ($factoids->get_data($chan, $command, 'ref_count') > 0 and $factoids->get_data($chan, $command, 'type') eq 'text') {
if ($factoids->{$chan}->{$command}->{ref_count} > 0 and $factoids->{$chan}->{$command}->{type} eq 'text') { $text .= $factoids->get_data($chan, $command, '_name') . ' (' . $factoids->get_data($chan, $command, 'ref_count') . ') ';
$text .= "$factoids->{$chan}->{$command}->{_name} ($factoids->{$chan}->{$command}->{ref_count}) ";
$i++; $i++;
last if $i >= 20; last if $i >= 20;
} }
@ -1294,14 +1235,13 @@ sub top20 {
} }
} else { } else {
if (lc $args eq "recent") { if (lc $args eq "recent") {
foreach my $chan (sort keys %{ $factoids }) { foreach my $chan (sort $factoids->get_keys) {
next if lc $chan ne lc $channel; next if lc $chan ne lc $channel;
foreach my $command (sort { $factoids->{$chan}->{$b}{created_on} <=> $factoids->{$chan}->{$a}{created_on} } keys %{ $factoids->{$chan} }) { foreach my $command (sort { $factoids->get_data($chan, $b, 'created_on') <=> $factoids->get_data($chan, $a, 'created_on') } $factoids->get_keys($chan)) {
next if $command eq '_name'; my $ago = concise ago gettimeofday - $factoids->get_data($chan, $command, 'created_on');
my $ago = concise ago gettimeofday - $factoids->{$chan}->{$command}->{created_on}; my $owner = $factoids->get_data($chan, $command, 'owner');
my $owner = $factoids->{$chan}->{$command}->{owner};
$owner =~ s/!.*$//; $owner =~ s/!.*$//;
$text .= " $factoids->{$chan}->{$command}->{_name} [$ago by $owner]\n"; $text .= ' ' . $factoids->get_data($chan, $command, '_name') . " [$ago by $owner]\n";
$i++; $i++;
last if $i >= 50; last if $i >= 50;
} }
@ -1312,16 +1252,17 @@ sub top20 {
} }
my $user = lc $args; my $user = lc $args;
foreach my $chan (sort keys %{ $factoids }) { foreach my $chan (sort $factoids->get_keys) {
next if lc $chan ne lc $channel; next if lc $chan ne lc $channel;
foreach my $command (sort { ($factoids->{$chan}->{$b}->{last_referenced_on} || 0) <=> ($factoids->{$chan}->{$a}->{last_referenced_on} || 0) } keys %{ $factoids->{$chan} }) { foreach my $command (sort { ($factoids->get_data($chan, $b, 'last_referenced_on') || 0) <=> ($factoids->get_data($chan, $a, 'last_referenced_on') || 0) } $factoids->get_keys($chan)) {
next if $command eq '_name'; next if $command eq '_name';
if ($factoids->{$chan}->{$command}->{ref_user} =~ /\Q$args\E/i) { my $ref_user = lc $factoids->get_data($chan, $command, 'ref_user');
if ($user ne lc $factoids->{$chan}->{$command}->{ref_user} && not $user =~ /$factoids->{$chan}->{$command}->{ref_user}/i) { if ($ref_user =~ /\Q$args\E/i) {
$user .= " ($factoids->{$chan}->{$command}->{ref_user})"; if ($user ne $ref_user && not $user =~ /$ref_user/i) {
$user .= " ($ref_user)";
} }
my $ago = $factoids->{$chan}->{$command}{last_referenced_on} ? concise ago(gettimeofday - $factoids->{$chan}->{$command}{last_referenced_on}) : "unknown"; my $ago = $factoids->get_data($chan, $command, 'last_referenced_on') ? concise ago(gettimeofday - $factoids->get_data($chan, $command, 'last_referenced_on')) : "unknown";
$text .= " $factoids->{$chan}->{$command}->{_name} [$ago]\n"; $text .= ' ' . $factoids->get_data($chan, $command, '_name') . " [$ago]\n";
$i++; $i++;
last if $i >= 20; last if $i >= 20;
} }
@ -1335,7 +1276,7 @@ sub top20 {
sub count { sub count {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my $i = 0; my $i = 0;
my $total = 0; my $total = 0;
@ -1346,12 +1287,12 @@ sub count {
$arguments = ".*" if ($arguments =~ /^factoids$/); $arguments = ".*" if ($arguments =~ /^factoids$/);
eval { eval {
foreach my $channel (keys %{ $factoids }) { foreach my $channel ($factoids->get_keys) {
foreach my $command (keys %{ $factoids->{$channel} }) { foreach my $command ($factoids->get_keys($channel)) {
next if $command eq '_name'; next if $command eq '_name';
next if $factoids->{$channel}->{$command}->{type} ne 'text'; next if $factoids->get_data($channel, $command, 'type') ne 'text';
$total++; $total++;
if ($factoids->{$channel}->{$command}->{owner} =~ /^\Q$arguments\E$/i) { if ($factoids->get_data($channel, $command, 'owner') =~ /^\Q$arguments\E$/i) {
$i++; $i++;
} }
} }
@ -1373,16 +1314,12 @@ sub count {
sub factfind { sub factfind {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash};
my $usage = "Usage: factfind [-channel channel] [-owner regex] [-editby regex] [-refby regex] [-regex] [text]"; my $usage = "Usage: factfind [-channel channel] [-owner regex] [-editby regex] [-refby regex] [-regex] [text]";
return $usage if not defined $arguments;
if (not defined $arguments) { my $factoids = $self->{pbot}->{factoids}->{factoids};
return $usage;
}
my ($channel, $owner, $refby, $editby, $use_regex); my ($channel, $owner, $refby, $editby, $use_regex);
$channel = $1 if $arguments =~ s/\s*-channel\s+([^\b\s]+)//i; $channel = $1 if $arguments =~ s/\s*-channel\s+([^\b\s]+)//i;
$owner = $1 if $arguments =~ s/\s*-owner\s+([^\b\s]+)//i; $owner = $1 if $arguments =~ s/\s*-owner\s+([^\b\s]+)//i;
$refby = $1 if $arguments =~ s/\s*-refby\s+([^\b\s]+)//i; $refby = $1 if $arguments =~ s/\s*-refby\s+([^\b\s]+)//i;
@ -1398,12 +1335,9 @@ sub factfind {
$arguments =~ s/\s+/ /g; $arguments =~ s/\s+/ /g;
$arguments = substr($arguments, 0, 30); $arguments = substr($arguments, 0, 30);
my $argtype = undef; my $argtype = undef;
if ($owner ne '.*') { $argtype = "owned by $owner" if $owner ne '.*';
$argtype = "owned by $owner";
}
if ($refby ne '.*') { if ($refby ne '.*') {
if (not defined $argtype) { if (not defined $argtype) {
@ -1450,21 +1384,21 @@ sub factfind {
$regex .= ($arguments =~ m/\w$/) ? '\b' : '\B'; $regex .= ($arguments =~ m/\w$/) ? '\b' : '\B';
} }
foreach my $chan (sort keys %{ $factoids }) { foreach my $chan (sort $factoids->get_keys) {
next if defined $channel and $chan !~ /^$channel$/i; next if defined $channel and $chan !~ /^$channel$/i;
foreach my $trigger (sort keys %{ $factoids->{$chan} }) { foreach my $trigger (sort $factoids->get_keys($chan)) {
next if $trigger eq '_name'; next if $trigger eq '_name';
if ($factoids->{$chan}->{$trigger}->{type} eq 'text' or $factoids->{$chan}->{$trigger}->{type} eq 'regex') { if ($factoids->get_data($chan, $trigger, 'type') eq 'text' or $factoids->get_data($chan, $trigger, 'type') eq 'regex') {
if ($factoids->{$chan}->{$trigger}->{owner} =~ /^$owner$/i if ($factoids->get_data($chan, $trigger, 'owner') =~ /^$owner$/i
&& $factoids->{$chan}->{$trigger}->{ref_user} =~ /^$refby$/i && $factoids->get_data($chan, $trigger, 'ref_user') =~ /^$refby$/i
&& (exists $factoids->{$chan}->{$trigger}->{edited_by} ? $factoids->{$chan}->{$trigger}->{edited_by} =~ /^$editby$/i : 1)) { && ($factoids->exists($chan, $trigger, 'edited_by') ? $factoids->get_data($chan, $trigger, 'edited_by') =~ /^$editby$/i : 1)) {
next if ($arguments ne "" && $factoids->{$chan}->{$trigger}->{action} !~ /$regex/i && $trigger !~ /$regex/i); next if ($arguments ne "" && $factoids->get_data($chan, $trigger, 'action') !~ /$regex/i && $trigger !~ /$regex/i);
$i++; $i++;
if ($chan ne $last_chan) { if ($chan ne $last_chan) {
$text .= $chan eq '.*' ? "[global channel] " : "[$factoids->{$chan}->{_name}] "; $text .= $chan eq '.*' ? '[global channel] ' : '[' . $factoids->get_data($chan, '_name') . '] ';
$last_chan = $chan; $last_chan = $chan;
} }
my $trigger_name = $factoids->{$chan}->{$trigger}->{_name}; my $trigger_name = $factoids->get_data($chan, $trigger, '_name');
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
$text .= "$trigger_name "; $text .= "$trigger_name ";
$last_trigger = $trigger_name; $last_trigger = $trigger_name;
@ -1478,7 +1412,7 @@ sub factfind {
if ($i == 1) { if ($i == 1) {
chop $text; chop $text;
return "Found one factoid submitted for " . ($last_chan eq '.*' ? 'global channel' : $factoids->{$last_chan}->{_name}) . " " . $argtype . ": $last_trigger is $factoids->{$last_chan}->{$last_trigger}->{action}"; return "Found one factoid submitted for " . ($last_chan eq '.*' ? 'global channel' : $factoids->get_data($last_chan, '_name')) . ' ' . $argtype . ": $last_trigger is " . $factoids->get_data($last_chan, $last_trigger, 'action');
} else { } else {
return "Found $i factoids " . $argtype . ": $text" unless $i == 0; return "Found $i factoids " . $argtype . ": $text" unless $i == 0;
my $chans = (defined $channel ? ($channel eq '.*' ? 'global channel' : $channel) : 'any channels'); my $chans = (defined $channel ? ($channel eq '.*' ? 'global channel' : $channel) : 'any channels');
@ -1489,7 +1423,7 @@ sub factfind {
sub factchange { sub factchange {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $factoids_hash = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids_data = $self->{pbot}->{factoids}->{factoids};
my ($channel, $trigger, $keyword, $delim, $tochange, $changeto, $modifier, $url); my ($channel, $trigger, $keyword, $delim, $tochange, $changeto, $modifier, $url);
$stuff->{preserve_whitespace} = 1; $stuff->{preserve_whitespace} = 1;
@ -1572,8 +1506,8 @@ sub factchange {
return "/say $keyword not found in channel $from_chan."; return "/say $keyword not found in channel $from_chan.";
} }
my $channel_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
@ -1584,15 +1518,15 @@ sub factchange {
} }
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host"); my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids_hash->{$channel}->{$trigger}->{'locked'}) { if ($factoids_data->get_data($channel, $trigger, 'locked')) {
return "/say $trigger_name is locked and cannot be changed." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin'); return "/say $trigger_name is locked and cannot be changed." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids_hash->{$channel}->{$trigger}->{'cap-override'} and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) { if ($factoids_data->exists($channel, $trigger, 'cap-override') and not $self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
return "/say $trigger_name is locked with a cap-override set and cannot be changed until the override is removed."; return "/say $trigger_name is locked with a cap-override set and cannot be changed until the override is removed.";
} }
} }
my $action = $factoids_hash->{$channel}->{$trigger}->{action}; my $action = $factoids_data->get_data($channel, $trigger, 'action');
if (defined $url) { if (defined $url) {
# FIXME: move this to registry # FIXME: move this to registry
@ -1680,54 +1614,51 @@ sub factchange {
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed '$trigger' 's/$tochange/$changeto/\n"); $self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed '$trigger' 's/$tochange/$changeto/\n");
$factoids_hash->{$channel}->{$trigger}->{action} = $action; $factoids_data->set($channel, $trigger, 'action', $action, 1);
$factoids_hash->{$channel}->{$trigger}->{edited_by} = "$nick!$user\@$host"; $factoids_data->set($channel, $trigger, 'edited_by', "$nick!$user\@$host", 1);
$factoids_hash->{$channel}->{$trigger}->{edited_on} = gettimeofday; $factoids_data->set($channel, $trigger, 'edited_on', gettimeofday);
$self->{pbot}->{factoids}->save_factoids(); $self->log_factoid($channel, $trigger, "$nick!$user\@$host", "changed to $action");
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "changed to $factoids_hash->{$channel}->{$trigger}->{action}"); return "Changed: $trigger_name is $action";
return "Changed: $trigger_name is " . $factoids_hash->{$channel}->{$trigger}->{action};
} }
# FIXME: these two functions need to use $stuff->{arglist} # FIXME: these two functions need to use $stuff->{arglist}
sub load_module { sub load_module {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($keyword, $module) = $arguments =~ /^(.*?)\s+(.*)$/ if defined $arguments; my ($keyword, $module) = $arguments =~ /^(.*?)\s+(.*)$/ if defined $arguments;
if (not defined $module) { if (not defined $module) {
return "Usage: load <keyword> <module>"; return "Usage: load <keyword> <module>";
} }
if (not exists($factoids->{'.*'}->{lc $keyword})) { if (not $factoids->exists('.*', $keyword)) {
$self->{pbot}->{factoids}->add_factoid('module', '.*', "$nick!$user\@$host", $keyword, $module); $self->{pbot}->{factoids}->add_factoid('module', '.*', "$nick!$user\@$host", $keyword, $module, 1);
$factoids->{'.*'}->{lc $keyword}->{add_nick} = 1; $factoids->set('.*', $keyword, 'add_nick', 1, 1);
$factoids->{'.*'}->{lc $keyword}->{nooverride} = 1; $factoids->set('.*', $keyword, 'nooverride', 1);
$self->{pbot}->{logger}->log("$nick!$user\@$host loaded module $keyword => $module\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host loaded module $keyword => $module\n");
$self->{pbot}->{factoids}->save_factoids();
return "Loaded module $keyword => $module"; return "Loaded module $keyword => $module";
} else { } else {
return "There is already a keyword named $factoids->{'.*'}->{$keyword}->{_name}."; return 'There is already a keyword named ' . $factoids->get_data('.*', $keyword, '_name') . '.';
} }
} }
sub unload_module { sub unload_module {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash}; my $factoids = $self->{pbot}->{factoids}->{factoids};
if (not defined $arguments) { if (not defined $arguments) {
return "Usage: unload <keyword>"; return "Usage: unload <keyword>";
} elsif (not exists $factoids->{'.*'}->{lc $arguments}) { } elsif (not $factoids->exists('.*', $arguments)) {
return "/say $arguments not found."; return "/say $arguments not found.";
} elsif ($factoids->{'.*'}->{lc $arguments}->{type} ne 'module') { } elsif ($factoids->get_data('.*', $arguments, 'type') ne 'module') {
return "/say " . $factoids->{'.*'}->{lc $arguments}->{_name} . " is not a module."; return "/say " . $factoids->get_data('.*', $arguments, '_name') . ' is not a module.';
} else { } else {
my $data = delete $factoids->{'.*'}->{lc $arguments}; my $name = $factoids->get_data('.*', $arguments, '_name');
$self->{pbot}->{factoids}->save_factoids(); $factoids->remove('.*', $arguments);
$self->{pbot}->{logger}->log("$nick!$user\@$host unloaded module $arguments\n"); $self->{pbot}->{logger}->log("$nick!$user\@$host unloaded module $arguments\n");
return "/say $data->{_name} unloaded."; return "/say $name unloaded.";
} }
} }

View File

@ -53,7 +53,7 @@ sub execute_module {
$stuff->{keyword} = $trigger; $stuff->{keyword} = $trigger;
$stuff->{trigger} = $trigger; $stuff->{trigger} = $trigger;
my $module = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{action}; my $module = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'action');
my $module_dir = $self->{pbot}->{registry}->get_value('general', 'module_dir'); my $module_dir = $self->{pbot}->{registry}->get_value('general', 'module_dir');
$self->{pbot}->{logger}->log("(" . (defined $stuff->{from} ? $stuff->{from} : "(undef)") . "): $stuff->{nick}!$stuff->{user}\@$stuff->{host}: Executing module [$stuff->{command}] $module $stuff->{arguments}\n"); $self->{pbot}->{logger}->log("(" . (defined $stuff->{from} ? $stuff->{from} : "(undef)") . "): $stuff->{nick}!$stuff->{user}\@$stuff->{host}: Executing module [$stuff->{command}] $module $stuff->{arguments}\n");
@ -87,8 +87,8 @@ sub execute_module {
Carp::croak("Could not chdir to '$module_dir': $!"); Carp::croak("Could not chdir to '$module_dir': $!");
} }
if (exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{workdir}) { if ($self->{pbot}->{factoids}->{factoids}->exists($channel, $trigger, 'workdir')) {
chdir $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{workdir}; chdir $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'workdir');
} }
my ($exitval, $stdout, $stderr) = eval { my ($exitval, $stdout, $stderr) = eval {
@ -170,7 +170,7 @@ sub module_pipe_reader {
$self->{pbot}->{interpreter}->handle_result($stuff, $stuff->{result}); $self->{pbot}->{interpreter}->handle_result($stuff, $stuff->{result});
} else { } else {
# don't override nick if already set # don't override nick if already set
if (exists $stuff->{special} and $stuff->{special} ne 'code-factoid' and exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$stuff->{channel}}->{$stuff->{trigger}}->{add_nick} and $self->{pbot}->{factoids}->{factoids}->{hash}->{$stuff->{channel}}->{$stuff->{trigger}}->{add_nick} != 0) { if (exists $stuff->{special} and $stuff->{special} ne 'code-factoid' and $self->{pbot}->{factoids}->{factoids}->exists($stuff->{channel}, $stuff->{trigger}, 'add_nick') and $self->{pbot}->{factoids}->{factoids}->get_data($stuff->{channel}, $stuff->{trigger}, 'add_nick') != 0) {
$stuff->{nickoverride} = $stuff->{nick}; $stuff->{nickoverride} = $stuff->{nick};
$stuff->{no_nickoverride} = 0; $stuff->{no_nickoverride} = 0;
$stuff->{force_nickoverride} = 1; $stuff->{force_nickoverride} = 1;

View File

@ -53,13 +53,13 @@ sub load_factoids {
$self->{factoids}->load; $self->{factoids}->load;
my ($text, $regex, $modules); my ($text, $regex, $modules);
foreach my $channel (keys %{ $self->{factoids}->{hash} }) { foreach my $channel ($self->{factoids}->get_keys) {
foreach my $trigger (keys %{ $self->{factoids}->{hash}->{$channel} }) { foreach my $trigger ($self->{factoids}->get_keys($channel)) {
next if $trigger eq '_name'; next if $trigger eq '_name';
$self->{pbot}->{logger}->log("Missing type for $channel->$trigger\n") if not $self->{factoids}->{hash}->{$channel}->{$trigger}->{type}; $self->{pbot}->{logger}->log("Missing type for $channel->$trigger\n") if not $self->{factoids}->get_data($channel, $trigger, 'type');
$text++ if $self->{factoids}->{hash}->{$channel}->{$trigger}->{type} eq 'text'; $text++ if $self->{factoids}->get_data($channel, $trigger, 'type') eq 'text';
$regex++ if $self->{factoids}->{hash}->{$channel}->{$trigger}->{type} eq 'regex'; $regex++ if $self->{factoids}->get_data($channel, $trigger, 'type') eq 'regex';
$modules++ if $self->{factoids}->{hash}->{$channel}->{$trigger}->{type} eq 'module'; $modules++ if $self->{factoids}->get_data($channel, $trigger, 'type') eq 'module';
} }
} }
$self->{pbot}->{logger}->log(" " . ($text + $regex + $modules) . " factoids loaded ($text text, $regex regexs, $modules modules).\n"); $self->{pbot}->{logger}->log(" " . ($text + $regex + $modules) . " factoids loaded ($text text, $regex regexs, $modules modules).\n");
@ -77,21 +77,19 @@ sub get_meta {
$trigger = lc $trigger; $trigger = lc $trigger;
my ($chan, $trig) = $self->find_factoid($channel, $trigger, exact_channel => 1); my ($chan, $trig) = $self->find_factoid($channel, $trigger, exact_channel => 1);
return undef if not defined $chan; return undef if not defined $chan;
return $self->{factoids}->{hash}->{$chan}->{$trig}->{$key}; return $self->{factoids}->get_data($chan, $trig, $key);
} }
sub add_factoid { sub add_factoid {
my $self = shift; my $self = shift;
my ($type, $channel, $owner, $trigger, $action, $dont_save) = @_; my ($type, $channel, $owner, $trigger, $action, $dont_save) = @_;
$type = lc $type; $type = lc $type;
$channel = '.*' if $channel !~ /^#/; $channel = '.*' if $channel !~ /^#/;
my $data; my $data;
if ($self->{factoids}->exists($channel, $trigger)) {
if (exists $self->{factoids}->{hash}->{lc $channel} and exists $self->{factoids}->{hash}->{lc $channel}->{lc $trigger}) {
# only update action field if force-adding it through factadd -f # only update action field if force-adding it through factadd -f
$data = $self->{factoids}->{hash}->{lc $channel}->{lc $trigger}; $data = $self->{factoids}->get_data($channel, $trigger);
$data->{action} = $action; $data->{action} = $action;
$data->{type} = $type; $data->{type} = $type;
} else { } else {
@ -107,28 +105,15 @@ sub add_factoid {
}; };
} }
$self->{commands}->log_factoid($channel, $trigger, $owner, "created: $action") unless $dont_save;
$self->{factoids}->add($channel, $trigger, $data, $dont_save); $self->{factoids}->add($channel, $trigger, $data, $dont_save);
unless ($dont_save) {
$self->{commands}->log_factoid($channel, $trigger, $owner, "created: $action");
}
} }
sub remove_factoid { sub remove_factoid {
my $self = shift; my $self = shift;
my ($channel, $trigger) = @_; my ($channel, $trigger) = @_;
$channel = '.*' if $channel !~ /^#/; $channel = '.*' if $channel !~ /^#/;
$channel = lc $channel; $self->{factoids}->remove($channel, $trigger);
$trigger = lc $trigger;
delete $self->{factoids}->{hash}->{$channel}->{$trigger};
if (scalar keys %{ $self->{factoids}->{hash}->{$channel} } == 1) {
delete $self->{factoids}->{hash}->{$channel};
}
$self->save_factoids;
} }
sub export_factoids { sub export_factoids {
@ -152,17 +137,17 @@ sub export_factoids {
my $i = 0; my $i = 0;
my $table_id = 1; my $table_id = 1;
foreach my $channel (sort keys %{ $self->{factoids}->{hash} }) { foreach my $channel (sort $self->{factoids}->get_keys) {
next if not scalar keys %{ $self->{factoids}->{hash}->{$channel} }; next if not $self->{factoids}->get_keys($channel);
my $chan = $self->{factoids}->{hash}->{$channel}->{_name}; my $chan = $self->{factoids}->get_data($channel, '_name');
$chan = 'global' if $chan eq '.*'; $chan = 'global' if $chan eq '.*';
print FILE "<a href='#" . encode_entities($chan) . "'>" . encode_entities($chan) . "</a><br>\n"; print FILE "<a href='#" . encode_entities($chan) . "'>" . encode_entities($chan) . "</a><br>\n";
} }
foreach my $channel (sort keys %{ $self->{factoids}->{hash} }) { foreach my $channel (sort $self->{factoids}->get_keys) {
next if not scalar keys %{ $self->{factoids}->{hash}->{$channel} }; next if not $self->{factoids}->get_keys($channel);
my $chan = $self->{factoids}->{hash}->{$channel}->{_name}; my $chan = $self->{factoids}->get_data($channel, '_name');
$chan = 'global' if $chan eq '.*'; $chan = 'global' if $chan eq '.*';
print FILE "<a name='" . encode_entities($chan) . "'></a>\n"; print FILE "<a name='" . encode_entities($chan) . "'></a>\n";
print FILE "<hr>\n<h3>" . encode_entities($chan) . "</h3>\n<hr>\n"; print FILE "<hr>\n<h3>" . encode_entities($chan) . "</h3>\n<hr>\n";
@ -179,10 +164,9 @@ sub export_factoids {
print FILE "</tr>\n</thead>\n<tbody>\n"; print FILE "</tr>\n</thead>\n<tbody>\n";
$table_id++; $table_id++;
foreach my $trigger (sort keys %{ $self->{factoids}->{hash}->{$channel} }) { foreach my $trigger (sort $self->{factoids}->get_keys($channel)) {
next if $trigger eq '_name'; my $trigger_name = $self->{factoids}->get_data($channel, $trigger, '_name');
my $trigger_name = $self->{factoids}->{hash}->{$channel}->{$trigger}->{_name}; if ($self->{factoids}->get_data($channel, $trigger, 'type') eq 'text') {
if ($self->{factoids}->{hash}->{$channel}->{$trigger}->{type} eq 'text') {
$i++; $i++;
if ($i % 2) { if ($i % 2) {
print FILE "<tr bgcolor=\"#dddddd\">\n"; print FILE "<tr bgcolor=\"#dddddd\">\n";
@ -190,12 +174,12 @@ sub export_factoids {
print FILE "<tr>\n"; print FILE "<tr>\n";
} }
print FILE "<td>" . encode_entities($self->{factoids}->{hash}->{$channel}->{$trigger}->{owner}) . "</td>\n"; print FILE "<td>" . encode_entities($self->{factoids}->get_data($channel, $trigger, 'owner')) . "</td>\n";
print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->{hash}->{$channel}->{$trigger}->{created_on}) . "</td>\n"; print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->get_data($channel, $trigger, 'created_on')) . "</td>\n";
print FILE "<td>" . $self->{factoids}->{hash}->{$channel}->{$trigger}->{ref_count} . "</td>\n"; print FILE "<td>" . $self->{factoids}->get_data($channel, $trigger, 'ref_count') . "</td>\n";
my $action = $self->{factoids}->{hash}->{$channel}->{$trigger}->{action}; my $action = $self->{factoids}->get_data($channel, $trigger, 'action');
if ($action =~ m/https?:\/\/[^ ]+/) { if ($action =~ m/https?:\/\/[^ ]+/) {
$action =~ s/(.*?)http(s?:\/\/[^ ]+)/encode_entities($1) . "<a href='http" . encode_entities($2) . "'>http" . encode_entities($2) . "<\/a>"/ge; $action =~ s/(.*?)http(s?:\/\/[^ ]+)/encode_entities($1) . "<a href='http" . encode_entities($2) . "'>http" . encode_entities($2) . "<\/a>"/ge;
@ -204,8 +188,8 @@ sub export_factoids {
$action = encode_entities($action); $action = encode_entities($action);
} }
if (exists $self->{factoids}->{hash}->{$channel}->{$trigger}->{action_with_args}) { if ($self->{factoids}->exists($channel, $trigger, 'action_with_args')) {
my $with_args = $self->{factoids}->{hash}->{$channel}->{$trigger}->{action_with_args}; my $with_args = $self->{factoids}->get_data($channel, $trigger, 'action_with_args');
$with_args =~ s/(.*?)http(s?:\/\/[^ ]+)/encode_entities($1) . "<a href='http" . encode_entities($2) . "'>http" . encode_entities($2) . "<\/a>"/ge; $with_args =~ s/(.*?)http(s?:\/\/[^ ]+)/encode_entities($1) . "<a href='http" . encode_entities($2) . "'>http" . encode_entities($2) . "<\/a>"/ge;
$with_args =~ s/(.*)<\/a>(.*$)/"$1<\/a>" . encode_entities($2)/e; $with_args =~ s/(.*)<\/a>(.*$)/"$1<\/a>" . encode_entities($2)/e;
print FILE "<td width=100%><b>" . encode_entities($trigger_name) . "</b> is $action<br><br><b>with_args:</b> " . encode_entities($with_args) . "</td>\n"; print FILE "<td width=100%><b>" . encode_entities($trigger_name) . "</b> is $action<br><br><b>with_args:</b> " . encode_entities($with_args) . "</td>\n";
@ -213,18 +197,18 @@ sub export_factoids {
print FILE "<td width=100%><b>" . encode_entities($trigger_name) . "</b> is $action</td>\n"; print FILE "<td width=100%><b>" . encode_entities($trigger_name) . "</b> is $action</td>\n";
} }
if (exists $self->{factoids}->{hash}->{$channel}->{$trigger}->{edited_by}) { if ($self->{factoids}->exists($channel, $trigger, 'edited_by')) {
print FILE "<td>" . $self->{factoids}->{hash}->{$channel}->{$trigger}->{edited_by} . "</td>\n"; print FILE "<td>" . $self->{factoids}->get_data($channel, $trigger, 'edited_by') . "</td>\n";
print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->{hash}->{$channel}->{$trigger}->{edited_on}) . "</td>\n"; print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->get_data($channel, $trigger, 'edited_on')) . "</td>\n";
} else { } else {
print FILE "<td></td>\n"; print FILE "<td></td>\n";
print FILE "<td></td>\n"; print FILE "<td></td>\n";
} }
print FILE "<td>" . encode_entities($self->{factoids}->{hash}->{$channel}->{$trigger}->{ref_user}) . "</td>\n"; print FILE "<td>" . encode_entities($self->{factoids}->get_data($channel, $trigger, 'ref_user')) . "</td>\n";
if (exists $self->{factoids}->{hash}->{$channel}->{$trigger}->{last_referenced_on}) { if ($self->{factoids}->exists($channel, $trigger, 'last_referenced_on')) {
print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->{hash}->{$channel}->{$trigger}->{last_referenced_on}) . "</td>\n"; print FILE "<td>" . encode_entities(strftime "%Y/%m/%d %H:%M:%S", localtime $self->{factoids}->get_data($channel, $trigger, 'last_referenced_on')) . "</td>\n";
} else { } else {
print FILE "<td></td>\n"; print FILE "<td></td>\n";
} }
@ -289,7 +273,7 @@ sub find_factoid {
my $string = $keyword . (length $arguments ? " $arguments" : ""); my $string = $keyword . (length $arguments ? " $arguments" : "");
$self->{pbot}->{logger}->log("string: $string\n") if $debug; $self->{pbot}->{logger}->log("string: $string\n") if $debug;
# check factoids # check factoids
foreach my $channel (sort keys %{ $self->{factoids}->{hash} }) { foreach my $channel (sort $self->{factoids}->get_keys) {
if ($opts{exact_channel}) { if ($opts{exact_channel}) {
if ($opts{exact_trigger} == 1) { if ($opts{exact_trigger} == 1) {
next unless $from eq lc $channel; next unless $from eq lc $channel;
@ -298,12 +282,11 @@ sub find_factoid {
} }
} }
foreach my $trigger (keys %{ $self->{factoids}->{hash}->{$channel} }) { foreach my $trigger ($self->{factoids}->get_keys($channel)) {
next if $trigger eq '_name';
if ($keyword eq $trigger) { if ($keyword eq $trigger) {
$self->{pbot}->{logger}->log("return $channel: $trigger\n") if $debug; $self->{pbot}->{logger}->log("return $channel: $trigger\n") if $debug;
if ($opts{find_alias} && $self->{factoids}->{hash}->{$channel}->{$trigger}->{action} =~ /^\/call\s+(.*)$/ms) { if ($opts{find_alias} && $self->{factoids}->get_data($channel, $trigger, 'action') =~ /^\/call\s+(.*)$/ms) {
my $command; my $command;
if (length $arguments) { if (length $arguments) {
$command = "$1 $arguments"; $command = "$1 $arguments";
@ -326,20 +309,20 @@ sub find_factoid {
# then check regex factoids # then check regex factoids
if (not $opts{exact_trigger}) { if (not $opts{exact_trigger}) {
foreach my $channel (sort keys %{ $self->{factoids}->{hash} }) { foreach my $channel ($self->{factoids}->get_keys) {
if ($opts{exact_channel}) { if ($opts{exact_channel}) {
next unless $from eq lc $channel or $channel eq '.*'; next unless $from eq lc $channel or $channel eq '.*';
} }
foreach my $trigger (sort keys %{ $self->{factoids}->{hash}->{$channel} }) { foreach my $trigger (sort $self->{factoids}->get_keys($channel)) {
next if $trigger eq '_name'; next if $trigger eq '_name';
if ($self->{factoids}->{hash}->{$channel}->{$trigger}->{type} eq 'regex') { if ($self->{factoids}->get_data($channel, $trigger, 'type') eq 'regex') {
$self->{pbot}->{logger}->log("checking regex $string =~ m/$trigger/i\n") if $debug >= 2; $self->{pbot}->{logger}->log("checking regex $string =~ m/$trigger/i\n") if $debug >= 2;
if ($string =~ m/$trigger/i) { if ($string =~ m/$trigger/i) {
$self->{pbot}->{logger}->log("return regex $channel: $trigger\n") if $debug; $self->{pbot}->{logger}->log("return regex $channel: $trigger\n") if $debug;
if ($opts{find_alias}) { if ($opts{find_alias}) {
my $command = $self->{factoids}->{hash}->{$channel}->{$trigger}->{action}; my $command = $self->{factoids}->get_data($channel, $trigger, 'action');
my $arglist = $self->{pbot}->{interpreter}->make_args($command); my $arglist = $self->{pbot}->{interpreter}->make_args($command);
($keyword, $arguments) = $self->{pbot}->{interpreter}->split_args($arglist, 2, 0, 1); ($keyword, $arguments) = $self->{pbot}->{interpreter}->split_args($arglist, 2, 0, 1);
$string = $keyword . (length $arguments ? " $arguments" : ""); $string = $keyword . (length $arguments ? " $arguments" : "");
@ -473,14 +456,14 @@ sub expand_factoid_vars {
my ($var_chan, $var) = ($factoids[0]->[0], $factoids[0]->[1]); my ($var_chan, $var) = ($factoids[0]->[0], $factoids[0]->[1]);
if ($self->{factoids}->{hash}->{$var_chan}->{$var}->{action} =~ m{^/call (.*)}ms) { if ($self->{factoids}->get_data($var_chan, $var, 'action') =~ m{^/call (.*)}ms) {
$test_v = $1; $test_v = $1;
next if ++$recurse > 100; next if ++$recurse > 100;
goto ALIAS; goto ALIAS;
} }
if ($self->{factoids}->{hash}->{$var_chan}->{$var}->{type} eq 'text') { if ($self->{factoids}->get_data($var_chan, $var, 'type') eq 'text') {
my $change = $self->{factoids}->{hash}->{$var_chan}->{$var}->{action}; my $change = $self->{factoids}->get_data($var_chan, $var, 'action');
my @list = $self->{pbot}->{interpreter}->split_line($change); my @list = $self->{pbot}->{interpreter}->split_line($change);
my @mylist; my @mylist;
for (my $i = 0; $i <= $#list; $i++) { for (my $i = 0; $i <= $#list; $i++) {
@ -693,7 +676,7 @@ sub expand_action_arguments {
sub execute_code_factoid_using_vm { sub execute_code_factoid_using_vm {
my ($self, $stuff) = @_; my ($self, $stuff) = @_;
unless (exists $self->{factoids}->{hash}->{lc $stuff->{channel}}->{lc $stuff->{keyword}}->{interpolate} and $self->{factoids}->{hash}->{lc $stuff->{channel}}->{lc $stuff->{keyword}}->{interpolate} eq '0') { unless ($self->{factoids}->exists($stuff->{channel}, $stuff->{keyword}, 'interpolate') and $self->{factoids}->get_data($stuff->{channel}, $stuff->{keyword}, 'interpolate') eq '0') {
if ($stuff->{code} =~ m/(?:\$\{?nick\b|\$\{?args\b|\$\{?arg\[)/ and length $stuff->{arguments}) { if ($stuff->{code} =~ m/(?:\$\{?nick\b|\$\{?args\b|\$\{?arg\[)/ and length $stuff->{arguments}) {
$stuff->{no_nickoverride} = 1; $stuff->{no_nickoverride} = 1;
} else { } else {
@ -703,7 +686,7 @@ sub execute_code_factoid_using_vm {
$stuff->{action} = $stuff->{code}; $stuff->{action} = $stuff->{code};
$stuff->{code} = $self->expand_factoid_vars($stuff); $stuff->{code} = $self->expand_factoid_vars($stuff);
if ($self->{factoids}->{hash}->{lc $stuff->{channel}}->{lc $stuff->{keyword}}->{'allow_empty_args'}) { if ($self->{factoids}->get_data($stuff->{channel}, $stuff->{keyword}, 'allow_empty_args')) {
$stuff->{code} = $self->expand_action_arguments($stuff->{code}, $stuff->{arguments}, ''); $stuff->{code} = $self->expand_action_arguments($stuff->{code}, $stuff->{arguments}, '');
} else { } else {
$stuff->{code} = $self->expand_action_arguments($stuff->{code}, $stuff->{arguments}, $stuff->{nick}); $stuff->{code} = $self->expand_action_arguments($stuff->{code}, $stuff->{arguments}, $stuff->{nick});
@ -714,8 +697,8 @@ sub execute_code_factoid_using_vm {
my %h = (nick => $stuff->{nick}, channel => $stuff->{from}, lang => $stuff->{lang}, code => $stuff->{code}, arguments => $stuff->{arguments}, factoid => "$stuff->{channel}:$stuff->{keyword}"); my %h = (nick => $stuff->{nick}, channel => $stuff->{from}, lang => $stuff->{lang}, code => $stuff->{code}, arguments => $stuff->{arguments}, factoid => "$stuff->{channel}:$stuff->{keyword}");
if (exists $self->{factoids}->{hash}->{lc $stuff->{channel}}->{lc $stuff->{keyword}}->{'persist-key'}) { if ($self->{factoids}->exists($stuff->{channel}, $stuff->{keyword}, 'persist-key')) {
$h{'persist-key'} = $self->{factoids}->{hash}->{lc $stuff->{channel}}->{lc $stuff->{keyword}}->{'persist-key'}; $h{'persist-key'} = $self->{factoids}->get_data($stuff->{channel}, $stuff->{keyword}, 'persist-key');
} }
my $json = encode_json \%h; my $json = encode_json \%h;
@ -780,12 +763,11 @@ sub interpreter {
my ($fwd_chan, $fwd_trig); my ($fwd_chan, $fwd_trig);
# build string of which channels contain the keyword, keeping track of the last one and count # build string of which channels contain the keyword, keeping track of the last one and count
foreach my $chan (keys %{ $self->{factoids}->{hash} }) { foreach my $chan ($self->{factoids}->get_keys) {
foreach my $trig (keys %{ $self->{factoids}->{hash}->{$chan} }) { foreach my $trig ($self->{factoids}->get_keys($chan)) {
next if $trig eq '_name'; my $type = $self->{factoids}->get_data($chan, $trig, 'type');
my $type = $self->{factoids}->{hash}->{$chan}->{$trig}->{type};
if (($type eq 'text' or $type eq 'module') and $trig eq $lc_keyword) { if (($type eq 'text' or $type eq 'module') and $trig eq $lc_keyword) {
$chans .= $comma . $self->{factoids}->{hash}->{$chan}->{_name}; $chans .= $comma . $self->{factoids}->get_data($chan, '_name');
$comma = ", "; $comma = ", ";
$found++; $found++;
$fwd_chan = $chan; $fwd_chan = $chan;
@ -843,8 +825,8 @@ sub interpreter {
} }
} }
my $channel_name = $self->{factoids}->{hash}->{$channel}->{_name}; my $channel_name = $self->{factoids}->get_data($channel, '_name');
my $trigger_name = $self->{factoids}->{hash}->{$channel}->{$keyword}->{_name}; my $trigger_name = $self->{factoids}->get_data($channel, $keyword, '_name');
$channel_name = 'global' if $channel_name eq '.*'; $channel_name = 'global' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /; $trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
@ -855,53 +837,55 @@ sub interpreter {
$stuff->{channel_name} = $channel_name; $stuff->{channel_name} = $channel_name;
$stuff->{trigger_name} = $trigger_name; $stuff->{trigger_name} = $trigger_name;
return undef if $stuff->{referenced} and $self->{factoids}->{hash}->{$channel}->{$keyword}->{noembed}; return undef if $stuff->{referenced} and $self->{factoids}->get_data($channel, $keyword, 'noembed');
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{locked_to_channel}) { if ($self->{factoids}->get_data($channel, $keyword, 'locked_to_channel')) {
if ($stuff->{ref_from} ne "") { # called from another channel if ($stuff->{ref_from} ne "") { # called from another channel
return "$trigger_name may be invoked only in $stuff->{ref_from}."; return "$trigger_name may be invoked only in $stuff->{ref_from}.";
} }
} }
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_on}) { if ($self->{factoids}->exists($channel, $keyword, 'last_referenced_on')) {
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_in}) { if ($self->{factoids}->exists($channel, $keyword, 'last_referenced_in')) {
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_in} eq $stuff->{from}) { if ($self->{factoids}->get_data($channel, $keyword, 'last_referenced_in') eq $stuff->{from}) {
my $ratelimit = $self->{pbot}->{registry}->get_value($stuff->{from}, 'ratelimit_override'); my $ratelimit = $self->{pbot}->{registry}->get_value($stuff->{from}, 'ratelimit_override');
$ratelimit = $self->{factoids}->{hash}->{$channel}->{$keyword}->{rate_limit} if not defined $ratelimit; $ratelimit = $self->{factoids}->get_data($channel, $keyword, 'rate_limit') if not defined $ratelimit;
if (gettimeofday - $self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_on} < $ratelimit) { if (gettimeofday - $self->{factoids}->get_data($channel, $keyword, 'last_referenced_on') < $ratelimit) {
my $ref_from = $stuff->{ref_from} ? "[$stuff->{ref_from}] " : ""; my $ref_from = $stuff->{ref_from} ? "[$stuff->{ref_from}] " : "";
return "/msg $stuff->{nick} $ref_from'$trigger_name' is rate-limited; try again in " . duration ($ratelimit - int(gettimeofday - $self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_on})) . "." unless $self->{pbot}->{users}->loggedin_admin($channel, "$stuff->{nick}!$stuff->{user}\@$stuff->{host}"); return "/msg $stuff->{nick} $ref_from'$trigger_name' is rate-limited; try again in " . duration ($ratelimit - int(gettimeofday - $self->{factoids}->get_data($channel, $keyword, 'last_referenced_on'))) . "." unless $self->{pbot}->{users}->loggedin_admin($channel, "$stuff->{nick}!$stuff->{user}\@$stuff->{host}");
} }
} }
} }
} }
$self->{factoids}->{hash}->{$channel}->{$keyword}->{ref_count}++; my $data = $self->{factoids}->get_data($channel, $keyword);
$self->{factoids}->{hash}->{$channel}->{$keyword}->{ref_user} = "$stuff->{nick}!$stuff->{user}\@$stuff->{host}"; $data->{ref_count}++;
$self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_on} = gettimeofday; $data->{ref_user} = "$stuff->{nick}!$stuff->{user}\@$stuff->{host}";
$self->{factoids}->{hash}->{$channel}->{$keyword}->{last_referenced_in} = $stuff->{from} || "stdin"; $data->{last_referenced_on} = gettimeofday;
$data->{last_referenced_in} = $stuff->{from} || "stdin";
$self->{factoids}->add($channel, $keyword, $data, 1, 1);
my $action; my $action;
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage} and not length $stuff->{arguments} and $self->{factoids}->{hash}->{$channel}->{$keyword}->{requires_arguments}) { if ($self->{factoids}->exists($channel, $keyword, 'usage') and not length $stuff->{arguments} and $self->{factoids}->get_data($channel, $keyword, 'requires_arguments')) {
$stuff->{alldone} = 1; $stuff->{alldone} = 1;
my $usage = $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage}; my $usage = $self->{factoids}->get_data($channel, $keyword, 'usage');
$usage =~ s/\$0|\$\{0\}/$trigger_name/g; $usage =~ s/\$0|\$\{0\}/$trigger_name/g;
return $usage; return $usage;
} }
if (length $stuff->{arguments} and exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{action_with_args}) { if (length $stuff->{arguments} and $self->{factoids}->exists($channel, $keyword, 'action_with_args')) {
$action = $self->{factoids}->{hash}->{$channel}->{$keyword}->{action_with_args}; $action = $self->{factoids}->get_data($channel, $keyword, 'action_with_args');
} else { } else {
$action = $self->{factoids}->{hash}->{$channel}->{$keyword}->{action}; $action = $self->{factoids}->get_data($channel, $keyword, 'action');
} }
if ($action =~ m{^/code\s+([^\s]+)\s+(.+)$}msi) { if ($action =~ m{^/code\s+([^\s]+)\s+(.+)$}msi) {
my ($lang, $code) = ($1, $2); my ($lang, $code) = ($1, $2);
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage} and not length $stuff->{arguments}) { if ($self->{factoids}->exists($channel, $keyword, 'usage') and not length $stuff->{arguments}) {
$stuff->{alldone} = 1; $stuff->{alldone} = 1;
my $usage = $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage}; my $usage = $self->{factoids}->get_data($channel, $keyword, 'usage');
$usage =~ s/\$0|\$\{0\}/$trigger_name/g; $usage =~ s/\$0|\$\{0\}/$trigger_name/g;
return $usage; return $usage;
} }
@ -931,14 +915,14 @@ sub handle_action {
my ($channel_name, $trigger_name) = ($stuff->{channel_name}, $stuff->{trigger_name}); my ($channel_name, $trigger_name) = ($stuff->{channel_name}, $stuff->{trigger_name});
my $ref_from = $stuff->{ref_from} ? "[$stuff->{ref_from}] " : ""; my $ref_from = $stuff->{ref_from} ? "[$stuff->{ref_from}] " : "";
unless (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} and $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} eq '0') { unless ($self->{factoids}->exists($channel, $keyword, 'interpolate') and $self->{factoids}->get_data($channel, $keyword, 'interpolate') eq '0') {
my ($root_channel, $root_keyword) = $self->find_factoid($stuff->{ref_from} ? $stuff->{ref_from} : $stuff->{from}, $stuff->{root_keyword}, arguments => $stuff->{arguments}, exact_channel => 1); my ($root_channel, $root_keyword) = $self->find_factoid($stuff->{ref_from} ? $stuff->{ref_from} : $stuff->{from}, $stuff->{root_keyword}, arguments => $stuff->{arguments}, exact_channel => 1);
if (not defined $root_channel or not defined $root_keyword) { if (not defined $root_channel or not defined $root_keyword) {
$root_channel = $channel; $root_channel = $channel;
$root_keyword = $keyword; $root_keyword = $keyword;
} }
if (not length $stuff->{keyword_override} and length $self->{factoids}->{hash}->{$root_channel}->{$root_keyword}->{keyword_override}) { if (not length $stuff->{keyword_override} and length $self->{factoids}->get_data($root_channel, $root_keyword, 'keyword_override')) {
$stuff->{keyword_override} = $self->{factoids}->{hash}->{$root_channel}->{$root_keyword}->{keyword_override}; $stuff->{keyword_override} = $self->{factoids}->get_data($root_channel, $root_keyword, 'keyword_override');
} }
$stuff->{action} = $action; $stuff->{action} = $action;
$action = $self->expand_factoid_vars($stuff); $action = $self->expand_factoid_vars($stuff);
@ -946,7 +930,7 @@ sub handle_action {
if (length $stuff->{arguments}) { if (length $stuff->{arguments}) {
if ($action =~ m/\$\{?args/ or $action =~ m/\$\{?arg\[/) { if ($action =~ m/\$\{?args/ or $action =~ m/\$\{?arg\[/) {
unless (defined $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} and $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} eq '0') { unless (defined $self->{factoids}->get_data($channel, $keyword, 'interpolate') and $self->{factoids}->get_data($channel, $keyword, 'interpolate') eq '0') {
$action = $self->expand_action_arguments($action, $stuff->{arguments}, $stuff->{nick}); $action = $self->expand_action_arguments($action, $stuff->{arguments}, $stuff->{nick});
$stuff->{no_nickoverride} = 1; $stuff->{no_nickoverride} = 1;
} else { } else {
@ -955,7 +939,7 @@ sub handle_action {
$stuff->{arguments} = ""; $stuff->{arguments} = "";
$stuff->{original_arguments} = ""; $stuff->{original_arguments} = "";
} else { } else {
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{type} eq 'text') { if ($self->{factoids}->get_data($channel, $keyword, 'type') eq 'text') {
my $target = $self->{pbot}->{nicklist}->is_present_similar($stuff->{from}, $stuff->{arguments}); my $target = $self->{pbot}->{nicklist}->is_present_similar($stuff->{from}, $stuff->{arguments});
if ($target and $action !~ /\$\{?(?:nick|args)\b/) { if ($target and $action !~ /\$\{?(?:nick|args)\b/) {
@ -968,12 +952,12 @@ sub handle_action {
} }
} else { } else {
# no arguments supplied, replace $args with $nick/$tonick, etc # no arguments supplied, replace $args with $nick/$tonick, etc
if (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage}) { if ($self->{factoids}->exists($channel, $keyword, 'usage')) {
$action = "/say " . $self->{factoids}->{hash}->{$channel}->{$keyword}->{usage}; $action = "/say " . $self->{factoids}->get_data($channel, $keyword, 'usage');
$action =~ s/\$0|\$\{0\}/$trigger_name/g; $action =~ s/\$0|\$\{0\}/$trigger_name/g;
$stuff->{alldone} = 1; $stuff->{alldone} = 1;
} else { } else {
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'allow_empty_args'}) { if ($self->{factoids}->get_data($channel, $keyword, 'allow_empty_args')) {
$action = $self->expand_action_arguments($action, undef, ''); $action = $self->expand_action_arguments($action, undef, '');
} else { } else {
$action = $self->expand_action_arguments($action, undef, $stuff->{nick}); $action = $self->expand_action_arguments($action, undef, $stuff->{nick});
@ -986,13 +970,13 @@ sub handle_action {
if ($action =~ /^\/call\s+(.*)$/msi) { if ($action =~ /^\/call\s+(.*)$/msi) {
my $command = $1; my $command = $1;
$command =~ s/\n$//; $command =~ s/\n$//;
unless ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'require_explicit_args'}) { unless ($self->{factoids}->get_data($channel, $keyword, 'require_explicit_args')) {
my $args = $stuff->{arguments}; my $args = $stuff->{arguments};
$command .= " $args" if length $args and not $stuff->{special} eq 'code-factoid'; $command .= " $args" if length $args and not $stuff->{special} eq 'code-factoid';
$stuff->{arguments} = ''; $stuff->{arguments} = '';
} }
unless ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'no_keyword_override'}) { unless ($self->{factoids}->get_data($channel, $keyword, 'no_keyword_override')) {
if ($command =~ s/\s*--keyword-override=([^ ]+)\s*//) { if ($command =~ s/\s*--keyword-override=([^ ]+)\s*//) {
$stuff->{keyword_override} = $1; $stuff->{keyword_override} = $1;
} }
@ -1003,12 +987,12 @@ sub handle_action {
$self->{pbot}->{logger}->log("[" . (defined $stuff->{from} ? $stuff->{from} : "stdin") . "] ($stuff->{nick}!$stuff->{user}\@$stuff->{host}) $trigger_name aliased to: $command\n"); $self->{pbot}->{logger}->log("[" . (defined $stuff->{from} ? $stuff->{from} : "stdin") . "] ($stuff->{nick}!$stuff->{user}\@$stuff->{host}) $trigger_name aliased to: $command\n");
if (defined $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'}) { if (defined $self->{factoids}->get_data($channel, $keyword, 'cap-override')) {
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'locked'}) { if ($self->{factoids}->get_data($channel, $keyword, 'locked')) {
$self->{pbot}->{logger}->log("Capability override set to $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'}\n"); $self->{pbot}->{logger}->log("Capability override set to " . $self->{factoids}->get_data($channel, $keyword, 'cap-override') . "\n");
$stuff->{'cap-override'} = $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'}; $stuff->{'cap-override'} = $self->{factoids}->get_data($channel, $keyword, 'cap-override');
} else { } else {
$self->{pbot}->{logger}->log("Ignoring cap-override of $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'} on unlocked factoid\n"); $self->{pbot}->{logger}->log("Ignoring cap-override of " . $self->{factoids}->get_data($channel, $keyword, 'cap-override') . " on unlocked factoid\n");
} }
} }
@ -1017,24 +1001,24 @@ sub handle_action {
$self->{pbot}->{logger}->log("(" . (defined $stuff->{from} ? $stuff->{from} : "(undef)") . "): $stuff->{nick}!$stuff->{user}\@$stuff->{host}: $trigger_name: action: \"$action\"\n"); $self->{pbot}->{logger}->log("(" . (defined $stuff->{from} ? $stuff->{from} : "(undef)") . "): $stuff->{nick}!$stuff->{user}\@$stuff->{host}: $trigger_name: action: \"$action\"\n");
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{enabled} == 0) { if ($self->{factoids}->get_data($channel, $keyword, 'enabled') == 0) {
$self->{pbot}->{logger}->log("$trigger_name disabled.\n"); $self->{pbot}->{logger}->log("$trigger_name disabled.\n");
return "/msg $stuff->{nick} ${ref_from}$trigger_name is currently disabled."; return "/msg $stuff->{nick} ${ref_from}$trigger_name is currently disabled.";
} }
unless (exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} and $self->{factoids}->{hash}->{$channel}->{$keyword}->{interpolate} eq '0') { unless ($self->{factoids}->exists($channel, $keyword, 'interpolate') and $self->{factoids}->get_data($channel, $keyword, 'interpolate') eq '0') {
my ($root_channel, $root_keyword) = $self->find_factoid($stuff->{ref_from} ? $stuff->{ref_from} : $stuff->{from}, $stuff->{root_keyword}, arguments => $stuff->{arguments}, exact_channel => 1); my ($root_channel, $root_keyword) = $self->find_factoid($stuff->{ref_from} ? $stuff->{ref_from} : $stuff->{from}, $stuff->{root_keyword}, arguments => $stuff->{arguments}, exact_channel => 1);
if (not defined $root_channel or not defined $root_keyword) { if (not defined $root_channel or not defined $root_keyword) {
$root_channel = $channel; $root_channel = $channel;
$root_keyword = $keyword; $root_keyword = $keyword;
} }
if (not length $stuff->{keyword_override} and length $self->{factoids}->{hash}->{$root_channel}->{$root_keyword}->{keyword_override}) { if (not length $stuff->{keyword_override} and length $self->{factoids}->get_data($root_channel, $root_keyword, 'keyword_override')) {
$stuff->{keyword_override} = $self->{factoids}->{hash}->{$root_channel}->{$root_keyword}->{keyword_override}; $stuff->{keyword_override} = $self->{factoids}->get_data($root_channel, $root_keyword, 'keyword_override');
} }
$stuff->{action} = $action; $stuff->{action} = $action;
$action = $self->expand_factoid_vars($stuff); $action = $self->expand_factoid_vars($stuff);
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'allow_empty_args'}) { if ($self->{factoids}->get_data($channel, $keyword, 'allow_empty_args')) {
$action = $self->expand_action_arguments($action, $stuff->{arguments}, ''); $action = $self->expand_action_arguments($action, $stuff->{arguments}, '');
} else { } else {
$action = $self->expand_action_arguments($action, $stuff->{arguments}, $stuff->{nick}); $action = $self->expand_action_arguments($action, $stuff->{arguments}, $stuff->{nick});
@ -1043,8 +1027,8 @@ sub handle_action {
return $action if $stuff->{special} eq 'code-factoid'; return $action if $stuff->{special} eq 'code-factoid';
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{type} eq 'module') { if ($self->{factoids}->get_data($channel, $keyword, 'type') eq 'module') {
my $preserve_whitespace = $self->{factoids}->{hash}->{$channel}->{$keyword}->{preserve_whitespace}; my $preserve_whitespace = $self->{factoids}->get_data($channel, $keyword, 'preserve_whitespace');
$preserve_whitespace = 0 if not defined $preserve_whitespace; $preserve_whitespace = 0 if not defined $preserve_whitespace;
$stuff->{preserve_whitespace} = $preserve_whitespace; $stuff->{preserve_whitespace} = $preserve_whitespace;
@ -1058,7 +1042,7 @@ sub handle_action {
return ""; return "";
} }
} }
elsif ($self->{factoids}->{hash}->{$channel}->{$keyword}->{type} eq 'text') { elsif ($self->{factoids}->get_data($channel, $keyword, 'type') eq 'text') {
# Don't allow user-custom /msg factoids, unless factoid triggered by admin # Don't allow user-custom /msg factoids, unless factoid triggered by admin
if ($action =~ m/^\/msg/i) { if ($action =~ m/^\/msg/i) {
my $admin = $self->{pbot}->{users}->loggedin_admin($stuff->{from}, "$stuff->{nick}!$stuff->{user}\@$stuff->{host}"); my $admin = $self->{pbot}->{users}->loggedin_admin($stuff->{from}, "$stuff->{nick}!$stuff->{user}\@$stuff->{host}");
@ -1082,7 +1066,7 @@ sub handle_action {
return "/say $trigger_name is $action"; return "/say $trigger_name is $action";
} }
} }
} elsif ($self->{factoids}->{hash}->{$channel}->{$keyword}->{type} eq 'regex') { } elsif ($self->{factoids}->get_data($channel, $keyword, 'type') eq 'regex') {
my $result = eval { my $result = eval {
my $string = "$stuff->{original_keyword}" . (defined $stuff->{arguments} ? " $stuff->{arguments}" : ""); my $string = "$stuff->{original_keyword}" . (defined $stuff->{arguments} ? " $stuff->{arguments}" : "");
my $cmd; my $cmd;

View File

@ -189,11 +189,6 @@ sub get_data {
sub add { sub add {
my ($self, $index, $data, $dont_save) = @_; my ($self, $index, $data, $dont_save) = @_;
my $lc_index = lc $index; my $lc_index = lc $index;
if (exists $self->{hash}->{$lc_index}) {
return "Error: $self->{hash}->{$lc_index}->{_name} already exists in $self->{name}.";
}
$data->{_name} = $index; # preserve case of index $data->{_name} = $index; # preserve case of index
$self->{hash}->{$lc_index} = $data; $self->{hash}->{$lc_index} = $data;
$self->save unless $dont_save; $self->save unless $dont_save;

View File

@ -280,8 +280,16 @@ sub on_mode {
if ($mode eq "+b") { if ($mode eq "+b") {
if ($nick eq "ChanServ" or $target =~ m/##fix_your_connection$/i) { if ($nick eq "ChanServ" or $target =~ m/##fix_your_connection$/i) {
if ($self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($self->{pbot}->{chanops}->can_gain_ops($channel)) {
$self->{pbot}->{chanops}->{unban_timeout}->{hash}->{lc $channel}->{lc $target}->{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout'); if ($self->{pbot}->{chanops}->{unban_timeout}->exists($channel, $target)) {
$self->{pbot}->{chanops}->{unban_timeout}->save; $self->{pbot}->{chanops}->{unban_timeout}->set($channel, $target, 'timeout', gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout'));
} else {
my $data = {
reason => 'Temp ban for banned-by-ChanServ or mask is *!*@*##fix_your_connection',
owner => $self->{pbot}->{registry}->get_value('irc', 'botnick'),
timeout => gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout'),
};
$self->{pbot}->{chanops}->{unban_timeout}->add($channel, $target, $data);
}
} }
} elsif ($target =~ m/^\*!\*@/ or $target =~ m/^\*!.*\@gateway\/web/i) { } elsif ($target =~ m/^\*!\*@/ or $target =~ m/^\*!.*\@gateway\/web/i) {
my $timeout = 60 * 60 * 24 * 7; my $timeout = 60 * 60 * 24 * 7;
@ -291,10 +299,14 @@ sub on_mode {
} }
if ($timeout && $self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($timeout && $self->{pbot}->{chanops}->can_gain_ops($channel)) {
if (not exists $self->{pbot}->{chanops}->{unban_timeout}->{hash}->{lc $channel}->{lc $target}) { if (not $self->{pbot}->{chanops}->{unban_timeout}->exists($channel, $target)) {
$self->{pbot}->{logger}->log("Temp ban for $target in $channel.\n"); $self->{pbot}->{logger}->log("Temp ban for $target in $channel.\n");
$self->{pbot}->{chanops}->{unban_timeout}->{hash}->{lc $channel}->{lc $target}->{timeout} = gettimeofday + $timeout; my $data = {
$self->{pbot}->{chanops}->{unban_timeout}->save; reason => 'Temp ban for *!*@... banmask',
timeout => gettimeofday + $timeout,
owner => $self->{pbot}->{registry}->get_value('irc', 'botnick'),
};
$self->{pbot}->{chanops}->{unban_timeout}->add($channel, $target, $data);
} }
} }
} }
@ -302,8 +314,16 @@ sub on_mode {
elsif ($mode eq "+q") { elsif ($mode eq "+q") {
if ($nick ne $event->{conn}->nick) { # bot muted if ($nick ne $event->{conn}->nick) { # bot muted
if ($self->{pbot}->{chanops}->can_gain_ops($channel)) { if ($self->{pbot}->{chanops}->can_gain_ops($channel)) {
$self->{pbot}->{chanops}->{unmute_timeout}->{hash}->{lc $channel}->{lc $target}->{timeout} = gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'mute_timeout'); if ($self->{pbot}->{chanops}->{unmute_timeout}->exists($channel, $target)) {
$self->{pbot}->{chanops}->{unmute_timeout}->save; $self->{pbot}->{chanops}->{unmute_timeout}->set($channel, $target, 'timeout', gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'chanserv_ban_timeout'));
} else {
my $data = {
reason => 'Temp mute',
owner => $self->{pbot}->{registry}->get_value('irc', 'botnick'),
timeout => gettimeofday + $self->{pbot}->{registry}->get_value('bantracker', 'mute_timeout'),
};
$self->{pbot}->{chanops}->{unmute_timeout}->add($channel, $target, $data);
}
} }
} }
} }

View File

@ -834,11 +834,11 @@ sub handle_result {
my ($chan, $trigger) = $self->{pbot}->{factoids}->find_factoid($stuff->{from}, $cmd, arguments => $args, exact_channel => 1, exact_trigger => 0, find_alias => 1); my ($chan, $trigger) = $self->{pbot}->{factoids}->find_factoid($stuff->{from}, $cmd, arguments => $args, exact_channel => 1, exact_trigger => 0, find_alias => 1);
if (defined $trigger) { if (defined $trigger) {
if ($stuff->{preserve_whitespace} == 0) { if ($stuff->{preserve_whitespace} == 0) {
$stuff->{preserve_whitespace} = $self->{pbot}->{factoids}->{factoids}->{hash}->{$chan}->{$trigger}->{preserve_whitespace}; $stuff->{preserve_whitespace} = $self->{pbot}->{factoids}->{factoids}->get_data($chan, $trigger, 'preserve_whitespace');
$stuff->{preserve_whitespace} = 0 if not defined $stuff->{preserve_whitespace}; $stuff->{preserve_whitespace} = 0 if not defined $stuff->{preserve_whitespace};
} }
$use_output_queue = $self->{pbot}->{factoids}->{factoids}->{hash}->{$chan}->{$trigger}->{use_output_queue}; $use_output_queue = $self->{pbot}->{factoids}->{factoids}->get_data($chan, $trigger, 'use_output_queue');
$use_output_queue = 0 if not defined $use_output_queue; $use_output_queue = 0 if not defined $use_output_queue;
} }
} }

View File

@ -336,11 +336,11 @@ sub listcmd {
if ($arguments =~ /^modules$/i) { if ($arguments =~ /^modules$/i) {
$text = "Loaded modules: "; $text = "Loaded modules: ";
foreach my $channel (sort keys %{ $self->{factoids}->{factoids}->{hash} }) { foreach my $channel (sort $self->{factoids}->{factoids}->get_keys) {
foreach my $command (sort keys %{ $self->{factoids}->{factoids}->{hash}->{$channel} }) { foreach my $command (sort $self->{factoids}->{factoids}->get_keys($channel)) {
next if $command eq '_name'; next if $command eq '_name';
if ($self->{factoids}->{factoids}->{hash}->{$channel}->{$command}->{type} eq 'module') { if ($self->{factoids}->{factoids}->get_data($channel, $command, 'type') eq 'module') {
$text .= "$self->{factoids}->{factoids}->{hash}->{$channel}->{$command}->{_name} "; $text .= $self->{factoids}->{factoids}->get_data($channel, $command, '_name') . ' ';
} }
} }
} }

View File

@ -29,10 +29,9 @@ sub initialize {
sub load { sub load {
my $self = shift; my $self = shift;
$self->{registry}->load; $self->{registry}->load;
foreach my $section (keys %{ $self->{registry}->{hash} }) { foreach my $section ($self->{registry}->get_keys) {
foreach my $item (keys %{ $self->{registry}->{hash}->{$section} }) { foreach my $item ($self->{registry}->get_keys($section)) {
next if $item eq '_name'; $self->process_trigger($section, $item, $self->{registry}->get_data($section, $item, 'value'));
$self->process_trigger($section, $item, $self->{registry}->{hash}->{$section}->{$item}->{value});
} }
} }
} }
@ -50,27 +49,22 @@ sub add_default {
sub add { sub add {
my $self = shift; my $self = shift;
my ($type, $section, $item, $value, $is_default) = @_; my ($type, $section, $item, $value, $is_default) = @_;
my $lc_section = lc $section;
my $lc_item = lc $item;
$type = lc $type; $type = lc $type;
if ($is_default) { if ($is_default) {
return if exists $self->{registry}->{hash}->{$lc_section} and exists $self->{registry}->{hash}->{$lc_section}->{$lc_item}; return if $self->{registry}->exists($section, $item);
} }
if (not exists $self->{registry}->{hash}->{$lc_section}) { if (not $self->{registry}->exists($section, $item)) {
$self->{registry}->{hash}->{$lc_section}->{_name} = $section; 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');
} }
if (not exists $self->{registry}->{hash}->{$lc_section}->{$lc_item}) {
$self->{registry}->{hash}->{$lc_section}->{$lc_item}->{_name} = $item;
}
$self->{registry}->{hash}->{$lc_section}->{$lc_item}->{value} = $value;
$self->{registry}->{hash}->{$lc_section}->{$lc_item}->{type} = $type unless exists $self->{registry}->{hash}->{$lc_section}->{$lc_item}->{type};
$self->process_trigger($section, $item, $value) unless $is_default; $self->process_trigger($section, $item, $value) unless $is_default;
$self->save unless $is_default; $self->save unless $is_default;
} }
@ -78,16 +72,7 @@ sub add {
sub remove { sub remove {
my $self = shift; my $self = shift;
my ($section, $item) = @_; my ($section, $item) = @_;
$self->{registry}->remove($section, $item);
$section = lc $section;
$item = lc $item;
delete $self->{registry}->{hash}->{$section}->{$item};
if (not scalar keys %{ $self->{registry}->{hash}->{$section} }) {
delete $self->{registry}->{hash}->{$section};
}
$self->save;
} }
sub set_default { sub set_default {
@ -97,15 +82,10 @@ sub set_default {
sub set { sub set {
my ($self, $section, $item, $key, $value, $is_default, $dont_save) = @_; my ($self, $section, $item, $key, $value, $is_default, $dont_save) = @_;
$section = lc $section;
$item = lc $item;
$key = lc $key if defined $key; $key = lc $key if defined $key;
if ($is_default) { if ($is_default) {
return if exists $self->{registry}->{hash}->{$section} return if $self->{registry}->exists($section, $item, $key);
and exists $self->{registry}->{hash}->{$section}->{$item}
and exists $self->{registry}->{hash}->{$section}->{$item}->{$key};
} }
my $oldvalue = $self->get_value($section, $item, 1) if defined $value; my $oldvalue = $self->get_value($section, $item, 1) if defined $value;
@ -123,14 +103,8 @@ sub set {
sub unset { sub unset {
my ($self, $section, $item, $key) = @_; my ($self, $section, $item, $key) = @_;
$section = lc $section;
$item = lc $item;
$key = lc $key; $key = lc $key;
return $self->{registry}->unset($section, $item, $key);
my $result = $self->{registry}->unset($section, $item, $key);
$self->save;
return $result;
} }
sub get_value { sub get_value {
@ -139,18 +113,19 @@ sub get_value {
$item = lc $item; $item = lc $item;
my $key = $item; my $key = $item;
# TODO: use user-metadata for this
if (defined $stuff and exists $stuff->{nick}) { if (defined $stuff and exists $stuff->{nick}) {
my $stuff_nick = lc $stuff->{nick}; my $stuff_nick = lc $stuff->{nick};
if (exists $self->{registry}->{hash}->{$section} and exists $self->{registry}->{hash}->{$section}->{"$item.nick.$stuff_nick"}) { if ($self->{registry}->exists($section, "$item.nick.$stuff_nick")) {
$key = "$item.nick.$stuff_nick"; $key = "$item.nick.$stuff_nick";
} }
} }
if (exists $self->{registry}->{hash}->{$section} and exists $self->{registry}->{hash}->{$section}->{$key}) { if ($self->{registry}->exists($section, $key)) {
if (not $as_text and $self->{registry}->{hash}->{$section}->{$key}->{type} eq 'array') { if (not $as_text and $self->{registry}->get_data($section, $key, 'type') eq 'array') {
return split /\s*,\s*/, $self->{registry}->{hash}->{$section}->{$key}->{value}; return split /\s*,\s*/, $self->{registry}->get_data($section, $key, 'value');
} else { } else {
return $self->{registry}->{hash}->{$section}->{$key}->{value}; return $self->{registry}->get_data($section, $key, 'value');
} }
} }
return undef; return undef;
@ -162,19 +137,20 @@ sub get_array_value {
$item = lc $item; $item = lc $item;
my $key = $item; my $key = $item;
# TODO: use user-metadata for this
if (defined $stuff and exists $stuff->{nick}) { if (defined $stuff and exists $stuff->{nick}) {
my $stuff_nick = lc $stuff->{nick}; my $stuff_nick = lc $stuff->{nick};
if (exists $self->{registry}->{hash}->{$section} and exists $self->{registry}->{hash}->{$section}->{"$item.nick.$stuff_nick"}) { if ($self->{registry}->exists($section, "$item.nick.$stuff_nick")) {
$key = "$item.nick.$stuff_nick"; $key = "$item.nick.$stuff_nick";
} }
} }
if (exists $self->{registry}->{hash}->{$section} and exists $self->{registry}->{hash}->{$section}->{$key}) { if ($self->{registry}->exists($section, $key)) {
if ($self->{registry}->{hash}->{$section}->{$key}->{type} eq 'array') { if ($self->{registry}->get_data($section, $key, 'type') eq 'array') {
my @array = split /\s*,\s*/, $self->{registry}->{hash}->{$section}->{$key}->{value}; my @array = split /\s*,\s*/, $self->{registry}->get_data($section, $key, 'value');
return $array[$index >= $#array ? $#array : $index]; return $array[$index >= $#array ? $#array : $index];
} else { } else {
return $self->{registry}->{hash}->{$section}->{$key}->{value}; return $self->{registry}->get_data($section, $key, 'value');
} }
} }
return undef; return undef;
@ -190,7 +166,6 @@ sub process_trigger {
my ($section, $item) = @_; my ($section, $item) = @_;
$section = lc $section; $section = lc $section;
$item = lc $item; $item = lc $item;
if (exists $self->{triggers}->{$section} and exists $self->{triggers}->{$section}->{$item}) { if (exists $self->{triggers}->{$section} and exists $self->{triggers}->{$section}->{$item}) {
return &{ $self->{triggers}->{$section}->{$item} }(@_); return &{ $self->{triggers}->{$section}->{$item} }(@_);
} }

View File

@ -71,14 +71,11 @@ sub regunset {
return $usage; return $usage;
} }
$section = lc $section; if (not $self->{pbot}->{registry}->{registry}->exits($section)) {
$item = lc $item;
if (not exists $self->{pbot}->{registry}->{registry}->{hash}->{$section}) {
return "No such registry section $section."; return "No such registry section $section.";
} }
if (not exists $self->{pbot}->{registry}->{registry}->{hash}->{$section}->{$item}) { if (not $self->{pbot}->{registry}->{registry}->exists($section, $item)) {
return "No such item $item in section $section."; return "No such item $item in section $section.";
} }
@ -135,7 +132,7 @@ sub regunsetmeta {
sub regshow { sub regshow {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_; my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $registry = $self->{pbot}->{registry}->{registry}->{hash}; my $registry = $self->{pbot}->{registry}->{registry};
my $usage = "Usage: regshow <section>.<item>"; my $usage = "Usage: regshow <section>.<item>";
# support "<section>.<key>" syntax in addition to "<section> <key>" # support "<section>.<key>" syntax in addition to "<section> <key>"
@ -151,24 +148,21 @@ sub regshow {
return $usage; return $usage;
} }
$section = lc $section; if (not $registry->exists($section)) {
$item = lc $item;
if (not exists $registry->{$section}) {
return "No such registry section $section."; return "No such registry section $section.";
} }
if (not exists $registry->{$section}->{$item}) { if (not $registry->exists($section, $item)) {
return "No such registry item $item in section $section."; return "No such registry item $item in section $section.";
} }
if ($registry->{$section}->{$item}->{private}) { if ($registry->get_data($section, $item, 'private')) {
return "$section.$item: <private>"; return "$section.$item: <private>";
} }
my $result = "$section.$item: $registry->{$section}->{$item}->{value}"; my $result = "$section.$item: " . $registry->get_data($section, $item, 'value');
if ($registry->{$section}->{$item}->{type} eq 'array') { if ($registry->get_data($section, $item, 'type') eq 'array') {
$result .= ' [array]'; $result .= ' [array]';
} }
return $result; return $result;
@ -177,7 +171,7 @@ sub regshow {
sub regfind { sub regfind {
my $self = shift; my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_; my ($from, $nick, $user, $host, $arguments) = @_;
my $registry = $self->{pbot}->{registry}->{registry}->{hash}; my $registry = $self->{pbot}->{registry}->{registry};
my $usage = "Usage: regfind [-showvalues] [-section section] <regex>"; my $usage = "Usage: regfind [-showvalues] [-section section] <regex>";
return $usage if not defined $arguments; return $usage if not defined $arguments;
@ -199,15 +193,15 @@ sub regfind {
$i = 0; $i = 0;
eval { eval {
use re::engine::RE2 -strict => 1; use re::engine::RE2 -strict => 1;
foreach my $section_key (sort keys %{ $registry }) { foreach my $section_key (sort $registry->get_keys) {
next if defined $section and $section_key ne $section; next if defined $section and $section_key ne $section;
foreach my $item_key (sort keys %{ $registry->{$section_key} }) { foreach my $item_key (sort $registry->get_keys($section_key)) {
next if $item_key eq '_name'; next if $item_key eq '_name';
if ($registry->{$section_key}->{$item_key}->{private}) { if ($registry->get_data($section_key, $item_key, 'private')) {
# do not match on value if private # do not match on value if private
next if $item_key !~ /$arguments/i; next if $item_key !~ /$arguments/i;
} else { } else {
next if $registry->{$section_key}->{$item_key}->{value} !~ /$arguments/i and $item_key !~ /$arguments/i; next if $registry->get_data($section_key, $item_key, 'value') !~ /$arguments/i and $item_key !~ /$arguments/i;
} }
$i++; $i++;
@ -217,10 +211,10 @@ sub regfind {
$last_section = $section_key; $last_section = $section_key;
} }
if ($showvalues) { if ($showvalues) {
if ($registry->{$section_key}->{$item_key}->{private}) { if ($registry->get_data($section_key, $item_key, 'private')) {
$text .= " $item_key = <private>\n"; $text .= " $item_key = <private>\n";
} else { } else {
$text .= " $item_key = $registry->{$section_key}->{$item_key}->{value}" . ($registry->{$section_key}->{$item_key}->{type} eq 'array' ? " [array]\n" : "\n"); $text .= " $item_key = " . $registry->get_data($section_key, $item_key, 'value') . ($registry->get_data($section_key, $item_key, 'type') eq 'array' ? " [array]\n" : "\n");
} }
} else { } else {
$text .= " $item_key\n"; $text .= " $item_key\n";
@ -234,10 +228,10 @@ sub regfind {
if ($i == 1) { if ($i == 1) {
chop $text; chop $text;
if ($registry->{$last_section}->{$last_item}->{private}) { if ($registry->get_data($last_section, $last_item, 'private')) {
return "Found one registry entry: [$last_section] $last_item: <private>"; return "Found one registry entry: [$last_section] $last_item: <private>";
} else { } 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]' : ''); return "Found one registry entry: [$last_section] $last_item: " . $registry->get_data($last_section, $last_item, 'value') . ($registry->get_data($last_section, $last_item, 'type') eq 'array' ? ' [array]' : '');
} }
} else { } else {
return "Found $i registry entries:\n$text" unless $i == 0; return "Found $i registry entries:\n$text" unless $i == 0;
@ -273,26 +267,26 @@ sub regchange {
$section = lc $section; $section = lc $section;
$item = lc $item; $item = lc $item;
my $registry = $self->{pbot}->{registry}->{registry}->{hash}; my $registry = $self->{pbot}->{registry}->{registry};
if (not exists $registry->{$section}) { if (not $registry->exists($section)) {
return "No such registry section $section."; return "No such registry section $section.";
} }
if (not exists $registry->{$section}->{$item}) { if (not $registry->exists($section, $item)) {
return "No such registry item $item in section $section."; return "No such registry item $item in section $section.";
} }
my $ret = eval { my $ret = eval {
use re::engine::RE2 -strict => 1; use re::engine::RE2 -strict => 1;
if (not $registry->{$section}->{$item}->{value} =~ s|$tochange|$changeto|) { if (not $registry->get_data($section, $item, 'value') =~ s|$tochange|$changeto|) {
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: failed to change $section.$item 's$delim$tochange$delim$changeto$delim$modifier\n"); $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."; return "/msg $nick Change $section.$item failed.";
} else { } else {
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed $section.$item 's/$tochange/$changeto/\n"); $self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed $section.$item 's/$tochange/$changeto/\n");
$self->{pbot}->{registry}->process_trigger($section, $item, 'value', $registry->{$section}->{$item}->{value}); $self->{pbot}->{registry}->process_trigger($section, $item, 'value', $registry->get_data($section, $item, 'value'));
$self->{pbot}->{registry}->save; $self->{pbot}->{registry}->save;
return "$section.$item set to $registry->{$section}->{$item}->{value}"; return "$section.$item set to " . $registry->get_data($section, $item, 'value');
} }
}; };
return "/msg $nick Failed to change $section.$item: $@" if $@; return "/msg $nick Failed to change $section.$item: $@" if $@;

View File

@ -104,7 +104,6 @@ sub remove_user {
sub load { sub load {
my $self = shift; my $self = shift;
my $filename; my $filename;
if (@_) { $filename = shift; } else { $filename = $self->{users}->{filename}; } if (@_) { $filename = shift; } else { $filename = $self->{users}->{filename}; }
if (not defined $filename) { if (not defined $filename) {
@ -115,19 +114,16 @@ sub load {
$self->{users}->load; $self->{users}->load;
my $i = 0; my $i = 0;
foreach my $channel (sort keys %{ $self->{users}->{hash} } ) { foreach my $channel (sort $self->{users}->get_keys) {
foreach my $hostmask (sort keys %{ $self->{users}->{hash}->{$channel} }) { foreach my $hostmask (sort $self->{users}->get_keys($channel)) {
next if $hostmask eq '_name';
$i++; $i++;
my $name = $self->{users}->{hash}->{$channel}->{$hostmask}->{name}; my $name = $self->{users}->get_data($channel, $hostmask, 'name');
my $password = $self->{users}->{hash}->{$channel}->{$hostmask}->{password}; my $password = $self->{users}->get_data($channel, $hostmask, 'password');
if (not defined $name or not defined $password) { if (not defined $name or not defined $password) {
Carp::croak "A user in $filename is missing critical data\n"; Carp::croak "A user in $filename is missing critical data\n";
} }
} }
} }
$self->{pbot}->{logger}->log(" $i users loaded.\n"); $self->{pbot}->{logger}->log(" $i users loaded.\n");
} }
@ -149,13 +145,12 @@ sub find_user_account {
$sort = sub { $b cmp $a }; $sort = sub { $b cmp $a };
} }
foreach my $chan (sort $sort keys %{ $self->{users}->{hash} }) { foreach my $chan (sort $sort $self->{users}->get_keys) {
if (($channel !~ m/^#/ and $any_channel) or $channel =~ m/^$chan$/i) { if (($channel !~ m/^#/ and $any_channel) or $channel =~ m/^$chan$/i) {
if (not exists $self->{users}->{hash}->{$chan}->{$hostmask}) { if (not $self->{users}->exists($chan, $hostmask)) {
# find hostmask by account name or wildcard # find hostmask by account name or wildcard
foreach my $mask (keys %{ $self->{users}->{hash}->{$chan} }) { foreach my $mask ($self->{users}->get_keys($chan)) {
next if $mask eq '_name'; if (lc $self->{users}->get_data($chan, $mask, 'name') eq $hostmask) {
if (lc $self->{users}->{hash}->{$chan}->{$mask}->{name} eq $hostmask) {
return ($chan, $mask); return ($chan, $mask);
} }
@ -195,22 +190,21 @@ sub find_user {
} }
my $user = eval { my $user = eval {
foreach my $channel_regex (sort $sort keys %{ $self->{users}->{hash} }) { foreach my $channel_regex (sort $sort $self->{users}->get_keys) {
if (($channel !~ m/^#/ and $any_channel) or $channel =~ m/^$channel_regex$/i) { if (($channel !~ m/^#/ and $any_channel) or $channel =~ m/^$channel_regex$/i) {
foreach my $hostmask_regex (keys %{ $self->{users}->{hash}->{$channel_regex} }) { foreach my $hostmask_regex ($self->{users}->get_keys($channel_regex)) {
next if $hostmask_regex eq '_name';
if ($hostmask_regex =~ m/[*?]/) { if ($hostmask_regex =~ m/[*?]/) {
# contains * or ? so it's converted to a regex # contains * or ? so it's converted to a regex
my $hostmask_quoted = quotemeta $hostmask_regex; my $hostmask_quoted = quotemeta $hostmask_regex;
$hostmask_quoted =~ s/\\\*/.*?/g; $hostmask_quoted =~ s/\\\*/.*?/g;
$hostmask_quoted =~ s/\\\?/./g; $hostmask_quoted =~ s/\\\?/./g;
if ($hostmask =~ m/^$hostmask_quoted$/i) { if ($hostmask =~ m/^$hostmask_quoted$/i) {
return $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex}; return $self->{users}->get_data($channel_regex, $hostmask_regex);
} }
} else { } else {
# direct comparison # direct comparison
if ($hostmask eq lc $hostmask_regex) { if ($hostmask eq lc $hostmask_regex) {
return $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex}; return $self->{users}->get_data($channel_regex, $hostmask_regex);
} }
} }
} }
@ -300,7 +294,7 @@ sub logincmd {
my ($user_channel, $user_hostmask) = $self->find_user_account($channel, "$nick!$user\@$host"); my ($user_channel, $user_hostmask) = $self->find_user_account($channel, "$nick!$user\@$host");
return "/msg $nick You do not have a user account." if not defined $user_channel; return "/msg $nick You do not have a user account." if not defined $user_channel;
my $u = $self->{users}->{hash}->{$user_channel}->{$user_hostmask}; my $u = $self->{users}->get_data($user_channel, $user_hostmask);
my $channel_text = $user_channel eq '.*' ? '' : " for $user_channel"; my $channel_text = $user_channel eq '.*' ? '' : " for $user_channel";
if ($u->{loggedin}) { if ($u->{loggedin}) {
@ -317,7 +311,7 @@ sub logoutcmd {
my ($user_channel, $user_hostmask) = $self->find_user_account($from, "$nick!$user\@$host"); my ($user_channel, $user_hostmask) = $self->find_user_account($from, "$nick!$user\@$host");
return "/msg $nick You do not have a user account." if not defined $user_channel; return "/msg $nick You do not have a user account." if not defined $user_channel;
my $u = $self->{users}->{hash}->{$user_channel}->{$user_hostmask}; my $u = $self->{users}->get_data($user_channel, $user_hostmask);
my $channel_text = $user_channel eq '.*' ? '' : " for $user_channel"; my $channel_text = $user_channel eq '.*' ? '' : " for $user_channel";
return "/msg $nick You are not logged into $u->{name} ($user_hostmask)$channel_text." if not $u->{loggedin}; return "/msg $nick You are not logged into $u->{name} ($user_hostmask)$channel_text." if not $u->{loggedin};
@ -340,7 +334,7 @@ sub users {
my $text = "Users: "; my $text = "Users: ";
my $last_channel = ""; my $last_channel = "";
my $sep = ""; my $sep = "";
foreach my $chan (sort keys %{ $self->{users}->{hash} }) { foreach my $chan (sort $self->{users}->get_keys) {
next if $from =~ m/^#/ and $chan ne $channel and $chan ne $include_global; next if $from =~ m/^#/ and $chan ne $channel and $chan ne $include_global;
next if $from !~ m/^#/ and $channel =~ m/^#/ and $chan ne $channel; next if $from !~ m/^#/ and $channel =~ m/^#/ and $chan ne $channel;
@ -350,19 +344,17 @@ sub users {
$sep = ""; $sep = "";
} }
foreach my $hostmask (sort { return 0 if $a eq '_name' or $b eq '_name'; $self->{users}->{hash}->{$chan}->{$a}->{name} cmp $self->{users}->{hash}->{$chan}->{$b}->{name} } keys %{ $self->{users}->{hash}->{$chan} }) { foreach my $hostmask (sort { return 0 if $a eq '_name' or $b eq '_name'; $self->{users}->get_data($chan, $a, 'name') cmp $self->{users}->get_data($chan, $b, 'name') } $self->{users}->get_keys($chan)) {
next if $hostmask eq '_name';
$text .= $sep; $text .= $sep;
my $has_cap = 0; my $has_cap = 0;
foreach my $key (keys %{$self->{users}->{hash}->{$chan}->{$hostmask}}) { foreach my $key ($self->{users}->get_keys($chan, $hostmask)) {
next if $key eq '_name';
if ($self->{pbot}->{capabilities}->exists($key)) { if ($self->{pbot}->{capabilities}->exists($key)) {
$has_cap = 1; $has_cap = 1;
last; last;
} }
} }
$text .= '+' if $has_cap; $text .= '+' if $has_cap;
$text .= $self->{users}->{hash}->{$chan}->{$hostmask}->{name}; $text .= $self->{users}->get_data($chan, $hostmask, 'name');
$sep = " "; $sep = " ";
} }
$sep = "; "; $sep = "; ";