Finished replacing admin-levels with user-capabilities [FIN commit 2 of 2]; misc clean-ups

This commit is contained in:
Pragmatic Software 2020-02-03 17:19:04 -08:00
parent 2ca9634c66
commit 6267cc04d2
48 changed files with 426 additions and 685 deletions

View File

@ -78,7 +78,7 @@ sub initialize {
$self->{pbot}->{registry}->add_default('text', 'antiflood', 'debug_checkban', $conf{debug_checkban} // 0);
$self->{pbot}->{commands}->register(sub { return $self->unbanme(@_) }, "unbanme", 0);
$self->{pbot}->{commands}->register(sub { return $self->whitelist(@_) }, "whitelist", 10);
$self->{pbot}->{commands}->register(sub { return $self->whitelist(@_) }, "whitelist", 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.whoisaccount', sub { $self->on_whoisaccount(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.whoisuser', sub { $self->on_whoisuser(@_) });

View File

@ -41,7 +41,7 @@ sub initialize {
$self->{keywords}->load;
$self->{pbot}->{registry}->add_default('text', 'antispam', 'enforce', $conf{enforce_antispam} // 1);
$self->{pbot}->{commands}->register(sub { return $self->antispam_cmd(@_) }, "antispam", 10);
$self->{pbot}->{commands}->register(sub { return $self->antispam_cmd(@_) }, "antispam", 1);
}
sub is_spam {

View File

@ -24,12 +24,8 @@ $Data::Dumper::Sortkeys = 1;
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to BanTracker should be key/value pairs, not hash reference");
}
Carp::croak("Options to BanTracker should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -38,14 +34,14 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to BanTracker");
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to BanTracker");
$self->{banlist} = {};
$self->{pbot}->{registry}->add_default('text', 'bantracker', 'chanserv_ban_timeout', '604800');
$self->{pbot}->{registry}->add_default('text', 'bantracker', 'mute_timeout', '604800');
$self->{pbot}->{registry}->add_default('text', 'bantracker', 'debug', '0');
$self->{pbot}->{commands}->register(sub { $self->dumpbans(@_) }, "dumpbans", 60);
$self->{pbot}->{commands}->register(sub { $self->dumpbans(@_) }, "dumpbans", 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.endofnames', sub { $self->get_banlist(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.banlist', sub { $self->on_banlist_entry(@_) });
@ -54,7 +50,6 @@ sub initialize {
sub dumpbans {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $bans = Dumper($self->{banlist});
return $bans;
}

View File

@ -33,7 +33,7 @@ sub initialize {
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{filename} = $conf{filename};
$self->{blacklist} = {};
$self->{pbot}->{commands}->register(sub { $self->blacklist(@_) }, "blacklist", 10);
$self->{pbot}->{commands}->register(sub { $self->blacklist(@_) }, "blacklist", 1);
$self->load_blacklist;
}

View File

@ -53,8 +53,9 @@ sub has {
my ($self, $cap, $subcap, $depth) = @_;
my $cap_data = $self->{caps}->get_data($cap);
return 0 if not defined $cap_data;
return 1 if $cap eq $subcap;
$depth //= 2;
$depth //= 10;
if (--$depth <= 0) {
$self->{pbot}->{logger}->log("Max recursion reached for PBot::Capabilities->has()\n");
return 0;
@ -74,7 +75,7 @@ sub userhas {
return 1 if $user->{$cap};
foreach my $key (keys %{$user}) {
next if $key eq '_name';
return 1 if $self->has($key, $cap, 10);
return 1 if $self->has($key, $cap);
}
return 0;
}
@ -109,6 +110,15 @@ sub add {
}
sub remove {
my ($self, $cap) = @_;
$cap = lc $cap;
foreach my $c (keys %{$self->{caps}->{hash}}) {
next if $c eq '_name';
foreach my $sub_cap (keys %{$self->{caps}->{hash}->{$c}}) {
delete $self->{caps}->{hash}->{$c}->{$sub_cap} if $sub_cap eq $cap;
}
delete $self->{caps}->{hash}->{$c} if $c eq $cap;
}
}
sub rebuild_botowner_capabilities {
@ -122,7 +132,7 @@ sub rebuild_botowner_capabilities {
sub list {
my ($self, $capability) = @_;
$capability = lc $capability;
$capability = lc $capability if defined $capability;
return "No such capability $capability." if defined $capability and not exists $self->{caps}->{hash}->{$capability};
my @caps;
@ -135,7 +145,7 @@ sub list {
$result = 'Capabilities: ';
} else {
@caps = sort keys %{$self->{caps}->{hash}->{$capability}};
return "Capability $capability has no sub-capabilities." if @caps == 1;
return "Capability $capability has no sub-capabilities." if not @caps or @caps == 1;
$result = "Sub-capabilities for $capability: ";
}
@ -144,7 +154,7 @@ sub list {
foreach my $cap (@caps) {
next if $cap eq '_name';
my $count = keys(%{$self->{caps}->{hash}->{$cap}}) - 1;
if ($count) {
if ($count > 0) {
push @cap_group, "$cap [$count]" if $count;
} else {
push @cap_standalone, $cap;
@ -166,6 +176,41 @@ sub capcmd {
}
when ('userhas') {
my ($hostmask, $cap) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 2);
return "Usage: cap userhas <user> [capability]" if not defined $hostmask;
$cap = lc $cap if defined $cap;
my $u = $self->{pbot}->{users}->find_user('.*', $hostmask);
return "No such user $hostmask." if not defined $u;
if (defined $cap) {
return "Try again. No such capability $cap." if not $self->exists($cap);
if ($self->userhas($u, $cap)) {
return "Yes. User $u->{name} has capability $cap.";
} else {
return "No. User $u->{name} does not have capability $cap.";
}
} else {
my $result = "User $u->{name} has capabilities: ";
my @groups;
my @single;
foreach my $key (sort keys %{$u}) {
next if $key eq '_name';
next if not $self->exists($key);
my $count = keys (%{$self->{caps}->{hash}->{$key}}) - 1;
if ($count > 0) {
push @groups, "$key [$count]";
} else {
push @single, $key;
}
}
if (@groups or @single) {
$result .= join ', ', @groups, @single;
} else {
$result = "User $u->{name} has no capabilities.";
}
return $result;
}
}
when ('add') {
@ -175,7 +220,7 @@ sub capcmd {
}
default {
$result = "Usage: cap list [capability] | cap add <capability> [sub-capability] | cap remove <capability> [sub-capability] | cap userhas <user> <capability>";
$result = "Usage: cap list [capability] | cap add <capability> [sub-capability] | cap remove <capability> [sub-capability] | cap userhas <user> [capability]";
}
}
return $result;

View File

@ -19,10 +19,7 @@ use Time::HiRes qw(gettimeofday);
use Time::Duration qw(concise duration);
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -31,7 +28,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to ChanOps");
$self->{unban_timeout} = PBot::DualIndexHashObject->new(

View File

@ -27,19 +27,18 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{channels} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Channels', filename => $conf{filename});
$self->load_channels;
$self->{pbot}->{commands}->register(sub { $self->join(@_) }, "join", 40);
$self->{pbot}->{commands}->register(sub { $self->part(@_) }, "part", 40);
$self->{pbot}->{commands}->register(sub { $self->set(@_) }, "chanset", 40);
$self->{pbot}->{commands}->register(sub { $self->unset(@_) }, "chanunset", 40);
$self->{pbot}->{commands}->register(sub { $self->add(@_) }, "chanadd", 40);
$self->{pbot}->{commands}->register(sub { $self->remove(@_) }, "chanrem", 40);
$self->{pbot}->{commands}->register(sub { $self->list(@_) }, "chanlist", 10);
$self->{pbot}->{commands}->register(sub { $self->join(@_) }, "join", 1);
$self->{pbot}->{commands}->register(sub { $self->part(@_) }, "part", 1);
$self->{pbot}->{commands}->register(sub { $self->set(@_) }, "chanset", 1);
$self->{pbot}->{commands}->register(sub { $self->unset(@_) }, "chanunset", 1);
$self->{pbot}->{commands}->register(sub { $self->add(@_) }, "chanadd", 1);
$self->{pbot}->{commands}->register(sub { $self->remove(@_) }, "chanrem", 1);
$self->{pbot}->{commands}->register(sub { $self->list(@_) }, "chanlist", 1);
}
sub join {

View File

@ -40,7 +40,6 @@ sub initialize {
sub load {
my ($self, $filename) = @_;
$filename = $self->{filename} if not defined $filename;
if (not defined $filename) {
@ -104,7 +103,6 @@ sub load {
sub save {
my $self = shift;
my $filename;
if (@_) { $filename = shift; } else { $filename = $self->{filename}; }
if (not defined $filename) {

View File

@ -25,26 +25,26 @@ use JSON;
use PBot::Utils::SafeFilename;
our %factoid_metadata_levels = (
created_on => 90,
enabled => 10,
last_referenced_in => 90,
last_referenced_on => 90,
modulelauncher_subpattern => 90,
owner => 90,
rate_limit => 10,
ref_count => 90,
ref_user => 90,
type => 90,
edited_by => 90,
edited_on => 90,
locked => 10,
add_nick => 10,
nooverride => 10,
'effective-level' => 40,
'persist-key' => 20,
'interpolate' => 10,
# all others are allowed to be factset by anybody/default to level 0
our %factoid_metadata_capabilities = (
created_on => 'botowner',
enabled => 'chanop',
last_referenced_in => 'botowner',
last_referenced_on => 'botowner',
modulelauncher_subpattern => 'botowner',
owner => 'botowner',
rate_limit => 'chanop',
ref_count => 'botowner',
ref_user => 'botowner',
type => 'botowner',
edited_by => 'botowner',
edited_on => 'botowner',
locked => 'chanop',
add_nick => 'chanop',
nooverride => 'chanop',
'cap-override' => 'botowner',
'persist-key' => 'admin',
'interpolate' => 'chanop',
# all others are allowed to be factset by anybody
);
sub new {
@ -78,14 +78,14 @@ sub initialize {
$self->{pbot}->{commands}->register(sub { return $self->call_factoid(@_) }, "fact", 0);
$self->{pbot}->{commands}->register(sub { return $self->factfind(@_) }, "factfind", 0);
$self->{pbot}->{commands}->register(sub { return $self->top20(@_) }, "top20", 0);
$self->{pbot}->{commands}->register(sub { return $self->load_module(@_) }, "load", 90);
$self->{pbot}->{commands}->register(sub { return $self->unload_module(@_) }, "unload", 90);
$self->{pbot}->{commands}->register(sub { return $self->load_module(@_) }, "load", 1);
$self->{pbot}->{commands}->register(sub { return $self->unload_module(@_) }, "unload", 1);
$self->{pbot}->{commands}->register(sub { return $self->histogram(@_) }, "histogram", 0);
$self->{pbot}->{commands}->register(sub { return $self->count(@_) }, "count", 0);
# the following commands have not yet been updated to use the new factoid structure
# DO NOT USE!! Factoid corruption may occur.
$self->{pbot}->{commands}->register(sub { return $self->add_regex(@_) }, "regex", 999);
$self->{pbot}->{commands}->register(sub { return $self->add_regex(@_) }, "regex", 1);
}
sub call_factoid {
@ -406,13 +406,12 @@ sub factundo {
}
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash};
my $admininfo = $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host");
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids->{$channel}->{$trigger}->{'locked'}) {
return "/say $trigger_name is locked and cannot be reverted." if not defined $admininfo;
return "/say $trigger_name is locked and cannot be reverted." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids->{$channel}->{$trigger}->{'effective-level'}
and $admininfo->{level} < $factoids->{$channel}->{$trigger}->{'effective-level'}) {
return "/say $trigger_name is locked with an effective-level higher than your level and cannot be reverted.";
if (exists $factoids->{$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.";
}
}
@ -499,13 +498,12 @@ sub factredo {
}
my $factoids = $self->{pbot}->{factoids}->{factoids}->{hash};
my $admininfo = $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host");
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids->{$channel}->{$trigger}->{'locked'}) {
return "/say $trigger_name is locked and cannot be reverted." if not defined $admininfo;
return "/say $trigger_name is locked and cannot be reverted." if not defined $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids->{$channel}->{$trigger}->{'effective-level'}
and $admininfo->{level} < $factoids->{$channel}->{$trigger}->{'effective-level'}) {
return "/say $trigger_name is locked with an effective-level higher than your level and cannot be reverted.";
if (exists $factoids->{$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.";
}
}
@ -559,50 +557,39 @@ sub factset {
$channel = '.*' if $channel !~ /^#/;
my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, exact_channel => 1, exact_trigger => 1);
my $admininfo;
my $userinfo;
if (defined $owner_channel) {
$admininfo = $self->{pbot}->{users}->loggedin_admin($owner_channel, "$nick!$user\@$host");
$userinfo = $self->{pbot}->{users}->loggedin($owner_channel, "$nick!$user\@$host");
} else {
$admininfo = $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host");
}
my $level = 0;
my $meta_level = 0;
if (defined $admininfo) {
$level = $admininfo->{level};
$userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
}
my $meta_cap;
if (defined $key) {
if (defined $factoid_metadata_levels{$key}) {
$meta_level = $factoid_metadata_levels{$key};
if (defined $factoid_metadata_capabilities{$key}) {
$meta_cap = $factoid_metadata_capabilities{$key};
}
if ($meta_level > 0) {
if ($level == 0) {
return "You must be an admin to set $key";
} elsif ($level < $meta_level) {
return "You must be at least level $meta_level to set $key";
if (defined $meta_cap) {
if (not $self->{pbot}->{capabilities}->userhas($userinfo, $meta_cap)) {
return "Your user account must have the $meta_cap capability to set $key.";
}
}
if (defined $value and !$level and $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'locked'}) {
if (defined $value and !$self->{pbot}->{capabilities}->userhas($userinfo, 'admin') and $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'locked'}) {
return "/say $trigger_name is locked; unlock before setting.";
}
if (lc $key eq 'effective-level' and defined $value and $level > 0) {
if ($value > $level) {
return "You cannot set `effective-level` greater than your level, which is $level.";
} elsif ($value < 0) {
return "You cannot set a negative effective-level.";
if (lc $key eq 'cap-override' and defined $value) {
if (not $self->{pbot}->{capabilities}->exists($value)) {
return "No such capability $value.";
}
$self->{pbot}->{factoids}->{factoids}->set($channel, $trigger, 'locked', '1');
}
if (lc $key eq 'locked' and exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'effective-level'}) {
if ($level < $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'effective-level'}) {
return "You cannot unlock this factoid because its effective-level is greater than your level.";
if (lc $key eq 'locked' and exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'cap-override'}) {
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.";
}
}
}
@ -622,7 +609,7 @@ sub factset {
$mask = $nick;
}
if ((defined $value and $key ne 'action' and $key ne 'action_with_args') and lc $mask ne lc $owner and $level == 0) {
if ((defined $value and $key ne 'action' and $key ne 'action_with_args') and lc $mask ne lc $owner and not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin')) {
return "You are not the owner of $trigger_name.";
}
}
@ -651,43 +638,30 @@ sub factunset {
my ($owner_channel, $owner_trigger) = $self->{pbot}->{factoids}->find_factoid($channel, $trigger, exact_channel => 1, exact_trigger => 1);
my $admininfo;
my $userinfo;
if (defined $owner_channel) {
$admininfo = $self->{pbot}->{users}->loggedin_admin($owner_channel, "$nick!$user\@$host");
$userinfo = $self->{pbot}->{users}->loggedin($owner_channel, "$nick!$user\@$host");
} else {
$admininfo = $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host");
$userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
}
my $level = 0;
my $meta_level = 0;
if (defined $admininfo) {
$level = $admininfo->{level};
my $meta_cap;
if (exists $factoid_metadata_capabilities{$key}) {
$meta_cap = $factoid_metadata_capabilities{$key};
}
if (defined $factoid_metadata_levels{$key}) {
$meta_level = $factoid_metadata_levels{$key};
}
if ($meta_level > 0) {
if ($level == 0) {
return "You must be an admin to unset $key";
} elsif ($level < $meta_level) {
return "You must be at least level $meta_level to unset $key";
if (defined $meta_cap) {
if (not $self->{pbot}->{capabilities}->userhas($userinfo, $meta_cap)) {
return "Your user account must have the $meta_cap capability to unset $key.";
}
}
if (exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'effective-level'}) {
if (exists $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'cap-override'}) {
if (lc $key eq 'locked') {
if ($level >= $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'effective-level'}) {
$self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, 'effective-level');
if ($self->{pbot}->{capabilities}->userhas($userinfo, 'botowner')) {
$self->{pbot}->{factoids}->{factoids}->unset($channel, $trigger, 'cap-override');
} else {
return "You cannot unlock this factoid because its effective-level is higher than your level.";
}
} elsif (lc $key eq 'effective-level') {
if ($level < $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{'effective-level'}) {
return "You cannot unset the effective-level because it is higher than your level.";
return "You cannot unlock this factoid because it has a cap-override. Remove the override first.";
}
}
}
@ -704,7 +678,7 @@ sub factunset {
my ($owner) = $factoid->{'owner'} =~ m/([^!]+)/;
if ($key ne 'action_with_args' and lc $nick ne lc $owner and $level == 0) {
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.";
}
$oldvalue = $self->{pbot}->{factoids}->{factoids}->{hash}->{$channel}->{$trigger}->{$key};
@ -717,7 +691,6 @@ sub factunset {
if ($result =~ m/unset/) {
$self->log_factoid($channel, $trigger, "$nick!$user\@$host", "unset $key (value: $oldvalue)");
}
return $result;
}
@ -1623,13 +1596,12 @@ sub factchange {
return "/say $trigger_name belongs to $channel_name, but this is $from_chan. Please switch to $channel_name or use /msg to change this factoid.";
}
my $admininfo = $self->{pbot}->{users}->loggedin_admin($channel, "$nick!$user\@$host");
my $userinfo = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
if ($factoids_hash->{$channel}->{$trigger}->{'locked'}) {
return "/say $trigger_name is locked and cannot be changed." if not defined $admininfo;
return "/say $trigger_name is locked and cannot be changed." if not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin');
if (exists $factoids_hash->{$channel}->{$trigger}->{'effective-level'}
and $admininfo->{level} < $factoids_hash->{$channel}->{$trigger}->{'effective-level'}) {
return "/say $trigger_name is locked with an effective-level higher than your level and cannot be changed.";
if (exists $factoids_hash->{$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.";
}
}
@ -1711,7 +1683,7 @@ sub factchange {
return $ret if length $ret;
}
if (length $action > 8000 and not defined $admininfo) {
if (length $action > 8000 and not $self->{pbot}->{capabilities}->userhas($userinfo, 'admin')) {
return "Change $trigger_name failed; result is too long.";
}

View File

@ -25,12 +25,8 @@ use Encode;
$SIG{CHLD} = sub { while (waitpid(-1, WNOHANG) > 0) {} };
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to Commands should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -38,13 +34,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
my $pbot = delete $conf{pbot};
if (not defined $pbot) {
Carp::croak("Missing pbot reference to PBot::FactoidModuleLauncher");
}
$self->{pbot} = $pbot;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
}
sub execute_module {

View File

@ -1009,12 +1009,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");
if (defined $self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'}) {
if (defined $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'}) {
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'locked'}) {
$self->{pbot}->{logger}->log("Effective-level set to $self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'}\n");
$stuff->{'effective-level'} = $self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'};
$self->{pbot}->{logger}->log("Capability override set to $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'}\n");
$stuff->{'cap-override'} = $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'};
} else {
$self->{pbot}->{logger}->log("Ignoring effective-level of $self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'} on unlocked factoid\n");
$self->{pbot}->{logger}->log("Ignoring cap-override of $self->{factoids}->{hash}->{$channel}->{$keyword}->{'cap-override'} on unlocked factoid\n");
}
}
@ -1068,9 +1068,9 @@ sub handle_action {
# Don't allow user-custom /msg factoids, unless factoid triggered by admin
if ($action =~ m/^\/msg/i) {
my $admin = $self->{pbot}->{users}->loggedin_admin($stuff->{from}, "$stuff->{nick}!$stuff->{user}\@$stuff->{host}");
if (not $admin or $admin->{level} < 60) {
if (not $admin) {
$self->{pbot}->{logger}->log("[ABUSE] Bad factoid (contains /msg): $action\n");
return "You are not powerful enough to use /msg in a factoid.";
return "You must be an admin to use /msg in a factoid.";
}
}
@ -1084,19 +1084,6 @@ sub handle_action {
} else {
if ($action =~ m/^\/(?:say|me|msg)/i) {
return $action;
} elsif ($action =~ s/^\/kick\s+//) {
if (not exists $self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'}) {
$stuff->{authorized} = 0;
return "/say $stuff->{nick}: $trigger_name doesn't have the effective-level to do that.";
}
my $level = 10;
if ($self->{factoids}->{hash}->{$channel}->{$keyword}->{'effective-level'} >= $level) {
$stuff->{authorized} = 1;
return "/kick " . $action;
} else {
$stuff->{authorized} = 0;
return "/say $stuff->{nick}: My effective-level isn't high enough to do that.";
}
} else {
return "/say $trigger_name is $action";
}

View File

@ -25,14 +25,10 @@ use warnings;
use strict;
use feature 'unicode_strings';
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -41,7 +37,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to FactoidCommands");
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { return $self->do_func(@_) }, 'func', 0);
$self->init_funcs;
}

View File

@ -40,7 +40,6 @@ sub initialize {
sub load {
my $self = shift;
my $filename;
if (@_) { $filename = shift; } else { $filename = $self->{filename}; }
if (not defined $filename) {
@ -85,7 +84,6 @@ sub load {
sub save {
my $self = shift;
my $filename;
if (@_) { $filename = shift; } else { $filename = $self->{filename}; }
if (not defined $filename) {

View File

@ -20,12 +20,8 @@ use Data::Dumper;
$Data::Dumper::Sortkeys = 1;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -33,9 +29,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot};
Carp::croak("Missing pbot parameter to " . __FILE__) if not defined $self->{pbot};
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot parameter to " . __FILE__);
$self->{pbot}->{event_dispatcher}->register_handler('irc.welcome', sub { $self->on_connect(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.disconnect', sub { $self->on_disconnect(@_) });

View File

@ -19,12 +19,8 @@ use Time::Duration;
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to IgnoreListCommands should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -32,16 +28,9 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
my $pbot = delete $conf{pbot};
if (not defined $pbot) {
Carp::croak("Missing pbot reference to IgnoreListCommands");
}
$self->{pbot} = $pbot;
$pbot->{commands}->register(sub { return $self->ignore_user(@_) }, "ignore", 10);
$pbot->{commands}->register(sub { return $self->unignore_user(@_) }, "unignore", 10);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { $self->ignore_user(@_) }, "ignore", 1);
$self->{pbot}->{commands}->register(sub { $self->unignore_user(@_) }, "unignore", 1);
}
sub ignore_user {

View File

@ -23,10 +23,7 @@ use Carp ();
use PBot::Utils::ValidateString;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -35,10 +32,8 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->SUPER::initialize(%conf);
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('text', 'general', 'compile_blocks', $conf{compile_blocks} // 1);
$self->{pbot}->{registry}->add_default('array', 'general', 'compile_blocks_channels', $conf{compile_blocks_channels} // '.*');
@ -174,8 +169,8 @@ sub process_line {
# check if user is ignored (and command isn't `login`)
if ($command !~ /^login / && defined $from && $pbot->{ignorelist}->check_ignore($nick, $user, $host, $from)) {
my $admin = $pbot->{users}->loggedin_admin($from, "$nick!$user\@$host");
if (!defined $admin || $admin->{level} < 10) {
# hostmask ignored
if (!defined $admin) {
# user is ignored
return 1;
}
}
@ -791,7 +786,7 @@ sub handle_result {
$stuff->{prepend} = $1;
}
if ($stuff->{pipe} and not $stuff->{authorized}) {
if ($stuff->{pipe}) {
my ($pipe, $pipe_rest) = (delete $stuff->{pipe}, delete $stuff->{pipe_rest});
if (not $stuff->{alldone}) {
$stuff->{command} = "$pipe $result $pipe_rest";
@ -975,27 +970,6 @@ sub output_result {
$pbot->{conn}->privmsg($to, $line) if $to ne $botnick;
$pbot->{antiflood}->check_flood($to, $botnick, $pbot->{registry}->get_value('irc', 'username'), 'pbot', $line, 0, 0, 0) if $stuff->{checkflood};
}
} elsif ($stuff->{authorized} && $line =~ s/^\/kick\s+//) {
$pbot->{antiflood}->check_flood($stuff->{from}, $botnick, $pbot->{registry}->get_value('irc', 'username'), 'pbot', '/kick ' . $line, 0, 0, 0) if $stuff->{checkflood};
my ($victim, $reason) = split /\s+/, $line, 2;
if (not defined $reason) {
if (open my $fh, '<', $self->{pbot}->{registry}->get_value('general', 'module_dir') . '/insults.txt') {
my @insults = <$fh>;
close $fh;
$reason = $insults[rand @insults];
chomp $reason;
} else {
$reason = 'Bye!';
}
}
if ($self->{pbot}->{chanops}->can_gain_ops($stuff->{from})) {
$self->{pbot}->{chanops}->add_op_command($stuff->{from}, "kick $stuff->{from} $victim $reason");
$self->{pbot}->{chanops}->gain_ops($stuff->{from});
} else {
$pbot->{conn}->privmsg($stuff->{from}, "$victim: $reason") if defined $stuff->{from} && $stuff->{from} ne $botnick;
}
} else {
if (defined $stuff->{nickoverride} and ($stuff->{no_nickoverride} == 0 or $stuff->{force_nickoverride} == 1)) {
$line = "$stuff->{nickoverride}: $line";
@ -1087,9 +1061,9 @@ sub process_command_queue {
preserve_whitespace => 0
};
if (exists $command->{level}) {
$self->{pbot}->{logger}->log("Override command effective-level to $command->{level}\n");
$stuff->{'effective-level'} = $command->{level};
if (exists $command->{'cap-override'}) {
$self->{pbot}->{logger}->log("[command queue] Override command capability with $command->{'cap-override'}\n");
$stuff->{'cap-override'} = $command->{'cap-override'};
}
my $result = $self->interpret($stuff);

View File

@ -30,7 +30,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to LagChecker");
$self->{lag_average} = undef; # average of entries in lag history, in seconds

View File

@ -14,45 +14,32 @@ use File::Basename;
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to Logger should be key/value pairs, not hash reference");
}
Carp::croak("Options to Logger should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
my $pbot = $conf{pbot} // Carp::croak "Missing pbot reference to " . __FILE__;
my $logfile = $conf{filename} // Carp::croak "Missing logfile parameter in " . __FILE__;
$self->{pbot} = $conf{pbot} // Carp::croak "Missing pbot reference to " . __FILE__;
$self->{logfile} = $conf{filename} // Carp::croak "Missing logfile parameter in " . __FILE__;
$self->{start} = time;
my $path = dirname $logfile;
my $path = dirname $self->{logfile};
if (not -d $path) {
print "Creating new logfile path: $path\n";
mkdir $path or Carp::croak "Couldn't create logfile path: $!\n";
}
open LOGFILE, ">>$logfile" or Carp::croak "Couldn't open logfile $logfile: $!\n";
open LOGFILE, ">>$self->{logfile}" or Carp::croak "Couldn't open logfile $self->{logfile}: $!\n";
LOGFILE->autoflush(1);
my $self = bless {
logfile => $logfile,
pbot => $pbot,
start => time,
}, $class;
$self->{pbot}->{atexit}->register(sub { $self->rotate_log; return; });
return $self;
}
sub log {
my ($self, $text) = @_;
my $time = localtime;
$text =~ s/(\P{PosixGraph})/my $ch = $1; if ($ch =~ m{[\s]}) { $ch } else { sprintf "\\x%02X", ord $ch }/ge;
if (openhandle *LOGFILE) {
print LOGFILE "$time :: $text";
}
print LOGFILE "$time :: $text" if openhandle *LOGFILE;
print "$time :: $text";
}

View File

@ -26,10 +26,7 @@ use Carp ();
use PBot::MessageHistory_SQLite;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -38,8 +35,8 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{filename} = delete $conf{filename} // $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/message_history.sqlite3';
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{filename} = $conf{filename} // $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/message_history.sqlite3';
$self->{database} = PBot::MessageHistory_SQLite->new(pbot => $self->{pbot}, filename => $self->{filename});
$self->{database}->begin();
@ -55,9 +52,9 @@ sub initialize {
$self->{pbot}->{commands}->register(sub { $self->recall_message(@_) }, "recall", 0);
$self->{pbot}->{commands}->register(sub { $self->list_also_known_as(@_) }, "aka", 0);
$self->{pbot}->{commands}->register(sub { $self->rebuild_aliases(@_) }, "rebuildaliases", 90);
$self->{pbot}->{commands}->register(sub { $self->aka_link(@_) }, "akalink", 60);
$self->{pbot}->{commands}->register(sub { $self->aka_unlink(@_) }, "akaunlink", 60);
$self->{pbot}->{commands}->register(sub { $self->rebuild_aliases(@_) }, "rebuildaliases", 1);
$self->{pbot}->{commands}->register(sub { $self->aka_link(@_) }, "akalink", 1);
$self->{pbot}->{commands}->register(sub { $self->aka_unlink(@_) }, "akaunlink", 1);
$self->{pbot}->{atexit}->register(sub { $self->{database}->end(); return; });
}

View File

@ -22,12 +22,8 @@ use Text::Levenshtein qw/fastdistance/;
use Time::Duration;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -36,8 +32,8 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference in " . __FILE__);
$self->{filename} = delete $conf{filename} // $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/message_history.sqlite3';
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference in " . __FILE__);
$self->{filename} = $conf{filename} // $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/message_history.sqlite3';
$self->{new_entries} = 0;
$self->{pbot}->{registry}->add_default('text', 'messagehistory', 'debug_link', 0);

View File

@ -32,10 +32,9 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{nicklist} = {};
$self->{nicklist} = {};
$self->{pbot}->{registry}->add_default('text', 'nicklist', 'debug', '0');
$self->{pbot}->{commands}->register(sub { $self->show_nicklist(@_) }, "nicklist", 0);
@ -57,10 +56,7 @@ sub initialize {
sub show_nicklist {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $nicklist;
if (not length $arguments) {
return "Usage: nicklist <channel> [nick]";
}
return "Usage: nicklist <channel> [nick]" if not length $arguments;
my @args = split / /, $arguments;
@ -77,7 +73,6 @@ sub show_nicklist {
}
$nicklist = Dumper($self->{nicklist}->{lc $args[0]}->{lc $args[1]});
}
return $nicklist;
}
@ -170,7 +165,6 @@ sub delete_meta {
or not exists $self->{nicklist}->{$channel}->{$nick}->{$key}) {
return undef;
}
return delete $self->{nicklist}->{$channel}->{$nick}->{$key};
}
@ -240,7 +234,6 @@ sub is_present_similar {
return $self->{nicklist}->{$channel}->{$person}->{nick};
}
}
return 0;
}
@ -290,7 +283,6 @@ sub on_namreply {
$self->set_meta($channel, $stripped_nick, '+h', 1);
}
}
return 0;
}
@ -327,7 +319,6 @@ sub on_quit {
$self->remove_nick($channel, $nick);
}
}
return 0;
}
@ -350,7 +341,6 @@ sub on_nickchange {
$self->{nicklist}->{$channel}->{lc $newnick} = $meta;
}
}
return 0;
}

View File

@ -49,10 +49,7 @@ use PBot::Utils::ParseDate;
use PBot::FuncCommand;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to PBot should be key/value pairs, not hash reference");
}
Carp::croak("Options to PBot should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->{atexit} = PBot::Registerable->new(%conf);
@ -63,7 +60,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{startup_timestamp} = time;
my $data_dir = $conf{data_dir};
@ -331,7 +327,7 @@ sub listcmd {
my ($from, $nick, $user, $host, $arguments) = @_;
my $text;
my $usage = "Usage: list <modules|commands|admins|users>";
my $usage = "Usage: list <modules|commands|users>";
if (not defined $arguments) {
return $usage;
@ -353,8 +349,11 @@ sub listcmd {
if ($arguments =~ /^commands$/i) {
$text = "Registered commands: ";
foreach my $command (sort { $a->{name} cmp $b->{name} } @{ $self->{commands}->{handlers} }) {
$text .= "$command->{name} ";
$text .= "($command->{level}) " if $command->{level} > 0;
if ($command->{requires_cap}) {
$text .= "+$command->{name} ";
} else {
$text .= "$command->{name} ";
}
}
return $text;
}
@ -373,31 +372,17 @@ sub listcmd {
foreach my $hostmask (sort { return 0 if $a eq '_name' or $b eq '_name'; $self->{users}->{users}->{hash}->{$channel}->{$a}->{name} cmp $self->{users}->{users}->{hash}->{$channel}->{$b}->{name} } keys %{ $self->{users}->{users}->{hash}->{$channel} }) {
next if $hostmask eq '_name';
$text .= $sep;
my $has_cap = 0;
foreach my $key (keys %{$self->{users}->{users}->{hash}->{$channel}->{$hostmask}}) {
next if $key eq '_name';
if ($self->{capabilities}->exists($key)) {
print "has $key?\n";
$has_cap = 1;
last;
}
}
$text .= '+' if $has_cap;
$text .= $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{name};
$text .= "(" . $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{level} . ")" if $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{level} > 0;
$sep = " ";
}
$sep = "; ";
}
return $text;
}
if ($arguments =~ /^admins$/i) {
$text = "Admins: ";
my $last_channel = "";
my $sep = "";
foreach my $channel (sort keys %{ $self->{users}->{users}->{hash} }) {
next if $from =~ m/^#/ and $channel ne $from and $channel ne '.*';
if ($last_channel ne $channel) {
$text .= $sep . ($channel eq ".*" ? "global" : $channel) . ": ";
$last_channel = $channel;
$sep = "";
}
foreach my $hostmask (sort { return 0 if $a eq '_name' or $b eq '_name'; $self->{users}->{users}->{hash}->{$channel}->{$a}->{name} cmp $self->{users}->{users}->{hash}->{$channel}->{$b}->{name} } keys %{ $self->{users}->{users}->{hash}->{$channel} }) {
next if $hostmask eq '_name';
next if $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{level} <= 0;
$text .= $sep;
$text .= $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{name} . " (" . $self->{users}->{users}->{hash}->{$channel}->{$hostmask}->{level} . ")";
$sep = " ";
}
$sep = "; ";

View File

@ -18,12 +18,8 @@ use File::Basename;
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -31,20 +27,16 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{plugins} = {};
$self->{pbot}->{commands}->register(sub { $self->load_cmd(@_) }, "plug", 90);
$self->{pbot}->{commands}->register(sub { $self->unload_cmd(@_) }, "unplug", 90);
$self->{pbot}->{commands}->register(sub { $self->reload_cmd(@_) }, "replug", 90);
$self->{pbot}->{commands}->register(sub { $self->list_cmd(@_) }, "pluglist", 0);
$self->{pbot}->{commands}->register(sub { $self->load_cmd(@_) }, "plug", 1);
$self->{pbot}->{commands}->register(sub { $self->unload_cmd(@_) }, "unplug", 1);
$self->{pbot}->{commands}->register(sub { $self->reload_cmd(@_) }, "replug", 1);
$self->{pbot}->{commands}->register(sub { $self->list_cmd(@_) }, "pluglist", 0);
}
sub autoload {
my ($self, %conf) = @_;
return if $self->{pbot}->{registry}->get_value('plugins', 'noautoload');
my $path = $self->{pbot}->{registry}->get_value('general', 'plugin_dir') // 'Plugins';
@ -71,7 +63,6 @@ sub autoload {
$plugin_count++ if $self->load($plugin, %conf)
}
$self->{pbot}->{logger}->log("$plugin_count plugin" . ($plugin_count == 1 ? '' : 's') . " loaded.\n");
}
@ -112,7 +103,6 @@ sub load {
$self->{pbot}->{logger}->log("Error loading $plugin: $@\n");
return 0;
}
return $ret;
}
@ -189,7 +179,6 @@ sub unload_cmd {
sub list_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $result = "Loaded plugins: ";
my $count = 0;
my $comma = '';
@ -201,7 +190,6 @@ sub list_cmd {
}
$result .= 'none' if $count == 0;
return $result;
}

View File

@ -22,10 +22,7 @@ use PBot::DualIndexHashObject;
use PBot::RegistryCommands;
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be item/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be item/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -34,15 +31,11 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
my $filename = $conf{filename} // Carp::croak("Missing filename reference in " . __FILE__);
$self->{registry} = PBot::DualIndexHashObject->new(name => 'Registry', filename => $filename, pbot => $self->{pbot});
$self->{triggers} = {};
$self->{pbot}->{atexit}->register(sub { $self->save; return; });
PBot::RegistryCommands->new(pbot => $self->{pbot});
}
@ -107,7 +100,6 @@ sub remove {
if (not scalar keys %{ $self->{registry}->{hash}->{$section} }) {
delete $self->{registry}->{hash}->{$section};
}
$self->save;
}
@ -139,7 +131,6 @@ sub set {
}
$self->save if !$dont_save && $result =~ m/set to/ && not $is_default;
return $result;
}

View File

@ -17,10 +17,7 @@ use feature 'unicode_strings';
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference");
}
Carp::croak("Options to " . __FILE__ . " should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
@ -29,23 +26,19 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
my $pbot = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $pbot;
$pbot->{commands}->register(sub { return $self->regset(@_) }, "regset", 60);
$pbot->{commands}->register(sub { return $self->regunset(@_) }, "regunset", 60);
$pbot->{commands}->register(sub { return $self->regshow(@_) }, "regshow", 0);
$pbot->{commands}->register(sub { return $self->regsetmeta(@_) }, "regsetmeta", 60);
$pbot->{commands}->register(sub { return $self->regunsetmeta(@_) }, "regunsetmeta", 60);
$pbot->{commands}->register(sub { return $self->regchange(@_) }, "regchange", 60);
$pbot->{commands}->register(sub { return $self->regfind(@_) }, "regfind", 0);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { $self->regset(@_) }, "regset", 1);
$self->{pbot}->{commands}->register(sub { $self->regunset(@_) }, "regunset", 1);
$self->{pbot}->{commands}->register(sub { $self->regshow(@_) }, "regshow", 0);
$self->{pbot}->{commands}->register(sub { $self->regsetmeta(@_) }, "regsetmeta", 1);
$self->{pbot}->{commands}->register(sub { $self->regunsetmeta(@_) }, "regunsetmeta", 1);
$self->{pbot}->{commands}->register(sub { $self->regchange(@_) }, "regchange", 1);
$self->{pbot}->{commands}->register(sub { $self->regfind(@_) }, "regfind", 0);
}
sub regset {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $usage = "Usage: regset <section>.<item> <value>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -71,7 +64,6 @@ sub regset {
sub regunset {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $usage = "Usage: regunset <section>.<item>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -106,7 +98,6 @@ sub regunset {
sub regsetmeta {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $usage = "Usage: regsetmeta <section>.<item> [key [value]]";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -125,14 +116,12 @@ sub regsetmeta {
$key = undef if not length $key;
$value = undef if not length $value;
return $self->{pbot}->{registry}->set($section, $item, $key, $value);
}
sub regunsetmeta {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $usage = "Usage: regunsetmeta <section>.<item> <key>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -148,7 +137,6 @@ sub regunsetmeta {
if (not defined $section or not defined $item or not defined $key) {
return $usage;
}
return $self->{pbot}->{registry}->unset($section, $item, $key);
}
@ -156,7 +144,6 @@ sub regshow {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $stuff) = @_;
my $registry = $self->{pbot}->{registry}->{registry}->{hash};
my $usage = "Usage: regshow <section>.<item>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -192,7 +179,6 @@ sub regshow {
if ($registry->{$section}->{$item}->{type} eq 'array') {
$result .= ' [array]';
}
return $result;
}
@ -200,15 +186,11 @@ sub regfind {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
my $registry = $self->{pbot}->{registry}->{registry}->{hash};
my $usage = "Usage: regfind [-showvalues] [-section section] <regex>";
if (not defined $arguments) {
return $usage;
}
return $usage if not defined $arguments;
my ($section, $showvalues);
$section = $1 if $arguments =~ s/-section\s+([^\b\s]+)//i;
$showvalues = 1 if $arguments =~ s/-showvalues?//i;
@ -216,9 +198,7 @@ sub regfind {
$arguments =~ s/\s+$//;
$arguments =~ s/\s+/ /g;
if ($arguments eq "") {
return $usage;
}
return $usage if $arguments eq "";
$section = lc $section if defined $section;;

View File

@ -13,12 +13,8 @@ use IO::Select;
use Carp ();
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to SelectHandler should be key/value pairs, not hash reference");
}
Carp::croak("Options to SelectHandler should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -26,8 +22,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference in SelectHandler");
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference in SelectHandler");
$self->{select} = IO::Select->new();
$self->{readers} = {};
$self->{buffers} = {};

View File

@ -22,7 +22,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference in StdinReader");
# create implicit bot-admin account for bot
@ -61,7 +60,6 @@ sub stdin_reader {
$from = $self->{pbot}->{registry}->get_value('irc', 'botnick') . "!stdin\@pbot";
$text = $self->{pbot}->{registry}->get_value('irc', 'botnick') . " $input";
}
return $self->{pbot}->{interpreter}->process_line($from, $self->{pbot}->{registry}->get_value('irc', 'botnick'), "stdin", "pbot", $text);
}

View File

@ -27,8 +27,6 @@ $SIG{ALRM} = sub {
$seconds += $min_timeout;
alarm $min_timeout;
# print "ALARM! $seconds $min_timeout\n";
# call timer func subroutines
foreach my $func (@timer_funcs) { &$func; }

View File

@ -27,9 +27,9 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{users} = PBot::DualIndexHashObject->new(name => 'Users', filename => $conf{filename}, pbot => $conf{pbot});
$self->{users} = PBot::DualIndexHashObject->new(name => 'Users', filename => $conf{filename}, pbot => $conf{pbot});
$self->load;
$self->{pbot}->{commands}->register(sub { return $self->logincmd(@_) }, "login", 0);
@ -74,7 +74,7 @@ sub on_join {
}
if ($u->{autologin}) {
$self->{pbot}->{logger}->log("$nick!$user\@$host autologin to $u->{name} ($u->{level}) for $channel\n");
$self->{pbot}->{logger}->log("$nick!$user\@$host autologin to $u->{name} for $channel\n");
$u->{loggedin} = 1;
}
}
@ -82,19 +82,23 @@ sub on_join {
}
sub add_user {
my ($self, $name, $channel, $hostmask, $level, $password, $dont_save) = @_;
my ($self, $name, $channel, $hostmask, $capabilities, $password, $dont_save) = @_;
$channel = '.*' if $channel !~ m/^#/;
$level //= 0;
$capabilities //= 'none';
$password //= $self->{pbot}->random_nick(16);
my $data = {
name => $name,
level => $level,
password => $password
};
$self->{pbot}->{logger}->log("Adding new user (level $level): name: $name hostmask: $hostmask channel: $channel\n");
foreach my $cap (split /\s*,\s*/, $capabilities) {
next if $cap eq 'none';
$data->{$cap} = 1;
}
$self->{pbot}->{logger}->log("Adding new user (caps: $capabilities): name: $name hostmask: $hostmask channel: $channel\n");
$self->{users}->add($channel, $hostmask, $data, $dont_save);
return $data;
}
@ -123,10 +127,9 @@ sub load {
next if $hostmask eq '_name';
$i++;
my $name = $self->{users}->{hash}->{$channel}->{$hostmask}->{name};
my $level = $self->{users}->{hash}->{$channel}->{$hostmask}->{level};
my $password = $self->{users}->{hash}->{$channel}->{$hostmask}->{password};
if (not defined $name or not defined $level or not defined $password) {
if (not defined $name or not defined $password) {
Carp::croak "A user in $filename is missing critical data\n";
}
}
@ -150,16 +153,13 @@ sub find_user_account {
foreach my $chan (keys %{ $self->{users}->{hash} }) {
if ($channel !~ m/^#/ or $channel =~ m/^$chan$/i) {
if (not exists $self->{users}->{hash}->{$chan}->{$hostmask}) {
my $last_level = 0;
# find hostmask by account name or wildcard
foreach my $mask (keys %{ $self->{users}->{hash}->{$chan} }) {
next if $mask eq '_name';
if (lc $self->{users}->{hash}->{$chan}->{$mask}->{name} eq $hostmask) {
if ($last_level <= $self->{users}->{hash}->{$chan}->{$mask}->{level}) {
$found_hostmask = $mask;
$found_channel = $chan;
$last_level = $self->{users}->{hash}->{$chan}->{$mask}->{level};
}
$found_hostmask = $mask;
$found_channel = $chan;
last;
}
if ($mask =~ /[*?]/) {
@ -168,26 +168,23 @@ sub find_user_account {
$mask_quoted =~ s/\\\*/.*?/g;
$mask_quoted =~ s/\\\?/./g;
if ($hostmask =~ m/^$mask_quoted$/i) {
if ($last_level <= $self->{users}->{hash}->{$chan}->{$mask}->{level}) {
$found_hostmask = $mask;
$found_channel = $chan;
$last_level = $self->{users}->{hash}->{$chan}->{$mask}->{level};
}
$found_hostmask = $mask;
$found_channel = $chan;
last;
}
}
}
} else {
$found_channel = $chan;
last;
}
}
}
return ($found_channel, $found_hostmask);
}
sub find_admin {
my ($self, $channel, $hostmask, $min_level) = @_;
$min_level //= 1;
sub find_user {
my ($self, $channel, $hostmask) = @_;
($channel, $hostmask) = $self->find_user_account($channel, $hostmask);
$channel = '.*' if not defined $channel;
@ -195,7 +192,7 @@ sub find_admin {
$hostmask = lc $hostmask;
my $result = eval {
my $admin;
my $user;
foreach my $channel_regex (keys %{ $self->{users}->{hash} }) {
if ($channel !~ m/^#/ or $channel =~ m/^$channel_regex$/i) {
foreach my $hostmask_regex (keys %{ $self->{users}->{hash}->{$channel_regex} }) {
@ -206,51 +203,45 @@ sub find_admin {
$hostmask_quoted =~ s/\\\*/.*?/g;
$hostmask_quoted =~ s/\\\?/./g;
if ($hostmask =~ m/^$hostmask_quoted$/i) {
my $temp = $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex};
$admin = $temp if $temp->{level} >= $min_level and (not defined $admin or $admin->{level} <= $temp->{level});
return $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex};
}
} else {
# direct comparison
if ($hostmask eq lc $hostmask_regex) {
my $temp = $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex};
$admin = $temp if $temp->{level} >= $min_level and (not defined $admin or $admin->{level} <= $temp->{level});
return $self->{users}->{hash}->{$channel_regex}->{$hostmask_regex};
}
}
}
}
}
return $admin;
return undef;
};
if ($@) {
$self->{pbot}->{logger}->log("Error in find_admin parameters: $@\n");
$self->{pbot}->{logger}->log("Error in find_user parameters: $@\n");
}
return $result;
}
sub find_user {
sub find_admin {
my ($self, $from, $hostmask) = @_;
return $self->find_admin($from, $hostmask, 0);
my $user = $self->find_user($from, $hostmask);
return undef if not defined $user;
return undef if not $self->{pbot}->{capabilities}->userhas($user, 'admin');
return $user;
}
sub loggedin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->find_user($channel, $hostmask);
if (defined $user and $user->{loggedin}) {
return $user;
}
return $user if defined $user and $user->{loggedin};
return undef;
}
sub loggedin_admin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->loggedin($channel, $hostmask);
if (defined $user and $user->{level} > 0) {
return $user;
}
return $user if defined $user and $self->{pbot}->{capabilities}->userhas($user, 'admin');
return undef;
}
@ -293,9 +284,7 @@ sub logincmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $channel = $from;
if (not $arguments) {
return "Usage: login [channel] password";
}
return "Usage: login [channel] password" if not $arguments;
if ($arguments =~ m/^([^ ]+)\s+(.+)/) {
$channel = $1;
@ -303,10 +292,7 @@ sub logincmd {
}
my ($user_channel, $user_hostmask) = $self->find_user_account($channel, "$nick!$user\@$host");
if (not defined $user_channel) {
return "/msg $nick You do not have a user account.";
}
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 $channel_text = $user_channel eq '.*' ? '' : " for $user_channel";
@ -343,29 +329,35 @@ sub logoutcmd {
sub useradd {
my ($self, $from, $nick, $user, $host, $arguments, $stuff) = @_;
my ($name, $channel, $hostmask, $level, $password) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5);
$level //= 0;
my ($name, $channel, $hostmask, $capabilities, $password) = $self->{pbot}->{interpreter}->split_args($stuff->{arglist}, 5);
$capabilities //= 'none';
if (not defined $name or not defined $channel or not defined $hostmask) {
return "Usage: useradd <account name> <channel> <hostmask> [level [password]]";
return "Usage: useradd <account name> <channel> <hostmask> [capabilities [password]]";
}
$channel = '.*' if $channel !~ /^#/;
my $admin = $self->{pbot}->{users}->find_admin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->find_user($channel, "$nick!$user\@$host");
if (not $admin) {
if (not defined $u) {
$channel = 'global' if $channel eq '.*';
return "You are not an admin for $channel; cannot add users to that channel.\n";
return "You do not have a user account for $channel; cannot add users to that channel.\n";
}
# don't allow non-bot-owners to add admins that can also add admins
if ($admin->{level} < 90 and $level > 40) {
return "You may not set admin level higher than 40.\n";
if ($capabilities ne 'none' and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-capabilities')) {
return "Your user account does not have the can-modify-capabilities capability. You cannot create user accounts with capabilities.";
}
$self->{pbot}->{users}->add_user($name, $channel, $hostmask, $level, $password);
return !$level ? "User added." : "Admin added.";
foreach my $cap (split /\s*,\s*/, $capabilities) {
next if $cap eq 'none';
return "There is no such capability $cap." if not $self->{pbot}->{capabilities}->exists($cap);
if (not $self->{pbot}->{capabilities}->userhas($u, $cap)) {
return "To set the $cap capability your user account must also have it.";
}
}
$self->{pbot}->{users}->add_user($name, $channel, $hostmask, $capabilities, $password);
return "User added.";
}
sub userdel {
@ -395,12 +387,12 @@ sub userset {
return "Usage: userset [channel] <hostmask or account name> [key [value]]";
}
my $admin = $self->find_admin($channel, "$nick!$user\@$host");
my $u = $self->find_user($channel, "$nick!$user\@$host");
my $target = $self->find_user($channel, $hostmask);
if (not $admin) {
if (not $u) {
$channel = 'global' if $channel eq '.*';
return "You are not an admin for $channel; cannot modify their users.";
return "You do not have a user account for $channel; cannot modify their users.";
}
if (not $target) {
@ -411,13 +403,14 @@ sub userset {
}
}
# don't allow non-bot-owners to add admins that can also add admins
if (defined $key and $key eq 'level' and $admin->{level} < 90 and $value > 40) {
return "You may not set user level higher than 40.\n";
if (defined $value and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-capabilities')) {
if ($key =~ m/^can-/i or $self->{pbot}->{capabilities}->exists($key)) {
return "The $key metadata requires the can-modify-capabilities capability, which your user account does not have.";
}
}
if (defined $key and $target->{level} > $admin->{level}) {
return "You may not modify users higher in level than you.";
if ($self->{pbot}->{capabilities}->exists($key) and not $self->{pbot}->{capabilities}->userhas($u, $key)) {
return "To set the $key capability your user account must also have it.";
}
my ($found_channel, $found_hostmask) = $self->find_user_account($channel, $hostmask);
@ -440,12 +433,12 @@ sub userunset {
return "Usage: userunset [channel] <hostmask or account name> <key>";
}
my $admin = $self->find_admin($channel, "$nick!$user\@$host");
my $u = $self->find_admin($channel, "$nick!$user\@$host");
my $target = $self->find_user($channel, $hostmask);
if (not $admin) {
if (not $u) {
$channel = 'global' if $channel eq '.*';
return "You are not an admin for $channel; cannot modify their users.";
return "You do not have a user account for $channel; cannot modify their users.";
}
if (not $target) {
@ -456,8 +449,14 @@ sub userunset {
}
}
if ($target->{level} > $admin->{level}) {
return "You may not modify users higher in level than you.";
if (defined $key and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-capabilities')) {
if ($key =~ m/^can-/i or $self->{pbot}->{capabilities}->exists($key)) {
return "The $key metadata requires the can-modify-capabilities capability, which your user account does not have.";
}
}
if (defined $key and $self->{pbot}->{capabilities}->exists($key) and not $self->{pbot}->{capabilities}->userhas($u, $key)) {
return "To unset the $key capability your user account must also have it.";
}
my ($found_channel, $found_hostmask) = $self->find_user_account($channel, $hostmask);

View File

@ -78,7 +78,6 @@ sub version_cmd {
if ($self->{last_check}->{version} > BUILD_REVISION) {
$result .= "; new version available: $self->{last_check}->{version} $self->{last_check}->{date}!";
}
return $result;
}

View File

@ -26,8 +26,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('text', 'antiaway', 'bad_nicks', $conf{bad_nicks} // '([[:punct:]](afk|brb|bbl|away|sleep|z+|work|gone|study|out|home|busy|off)[[:punct:]]*$|.+\[.*\]$)');
$self->{pbot}->{registry}->add_default('text', 'antiaway', 'bad_actions', $conf{bad_actions} // '^/me (is (away|gone)|.*auto.?away)');
@ -52,7 +51,6 @@ sub on_nickchange {
$self->{pbot}->{chanops}->gain_ops($chan);
}
}
return 0;
}
@ -70,7 +68,6 @@ sub on_action {
$self->{pbot}->{chanops}->add_op_command($channel, "kick $channel $nick $kick_msg");
$self->{pbot}->{chanops}->gain_ops($channel);
}
return 0;
}

View File

@ -28,7 +28,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('array', 'antikickautorejoin', 'punishment', '300,900,1800,3600,28800');
@ -36,7 +35,6 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) });
$self->{kicks} = {};
}
@ -54,7 +52,6 @@ sub on_kick {
}
$self->{kicks}->{$channel}->{$target}->{last_kick} = gettimeofday;
return 0;
}
@ -82,7 +79,6 @@ sub on_join {
$self->{kicks}->{$channel}->{$nick}->{rejoins}++;
}
}
return 0;
}

View File

@ -30,10 +30,8 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.caction', sub { $self->on_action(@_) });
$self->{nicks} = {};
}
@ -98,7 +96,6 @@ sub clear_old_nicks {
last;
}
}
delete $self->{nicks}->{$channel} if not @{$self->{nicks}->{$channel}};
}

View File

@ -28,7 +28,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('text', 'antiflood', 'antirepeat', $conf{antirepeat} // 1);
@ -40,17 +39,11 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.caction', sub { $self->on_public(@_) });
$self->{pbot}->{timer}->register(sub { $self->adjust_offenses }, 60 * 60 * 1, 'antirepeat');
$self->{offenses} = {};
}
sub unload {
my $self = shift;
# perform plugin clean-up here
# normally we'd unregister the 'irc.public' event handler; however, the
# event dispatcher will do this automatically for us when it sees there
# is no longer an existing sub.
$self->{pbot}->{timer}->unregister('antirepeat');
}
@ -161,7 +154,6 @@ sub on_public {
return 0;
}
}
return 0;
}

View File

@ -28,20 +28,17 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('array', 'autorejoin', 'rejoin_delay', '900,1800,3600');
$self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_part(@_) });
$self->{rejoins} = {};
}
sub rejoin_channel {
my ($self, $channel) = @_;
$self->{rejoins}->{$channel}->{rejoins} = 0 if not exists $self->{rejoins}->{$channel};
my $delay = $self->{pbot}->{registry}->get_array_value($channel, 'rejoin_delay', $self->{rejoins}->{$channel}->{rejoins});
@ -51,8 +48,6 @@ sub rejoin_channel {
$delay = duration $delay;
$self->{pbot}->{logger}->log("Rejoining $channel in $delay.\n");
#$self->{rejoins}->{$channel}->{rejoins}++;
$self->{rejoins}->{$channel}->{last_rejoin} = gettimeofday;
}
@ -66,7 +61,6 @@ sub on_kick {
if ($target eq $self->{pbot}->{registry}->get_value('irc', 'botnick')) {
$self->rejoin_channel($channel);
}
return 0;
}
@ -80,7 +74,6 @@ sub on_part {
if ($nick eq $self->{pbot}->{registry}->get_value('irc', 'botnick')) {
$self->rejoin_channel($channel);
}
return 0;
}

View File

@ -29,7 +29,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { $self->battleship_cmd(@_) }, 'battleship', 0);

View File

@ -29,7 +29,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot};
$self->{pbot} = $conf{pbot};
$self->{pbot}->{commands}->register(sub { $self->connect4_cmd(@_) }, 'connect4', 0);

View File

@ -27,7 +27,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { $self->counteradd(@_) }, 'counteradd', 0);
@ -40,7 +39,6 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
$self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/counters.sqlite3';
$self->create_database;
}
@ -130,7 +128,6 @@ sub add_counter {
$self->{pbot}->{logger}->log("Add counter failed: $@");
return 0;
}
return 1;
}
@ -155,7 +152,6 @@ sub reset_counter {
$self->{pbot}->{logger}->log("Reset counter failed: $@");
return (undef, undef);
}
return ($description, $timestamp);
}
@ -179,7 +175,6 @@ sub delete_counter {
$self->{pbot}->{logger}->log("Delete counter failed: $@");
return 0;
}
return 1;
}
@ -196,7 +191,6 @@ sub list_counters {
if ($@) {
$self->{pbot}->{logger}->log("List counters failed: $@");
}
return map { $_->[0] } @$counters;
}
@ -216,7 +210,6 @@ sub get_counter {
$self->{pbot}->{logger}->log("Get counter failed: $@");
return undef;
}
return ($description, $time, $counter, $created_on, $created_by);
}
@ -240,7 +233,6 @@ sub add_trigger {
$self->{pbot}->{logger}->log("Add trigger failed: $@");
return 0;
}
return 1;
}
@ -256,7 +248,6 @@ sub delete_trigger {
$sth->bind_param(1, lc $channel);
$sth->bind_param(2, lc $trigger);
$sth->execute();
return 1;
}
@ -273,7 +264,6 @@ sub list_triggers {
if ($@) {
$self->{pbot}->{logger}->log("List triggers failed: $@");
}
return @$triggers;
}
@ -293,17 +283,12 @@ sub get_trigger {
$self->{pbot}->{logger}->log("Get trigger failed: $@");
return undef;
}
return $target;
}
sub counteradd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my ($channel, $name, $description);
if ($from !~ m/^#/) {
@ -325,18 +310,13 @@ sub counteradd {
} else {
$result = "Counter '$name' already exists.";
}
$self->dbi_end;
return $result;
}
sub counterdel {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
@ -358,18 +338,13 @@ sub counterdel {
} else {
$result = "No such counter.";
}
$self->dbi_end;
return $result;
}
sub counterreset {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
@ -400,11 +375,7 @@ sub counterreset {
sub countershow {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
@ -436,11 +407,7 @@ sub countershow {
sub counterlist {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my $channel;
if ($from !~ m/^#/) {
@ -472,11 +439,7 @@ sub counterlist {
sub countertrigger {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not $self->dbi_begin) {
return "Internal error.";
}
return "Internal error." if not $self->dbi_begin;
my $command;
($command, $arguments) = split / /, $arguments, 2;
@ -642,9 +605,7 @@ sub on_public {
$self->{pbot}->{logger}->log("Skipping bad trigger $trigger->{trigger}: $@");
}
}
$self->dbi_end;
return 0;
}

View File

@ -21,10 +21,8 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
}
sub unload {
@ -45,7 +43,6 @@ sub on_public {
}
$self->{pbot}->{logger}->log("Example plugin: got message from $nick!$user\@$host: $msg\n");
return 0;
}

View File

@ -26,7 +26,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('text', 'googlesearch', 'api_key', '');
@ -107,7 +106,6 @@ sub googlesearch {
$comma = " -- ";
last if --$matches <= 0;
}
return $output;
}

View File

@ -13,7 +13,6 @@ use warnings;
use strict;
use feature 'unicode_strings';
use Carp ();
sub new {
@ -26,7 +25,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { return $self->magic(@_)}, "mc", 90);
}
@ -39,7 +37,6 @@ sub unload {
sub magic {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
# do something magical!
return "Did something magical.";
}

View File

@ -10,7 +10,6 @@ use warnings;
use strict;
use feature 'unicode_strings';
use Carp ();
use Time::Duration qw/duration/;

View File

@ -26,12 +26,8 @@ use PBot::Utils::ValidateString;
use POSIX qw(strftime);
sub new {
if (ref($_[1]) eq 'HASH') {
Carp::croak("Options to Quotegrabs should be key/value pairs, not hash reference");
}
Carp::croak("Options to Quotegrabs should be key/value pairs, not hash reference") if ref($_[1]) eq 'HASH';
my ($class, %conf) = @_;
my $self = bless {}, $class;
$self->initialize(%conf);
return $self;
@ -39,7 +35,6 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference in Quotegrabs");
$self->{filename} = $conf{quotegrabs_file} // $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/quotegrabs.sqlite3';

View File

@ -30,31 +30,23 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{commands}->register(sub { $self->remindme(@_) }, 'remindme', 0);
$self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/reminders.sqlite3';
$self->{pbot}->{timer}->register(sub { $self->check_reminders(@_) }, 1, 'RemindMe');
$self->dbi_begin;
$self->create_database;
}
sub unload {
my $self = shift;
$self->dbi_end;
$self->{pbot}->{commands}->unregister('remindme');
$self->{pbot}->{timer}->unregister('RemindMe');
}
sub create_database {
my $self = shift;
return if not $self->{dbh};
eval {
@ -154,7 +146,6 @@ sub get_reminder {
$self->{pbot}->{logger}->log("List reminders failed: $@");
return undef;
}
return $reminder;
}

View File

@ -26,8 +26,7 @@ sub new {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot} = delete $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot} = $conf{pbot} // Carp::croak("Missing pbot reference to " . __FILE__);
$self->{pbot}->{registry}->add_default('text', 'general', 'show_url_titles', $conf{show_url_titles} // 1);
$self->{pbot}->{registry}->add_default('array', 'general', 'show_url_titles_channels', $conf{show_url_titles_channels} // '.*');
@ -37,9 +36,7 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.caction', sub { $self->show_url_titles(@_) });
}
sub unload {
my $self = shift;
}
sub unload {}
sub show_url_titles {
my ($self, $event_type, $event) = @_;
@ -88,7 +85,6 @@ sub show_url_titles {
$self->{pbot}->{factoids}->{factoidmodulelauncher}->execute_module($stuff);
}
}
return 0;
}

View File

@ -71,7 +71,6 @@ sub weathercmd {
if (not length $arguments) {
return $usage;
}
return $self->get_weather($arguments);
}
@ -125,7 +124,6 @@ sub get_weather {
last;
}
}
return $result;
}

230
data/commands vendored
View File

@ -2,532 +2,546 @@
"actiontrigger" : {
"_name" : "actiontrigger",
"help" : "Adds a new actiontrigger to PBot. See https://github.com/pragma-/pbot/blob/master/doc/ActionTrigger.md",
"level" : 10
"requires_cap" : 1
},
"aka" : {
"_name" : "aka",
"help" : "Lists known aliases for a given nick. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#aka",
"level" : 0
"requires_cap" : 0
},
"akalink" : {
"_name" : "akalink",
"help" : "Manually link a known alias to a nick. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#akalink",
"level" : 60
"requires_cap" : 1
},
"akaunlink" : {
"_name" : "akaunlink",
"help" : "Manually unlink a known alias from a nick. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#akaunlink",
"level" : 60
"requires_cap" : 1
},
"antispam" : {
"_name" : "antispam",
"help" : "See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#antispam",
"level" : 10
"requires_cap" : 1
},
"ban" : {
"_name" : "ban",
"help" : "Bans a user. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#banmute",
"level" : 10
"requires_cap" : 1
},
"battleship" : {
"_name" : "battleship",
"help" : "The classic Battleship board game, modified for IRC. See https://github.com/pragma-/pbot/blob/master/doc/Battleship.md",
"level" : 0
"requires_cap" : 0
},
"blacklist" : {
"_name" : "blacklist",
"help" : "Blacklists a hostmask from joining a channel. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#blacklist",
"level" : 10
"requires_cap" : 1
},
"cap" : {
"_name" : "cap",
"help" : "",
"requires_cap" : 0
},
"chanadd" : {
"_name" : "chanadd",
"help" : "Permanently adds a channel to PBot's list of channels to auto-join and manage. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#chanadd",
"level" : 40
"requires_cap" : 1
},
"chanlist" : {
"_name" : "chanlist",
"help" : "Lists all added channels and their metadata keys and values. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#chanlist",
"level" : 10
"requires_cap" : 1
},
"chanrem" : {
"_name" : "chanrem",
"help" : "Removes a channel from PBot's list of channels to auto-join and manage. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#chanrem",
"level" : 40
"requires_cap" : 1
},
"chanset" : {
"_name" : "chanset",
"help" : "Sets a channel's metadata. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#chanset and https://github.com/pragma-/pbot/blob/master/doc/Admin.md#channel-metadata-list",
"level" : 40
"requires_cap" : 1
},
"chanunset" : {
"_name" : "chanunset",
"help" : "Deletes a channel's metadata key. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#chanunset",
"level" : 40
"requires_cap" : 1
},
"checkban" : {
"_name" : "checkban",
"help" : "Shows the reason a mask was banned and how long the ban lasts. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#checkban",
"level" : 0
"requires_cap" : 0
},
"checkmute" : {
"_name" : "checkmute",
"help" : "Shows the reason a mask was muted and how long the mute lasts. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#checkmute",
"level" : 0
"requires_cap" : 0
},
"cmdset" : {
"_name" : "cmdset",
"help" : "Sets or shows command metadata. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#cmdset",
"level" : 90
"requires_cap" : 1
},
"cmdunset" : {
"_name" : "cmdunset",
"help" : "Deletes a channel metadata key. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#cmdunset",
"level" : 90
"requires_cap" : 1
},
"connect4" : {
"_name" : "connect4",
"help" : "The classic Connect-4 board game. See https://github.com/pragma-/pbot/blob/master/doc/Connect4.md",
"level" : 0
"requires_cap" : 0
},
"count" : {
"_name" : "count",
"help" : "Shows how many factoids and what percentage of the database <nick> has submitted. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#count",
"level" : 0
"requires_cap" : 0
},
"counteradd" : {
"_name" : "counteradd",
"help" : "Adds a new counter. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#add",
"level" : 0
"requires_cap" : 0
},
"counterdel" : {
"_name" : "counterdel",
"help" : "Deletes a counter. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#del",
"level" : 0
"requires_cap" : 0
},
"counterlist" : {
"_name" : "counterlist",
"help" : "Lists counters. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#list",
"level" : 0
"requires_cap" : 0
},
"counterreset" : {
"_name" : "counterreset",
"help" : "Resets a counter. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#reset",
"level" : 0
"requires_cap" : 0
},
"countershow" : {
"_name" : "countershow",
"help" : "Shows a counter's data. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#show",
"level" : 0
"requires_cap" : 0
},
"countertrigger" : {
"_name" : "countertrigger",
"help" : "Manages counter triggers. See https://github.com/pragma-/pbot/blob/master/doc/Counter.md#trigger",
"level" : 10
"requires_cap" : 1
},
"date" : {
"_name" : "date",
"help" : "Shows date and time for a timezone. Accepts Linux timezone locations. You can set `!my timezone ...` to remember your timezone.",
"level" : 0
"requires_cap" : 0
},
"delq" : {
"_name" : "delq",
"help" : "Deletes a quote from the quotegrabs database. See https://github.com/pragma-/pbot/blob/master/doc/Quotegrabs.md#delq",
"level" : 0
"requires_cap" : 0
},
"deop" : {
"_name" : "deop",
"help" : "Removes OP status from users. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#deop",
"level" : 10
"requires_cap" : 1
},
"devoice" : {
"_name" : "devoice",
"help" : "Removes VOICE status from users. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#devoice",
"level" : 10
"requires_cap" : 1
},
"die" : {
"_name" : "die",
"help" : "Tells PBot to disconnect and exit. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#die",
"level" : 90
"requires_cap" : 1
},
"dumpbans" : {
"_name" : "dumpbans",
"help" : "Displays PBot's internal banlist data structure. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#dumpbans",
"level" : 60
"requires_cap" : 1
},
"eval" : {
"_name" : "eval",
"help" : "Evaluates Perl code within PBot's context. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#eval",
"level" : 99
"requires_cap" : 1
},
"export" : {
"_name" : "export",
"help" : "Exports specified list to HTML file. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#export",
"level" : 90
"requires_cap" : 1
},
"fact" : {
"_name" : "fact",
"help" : "Displays or invokes a factoid belonging to a specific channel. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#fact",
"level" : 0
"requires_cap" : 0
},
"factadd" : {
"_name" : "factadd",
"help" : "Creates a new factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factadd",
"level" : 0
"requires_cap" : 0
},
"factalias" : {
"_name" : "factalias",
"help" : "Creates a factoid that acts as an alias for a command. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factalias",
"level" : 0
"requires_cap" : 0
},
"factchange" : {
"_name" : "factchange",
"help" : "Changes a factoid using a regular expression. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factchange",
"level" : 0
"requires_cap" : 0
},
"factfind" : {
"_name" : "factfind",
"help" : "Searches the database for a factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factfind",
"level" : 0
"requires_cap" : 0
},
"factinfo" : {
"_name" : "factinfo",
"help" : "Displays information about a factoid, such as who submitted it and when. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factinfo",
"level" : 0
"requires_cap" : 0
},
"factlog" : {
"_name" : "factlog",
"help" : "Displays a factoid's changelog history. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factlog",
"level" : 0
"requires_cap" : 0
},
"factmove" : {
"_name" : "factmove",
"help" : "Renames a factoid or moves a factoid to a different channel. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factmove",
"level" : 0
"requires_cap" : 0
},
"factredo" : {
"_name" : "factredo",
"help" : "Reverts a factoid to a newer revision. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factredo",
"level" : 0
"requires_cap" : 0
},
"factrem" : {
"_name" : "factrem",
"help" : "Deletes a factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factrem",
"level" : 0
"requires_cap" : 0
},
"factset" : {
"_name" : "factset",
"help" : "Displays or sets factoid metadata, such as owner, rate-limit, etc. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factset and https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factoid-metadata-list",
"level" : 0
"requires_cap" : 0
},
"factshow" : {
"_name" : "factshow",
"help" : "Displays a factoid's literal value without invoking the factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factshow",
"level" : 0
"requires_cap" : 0
},
"factundo" : {
"_name" : "factundo",
"help" : "Reverts a factoid to an older revision. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factundo",
"level" : 0
"requires_cap" : 0
},
"factunset" : {
"_name" : "factunset",
"help" : "Unsets a factoid metadata key. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factunset and https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factoid-metadata-list",
"level" : 0
"requires_cap" : 0
},
"forget" : {
"_name" : "forget",
"help" : "Deletes a factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#forget",
"level" : 0
"requires_cap" : 0
},
"func" : {
"_name" : "func",
"help" : "Invokes built-in functions. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#func",
"level" : 0
"requires_cap" : 0
},
"getq" : {
"_name" : "getq",
"help" : "Retrieves and displays a specific quote from the quotegrabs database. See https://github.com/pragma-/pbot/blob/master/doc/Quotegrabs.md#getq",
"level" : 0
"requires_cap" : 0
},
"google" : {
"_name" : "google",
"help" : "Displays Google search results for a query. See https://github.com/pragma-/pbot/blob/master/doc/Modules.md#google",
"level" : 0
"requires_cap" : 0
},
"grab" : {
"_name" : "grab",
"help" : "Grabs a message someone says, and adds it to the quotegrabs database. See https://github.com/pragma-/pbot/blob/master/doc/Quotegrabs.md#grab",
"level" : 0
"requires_cap" : 0
},
"help" : {
"_name" : "help",
"help" : "Displays the `help` metadata for commands and factoids.",
"level" : "0"
"requires_cap" : 0
},
"histogram" : {
"_name" : "histogram",
"help" : "Displays a histogram of the top factoid submitters. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#histogram",
"level" : 0
"requires_cap" : 0
},
"ignore" : {
"_name" : "ignore",
"help" : "Ignores a user. If you omit [channel] PBot will ignore the user in all channels, including private messages. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#ignore",
"level" : 10
"requires_cap" : 1
},
"in" : {
"_name" : "in",
"help" : "Performs a command in a specific channel. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#in",
"level" : 0
"requires_cap" : 1
},
"invite" : {
"_name" : "invite",
"help" : "Invites a user to a channel. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#invite",
"level" : 10
"requires_cap" : 1
},
"join" : {
"_name" : "join",
"help" : "Temporarily joins a channel without adding it to PBot's list of channels to manage/auto-join. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#join",
"level" : 40
"requires_cap" : 1
},
"kick" : {
"_name" : "kick",
"help" : "Removes a user from the channel. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#kick",
"level" : "10"
"requires_cap" : 1
},
"lagcheck" : {
"_name" : "lagcheck",
"help" : "Displays history of PING times. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#lagcheck",
"level" : 0
"requires_cap" : 0
},
"learn" : {
"_name" : "learn",
"help" : "Creates a new factoid. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#factadd",
"level" : 0
"requires_cap" : 0
},
"list" : {
"_name" : "list",
"help" : "Lists various collections, such as channels or admins. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#list",
"level" : 0
"help" : "Lists various collections, such as channels or admins. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#list"
},
"load" : {
"_name" : "load",
"help" : "This command loads a module as a PBot command. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#load",
"level" : 90
"requires_cap" : 1
},
"login" : {
"_name" : "login",
"help" : "Logs into a PBot admin account. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#login",
"level" : 0
"requires_cap" : 0
},
"logout" : {
"_name" : "logout",
"help" : "Logs out of a PBot admin account. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#logout",
"level" : 0
"requires_cap" : 0
},
"mod" : {
"_name" : "mod",
"help" : "Provides restricted moderation abilities to voiced users. They can kick/ban/etc only users that are not admins, whitelisted, voiced or opped.",
"requires_cap" : 0
},
"mode" : {
"_name" : "mode",
"help" : "Sets or unsets channel or user modes. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#mode",
"level" : 40
"requires_cap" : 1
},
"mute" : {
"_name" : "mute",
"help" : "Mutes a user. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#banmute",
"level" : 10
"requires_cap" : 1
},
"my" : {
"_name" : "my",
"help" : "Lets users view and manipulate their own user metadata. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#my and https://github.com/pragma-/pbot/blob/master/doc/Admin.md#user-metadata-list",
"level" : 0
"requires_cap" : 0
},
"nicklist" : {
"_name" : "nicklist",
"help" : "Dumps the internal nicklist structure. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#nicklist",
"level" : 0
"requires_cap" : 0
},
"op" : {
"_name" : "op",
"help" : "Gives channel operator status to users. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#op",
"level" : 10
"requires_cap" : "1"
},
"part" : {
"_name" : "part",
"help" : "Departs a channel, without removing it from PBot's list of channels to manage/auto-join. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#part",
"level" : 40
"requires_cap" : 1
},
"plug" : {
"_name" : "plug",
"help" : "Loads a plugin into PBot. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#plug",
"level" : 90
"requires_cap" : 1
},
"pluglist" : {
"_name" : "pluglist",
"help" : "Lists all currently loaded plugins. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#pluglist",
"level" : 0
"requires_cap" : 0
},
"rebuildaliases" : {
"_name" : "rebuildaliases",
"help" : "Rebuilds the aka link table. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#rebuildaliases",
"level" : 90
"requires_cap" : 1
},
"recall" : {
"_name" : "recall",
"help" : "Recalls previous chat history for a channel. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#recall",
"level" : 0
"requires_cap" : 0
},
"refresh" : {
"_name" : "refresh",
"help" : "Refreshes and reloads PBot core modules and plugins. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#refresh",
"level" : 90
"requires_cap" : 0
},
"regchange" : {
"_name" : "regchange",
"help" : "Changes the value of a registry item using a regular expression. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regchange",
"level" : 60
"requires_cap" : 1
},
"regex" : {
"_name" : "regex",
"help" : "Manages regular expression commands. See https://github.com/pragma-/pbot/blob/master/doc/Commands.md#regex",
"level" : 999
"requires_cap" : 1
},
"regfind" : {
"_name" : "regfind",
"help" : "Searches the registry for keywords or values. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regfind",
"level" : 0
"requires_cap" : 0
},
"regset" : {
"_name" : "regset",
"help" : "Creates a new registry item or updates an existing item. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regset",
"level" : 60
"requires_cap" : 1
},
"regsetmeta" : {
"_name" : "regsetmeta",
"help" : "Sets or displays the metadata for a specific registry key. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regsetmeta and https://github.com/pragma-/pbot/blob/master/doc/Registry.md#metadata-list",
"level" : 60
"requires_cap" : 1
},
"regshow" : {
"_name" : "regshow",
"help" : "Displays the type and value of a registry item. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regshow",
"level" : 0
"requires_cap" : 0
},
"regunset" : {
"_name" : "regunset",
"help" : "Deletes a registry item from a specific section/channel. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regunset",
"level" : 60
"requires_cap" : 1
},
"regunsetmeta" : {
"_name" : "regunsetmeta",
"help" : "Deletes a metadata key from a registry item. See https://github.com/pragma-/pbot/blob/master/doc/Registry.md#regsetmeta and https://github.com/pragma-/pbot/blob/master/doc/Registry.md#metadata",
"level" : 60
"requires_cap" : 1
},
"reload" : {
"_name" : "reload",
"help" : "Reloads a data or configuration file. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#reload",
"level" : 90
"requires_cap" : 1
},
"remindme" : {
"_name" : "remindme",
"help" : "Manages user reminders. See https://github.com/pragma-/pbot/blob/master/doc/Remindme.md",
"level" : 0
"requires_cap" : 0
},
"replug" : {
"_name" : "replug",
"help" : "Reloads a plugin into PBot. The plugin is first unloaded and then it is loaded again. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#replug",
"level" : 90
"requires_cap" : 1
},
"rq" : {
"_name" : "rq",
"help" : "Retrieves and displays a random quote from the quotegrabs database. See https://github.com/pragma-/pbot/blob/master/doc/Quotegrabs.md#rq",
"level" : 0
"requires_cap" : 0
},
"sl" : {
"_name" : "sl",
"help" : "Sends a raw IRC command to the server. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#sl",
"level" : 90
"requires_cap" : 1
},
"spinach" : {
"_name" : "spinach",
"help" : "Manages and interacts with the Spinach trivia game. See https://github.com/pragma-/pbot/blob/master/doc/Spinach.md",
"level" : 0
"requires_cap" : 0
},
"top20" : {
"_name" : "top20",
"help" : "Displays the top 20 most popular factoids. See https://github.com/pragma-/pbot/blob/master/doc/Factoids.md#top20",
"level" : 0
"requires_cap" : 0
},
"unban" : {
"_name" : "unban",
"help" : "Unbans a user. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#unbanunmute",
"level" : 10
"requires_cap" : 1
},
"unbanme" : {
"_name" : "unbanme",
"help" : "Removes a join-flood ban. See https://github.com/pragma-/pbot/blob/master/doc/Abuse.md#unbanme",
"level" : 0
"requires_cap" : 0
},
"unignore" : {
"_name" : "unignore",
"help" : "Unignores a user. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#unignore",
"level" : 10
"requires_cap" : 1
},
"unload" : {
"_name" : "unload",
"help" : "Unloads a module and removes its associated command. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#unload",
"level" : 90
"requires_cap" : 1
},
"unmute" : {
"_name" : "unmute",
"help" : "Unmutes a user. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#unbanunmute",
"level" : 10
"requires_cap" : 1
},
"unplug" : {
"_name" : "unplug",
"help" : "Unloads a plugin from PBot. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#unplug",
"level" : 90
"requires_cap" : 1
},
"uptime" : {
"_name" : "uptime",
"help" : "",
"level" : 0
"help" : "Displays the date and time this instance of PBot was started and how long it has been running.",
"requires_cap" : 0
},
"useradd" : {
"_name" : "useradd",
"help" : "Adds a new user to PBot. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#useradd",
"level" : 60
"requires_cap" : 1
},
"userdel" : {
"_name" : "userdel",
"help" : "Removes an user from PBot. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#userdel",
"level" : 60
"requires_cap" : 1
},
"userset" : {
"_name" : "userset",
"help" : "Sets metadata for an user account. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#userset and https://github.com/pragma-/pbot/blob/master/doc/Admin.md#user-metadata-list",
"level" : 60
"requires_cap" : 1
},
"userunset" : {
"_name" : "userunset",
"help" : "Deletes a metadata key from an user account. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#userunset",
"level" : 60
"requires_cap" : 1
},
"version" : {
"_name" : "version",
"help" : "",
"level" : 0
"requires_cap" : 0
},
"voice" : {
"_name" : "voice",
"help" : "Sets mode +v on users. Accepts wildcards. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#voice",
"level" : 10
"requires_cap" : 1
},
"weather" : {
"_name" : "weather",
"help" : "Fetches and displays weather data. You may set `!my location ...` to remember your location.",
"level" : 0
"requires_cap" : 0
},
"whitelist" : {
"_name" : "whitelist",
"help" : "Whitelists a hostmask to be exempted from ban evasions or anti-flood enforcement. See https://github.com/pragma-/pbot/blob/master/doc/Admin.md#whitelist",
"level" : 10
"requires_cap" : 1
},
"wttr" : {
"_name" : "wttr",
"help" : "",
"requires_cap" : "0"
}
}

29
data/factoids vendored
View File

@ -419,7 +419,7 @@
"created_on" : "1519931258.36575",
"edited_by" : "iamgarp!~chaos@unaffiliated/pragmatic-chaos",
"edited_on" : "1555805847.25419",
"effective-level" : "100",
"cap-override" : "botowner",
"enabled" : "1",
"last_referenced_in" : "##spinach",
"last_referenced_on" : 1578910468.98602,
@ -10231,10 +10231,10 @@
},
"kickme" : {
"_name" : "kickme",
"action" : "/kick $nick",
"action_with_args" : "/kick $nick $args",
"action" : "/call kick $nick",
"action_with_args" : "/call kick $nick $args",
"created_on" : "1524347954.63458",
"effective-level" : "10",
"cap-override" : "can-kick",
"enabled" : "1",
"last_referenced_in" : "##c-offtopic",
"last_referenced_on" : 1572992043.13307,
@ -14908,7 +14908,7 @@
"_name" : "removeme",
"action" : "/call sl remove $channel $nick :Bye!",
"created_on" : 1567373781.37961,
"effective-level" : "90",
"cap-override" : "botowner",
"enabled" : "1",
"last_referenced_in" : "##c-offtopic",
"last_referenced_on" : 1567721282.13253,
@ -15257,7 +15257,7 @@
"created_on" : "1254874530",
"edited_by" : "pragma-!~chaos@unaffiliated/pragmatic-chaos",
"edited_on" : "1504601046.70364",
"effective-level" : "20",
"cap-override" : "can-kick",
"enabled" : "1",
"last_referenced_in" : "##c-offtopic",
"last_referenced_on" : 1579041706.76328,
@ -15270,7 +15270,7 @@
},
"roulette_outcome" : {
"_name" : "roulette_outcome",
"action" : "\"/kick $nick *BANG!*\" \"/say $args: *click*\" \"/say $args: *click*\"",
"action" : "\"/call kick $nick *BANG!*\" \"/say $args: *click*\" \"/say $args: *click*\"",
"created_on" : "1254874748",
"edited_by" : "pragma-!~chaos@unaffiliated/pragmatic-chaos",
"edited_on" : "1492056512.90395",
@ -21511,21 +21511,6 @@
"ref_user" : "k!~krok@unaffiliated/krok",
"type" : "text"
},
"wang" : {
"_name" : "wang",
"action" : "/msg mnrmnaugh wtf",
"created_on" : "1519278998.50208",
"effective-level" : "60",
"enabled" : "1",
"last_referenced_in" : "#pbot2",
"last_referenced_on" : "1519979002.921",
"locked" : "1",
"owner" : "pragma-!~chaos@unaffiliated/pragmatic-chaos",
"rate_limit" : "15",
"ref_count" : "8",
"ref_user" : "mnrmnaugh!~mnrmnaugh@unaffiliated/mnrmnaugh",
"type" : "text"
},
"warning-labels" : {
"_name" : "warning-labels",
"action" : "http://www.myconfinedspace.com/2007/03/23/internet-warning-labels/",