mirror of
https://github.com/pragma-/pbot.git
synced 2025-01-22 10:04:36 +01:00
Finished replacing admin-levels with user-capabilities [FIN commit 2 of 2]; misc clean-ups
This commit is contained in:
parent
2ca9634c66
commit
6267cc04d2
@ -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(@_) });
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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.";
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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";
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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(@_) });
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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";
|
||||
}
|
||||
|
||||
|
@ -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; });
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
49
PBot/PBot.pm
49
PBot/PBot.pm
@ -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 = "; ";
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;;
|
||||
|
||||
|
@ -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} = {};
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
|
145
PBot/Users.pm
145
PBot/Users.pm
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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}};
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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.";
|
||||
}
|
||||
|
@ -10,7 +10,6 @@ use warnings;
|
||||
use strict;
|
||||
|
||||
use feature 'unicode_strings';
|
||||
|
||||
use Carp ();
|
||||
|
||||
use Time::Duration qw/duration/;
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
230
data/commands
vendored
@ -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
29
data/factoids
vendored
@ -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/",
|
||||
|
Loading…
Reference in New Issue
Block a user