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

Refactor commands to begin with cmd_ and take a $context object

Move all command subroutines closer to top of source file
Do not send WHO to non-chanop channels
Minor misc bugfixes and improvements
This commit is contained in:
Pragmatic Software 2020-05-04 13:21:35 -07:00
parent 5df95b45e9
commit 976bfcb5e7
39 changed files with 2927 additions and 2863 deletions

View File

@ -64,8 +64,8 @@ sub initialize {
$self->{pbot}->{registry}->add_default('text', 'antiflood', 'debug_checkban', $conf{debug_checkban} // 0);
$self->{pbot}->{commands}->register(sub { $self->unbanme(@_) }, "unbanme", 0);
$self->{pbot}->{commands}->register(sub { $self->ban_exempt(@_) }, "ban-exempt", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unbanme(@_) }, "unbanme", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_ban_exempt(@_) }, "ban-exempt", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-ban-exempt', 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.whoisaccount', sub { $self->on_whoisaccount(@_) });
@ -74,16 +74,8 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('irc.account', sub { $self->on_accountnotify(@_) });
}
sub ban_exempted {
my ($self, $channel, $hostmask) = @_;
$channel = lc $channel;
$hostmask = lc $hostmask;
return 1 if $self->{'ban-exemptions'}->exists($channel, $hostmask);
return 0;
}
sub ban_exempt {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_ban_exempt {
my ($self, $context) = @_;
my $arglist = $context->{arglist};
$self->{pbot}->{interpreter}->lc_args($arglist);
@ -109,7 +101,7 @@ sub ban_exempt {
return "Usage: ban-exempt add <channel> <mask>" if not defined $channel or not defined $mask;
my $data = {
owner => "$nick!$user\@$host",
owner => $context->{hostmask},
created_on => scalar gettimeofday
};
@ -125,6 +117,123 @@ sub ban_exempt {
}
}
sub cmd_unbanme {
my ($self, $context) = @_;
my $unbanned;
my %aliases = $self->{pbot}->{messagehistory}->{database}->get_also_known_as($context->{nick});
foreach my $alias (keys %aliases) {
next if $aliases{$alias}->{type} == $self->{pbot}->{messagehistory}->{database}->{alias_type}->{WEAK};
next if $aliases{$alias}->{nickchange} == 1;
my ($anick, $auser, $ahost) = $alias =~ m/([^!]+)!([^@]+)@(.*)/;
my $banmask = $self->address_to_mask($ahost);
my $mask = "*!$auser\@$banmask\$##stop_join_flood";
my @channels = $self->{pbot}->{messagehistory}->{database}->get_channels($aliases{$alias}->{id});
foreach my $channel (@channels) {
next if exists $unbanned->{$channel} and exists $unbanned->{$channel}->{$mask};
next if not $self->{pbot}->{banlist}->{banlist}->exists($channel . '-floodbans', $mask);
my $message_account = $self->{pbot}->{messagehistory}->{database}->get_message_account($anick, $auser, $ahost);
my @nickserv_accounts = $self->{pbot}->{messagehistory}->{database}->get_nickserv_accounts($message_account);
push @nickserv_accounts, undef;
foreach my $nickserv_account (@nickserv_accounts) {
my $baninfos = $self->{pbot}->{banlist}->get_baninfo($channel, "$anick!$auser\@$ahost", $nickserv_account);
if (defined $baninfos) {
foreach my $baninfo (@$baninfos) {
my $u = $self->{pbot}->{users}->loggedin($baninfo->{channel}, $context->{hostmask});
my $whitelisted = $self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted');
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{mask}) || $whitelisted) {
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost banned as $baninfo->{mask} in $baninfo->{channel}, but allowed through whitelist\n");
} else {
if ($channel eq lc $baninfo->{channel}) {
my $mode = $baninfo->{type} eq 'b' ? "banned" : "quieted";
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost $mode as $baninfo->{mask} in $baninfo->{channel} by $baninfo->{owner}, unbanme rejected\n");
return "/msg $context->{nick} You have been $mode as $baninfo->{mask} by $baninfo->{owner}, unbanme will not work until it is removed.";
}
}
}
}
}
my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'unbanmes');
if ($channel_data->{unbanmes} <= 2) {
$channel_data->{unbanmes}++;
$self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
}
$unbanned->{$channel}->{$mask} = $channel_data->{unbanmes};
}
}
if (keys %$unbanned) {
my $channels = '';
my $sep = '';
my $channels_warning = '';
my $sep_warning = '';
my $channels_disabled = '';
my $sep_disabled = '';
foreach my $channel (keys %$unbanned) {
foreach my $mask (keys %{$unbanned->{$channel}}) {
if ($self->{pbot}->{channels}->is_active_op("${channel}-floodbans")) {
if ($unbanned->{$channel}->{$mask} <= 2) {
$self->{pbot}->{banlist}->unban_user($channel . '-floodbans', 'b', $mask);
$channels .= "$sep$channel";
$sep = ", ";
}
if ($unbanned->{$channel}->{$mask} == 1) {
$channels_warning .= "$sep_warning$channel";
$sep_warning = ", ";
} else {
$channels_disabled .= "$sep_disabled$channel";
$sep_disabled = ", ";
}
}
}
}
$self->{pbot}->{banlist}->flush_unban_queue();
$channels =~ s/(.*), /$1 and /;
$channels_warning =~ s/(.*), /$1 and /;
$channels_disabled =~ s/(.*), /$1 and /;
my $warning = '';
if (length $channels_warning) {
$warning =
" You may use `unbanme` one more time today for $channels_warning; please ensure that your client or connection issues are resolved.";
}
if (length $channels_disabled) {
$warning .=
" You may not use `unbanme` again for several hours for $channels_disabled.";
}
if (length $channels) { return "/msg $context->{nick} You have been unbanned from $channels.$warning"; }
else { return "/msg $context->{nick} $warning"; }
} else {
return "/msg $context->{nick} There is no join-flooding ban set for you.";
}
}
sub ban_exempted {
my ($self, $channel, $hostmask) = @_;
$channel = lc $channel;
$hostmask = lc $hostmask;
return 1 if $self->{'ban-exemptions'}->exists($channel, $hostmask);
return 0;
}
sub update_join_watch {
my ($self, $account, $channel, $text, $mode) = @_;
@ -562,115 +671,6 @@ sub check_flood {
$self->{channels}->{$channel}->{last_spoken_nick} = $nick if $mode == $self->{pbot}->{messagehistory}->{MSG_CHAT};
}
sub unbanme {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $unbanned;
my %aliases = $self->{pbot}->{messagehistory}->{database}->get_also_known_as($nick);
foreach my $alias (keys %aliases) {
next if $aliases{$alias}->{type} == $self->{pbot}->{messagehistory}->{database}->{alias_type}->{WEAK};
next if $aliases{$alias}->{nickchange} == 1;
my ($anick, $auser, $ahost) = $alias =~ m/([^!]+)!([^@]+)@(.*)/;
my $banmask = $self->address_to_mask($ahost);
my $mask = "*!$auser\@$banmask\$##stop_join_flood";
my @channels = $self->{pbot}->{messagehistory}->{database}->get_channels($aliases{$alias}->{id});
foreach my $channel (@channels) {
next if exists $unbanned->{$channel} and exists $unbanned->{$channel}->{$mask};
next if not $self->{pbot}->{banlist}->{banlist}->exists($channel . '-floodbans', $mask);
my $message_account = $self->{pbot}->{messagehistory}->{database}->get_message_account($anick, $auser, $ahost);
my @nickserv_accounts = $self->{pbot}->{messagehistory}->{database}->get_nickserv_accounts($message_account);
push @nickserv_accounts, undef;
foreach my $nickserv_account (@nickserv_accounts) {
my $baninfos = $self->{pbot}->{banlist}->get_baninfo($channel, "$anick!$auser\@$ahost", $nickserv_account);
if (defined $baninfos) {
foreach my $baninfo (@$baninfos) {
my $u = $self->{pbot}->{users}->loggedin($baninfo->{channel}, "$nick!$user\@$host");
my $whitelisted = $self->{pbot}->{capabilities}->userhas($u, 'is-whitelisted');
if ($self->ban_exempted($baninfo->{channel}, $baninfo->{mask}) || $whitelisted) {
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost banned as $baninfo->{mask} in $baninfo->{channel}, but allowed through whitelist\n");
} else {
if ($channel eq lc $baninfo->{channel}) {
my $mode = $baninfo->{type} eq 'b' ? "banned" : "quieted";
$self->{pbot}->{logger}->log("anti-flood: [unbanme] $anick!$auser\@$ahost $mode as $baninfo->{mask} in $baninfo->{channel} by $baninfo->{owner}, unbanme rejected\n");
return "/msg $nick You have been $mode as $baninfo->{mask} by $baninfo->{owner}, unbanme will not work until it is removed.";
}
}
}
}
}
my $channel_data = $self->{pbot}->{messagehistory}->{database}->get_channel_data($message_account, $channel, 'unbanmes');
if ($channel_data->{unbanmes} <= 2) {
$channel_data->{unbanmes}++;
$self->{pbot}->{messagehistory}->{database}->update_channel_data($message_account, $channel, $channel_data);
}
$unbanned->{$channel}->{$mask} = $channel_data->{unbanmes};
}
}
if (keys %$unbanned) {
my $channels = '';
my $sep = '';
my $channels_warning = '';
my $sep_warning = '';
my $channels_disabled = '';
my $sep_disabled = '';
foreach my $channel (keys %$unbanned) {
foreach my $mask (keys %{$unbanned->{$channel}}) {
if ($self->{pbot}->{channels}->is_active_op("${channel}-floodbans")) {
if ($unbanned->{$channel}->{$mask} <= 2) {
$self->{pbot}->{banlist}->unban_user($channel . '-floodbans', 'b', $mask);
$channels .= "$sep$channel";
$sep = ", ";
}
if ($unbanned->{$channel}->{$mask} == 1) {
$channels_warning .= "$sep_warning$channel";
$sep_warning = ", ";
} else {
$channels_disabled .= "$sep_disabled$channel";
$sep_disabled = ", ";
}
}
}
}
$self->{pbot}->{banlist}->flush_unban_queue();
$channels =~ s/(.*), /$1 and /;
$channels_warning =~ s/(.*), /$1 and /;
$channels_disabled =~ s/(.*), /$1 and /;
my $warning = '';
if (length $channels_warning) {
$warning =
" You may use `unbanme` one more time today for $channels_warning; please ensure that your client or connection issues are resolved.";
}
if (length $channels_disabled) {
$warning .=
" You may not use `unbanme` again for several hours for $channels_disabled.";
}
if (length $channels) { return "/msg $nick You have been unbanned from $channels.$warning"; }
else { return "/msg $nick $warning"; }
} else {
return "/msg $nick There is no join-flooding ban set for you.";
}
}
sub address_to_mask {
my ($self, $address) = @_;
my $banmask;

View File

@ -26,36 +26,12 @@ sub initialize {
$self->{keywords}->load;
$self->{pbot}->{registry}->add_default('text', 'antispam', 'enforce', $conf{enforce_antispam} // 1);
$self->{pbot}->{commands}->register(sub { $self->antispam_cmd(@_) }, "antispam", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_antispam(@_) }, "antispam", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-antispam', 1);
}
sub is_spam {
my ($self, $namespace, $text, $all_namespaces) = @_;
my $lc_namespace = lc $namespace;
return 0 if not $self->{pbot}->{registry}->get_value('antispam', 'enforce');
return 0 if $self->{pbot}->{registry}->get_value($namespace, 'dont_enforce_antispam');
my $ret = eval {
foreach my $space ($self->{keywords}->get_keys) {
if ($all_namespaces or $lc_namespace eq $space) {
foreach my $keyword ($self->{keywords}->get_keys($space)) { return 1 if $text =~ m/$keyword/i; }
}
}
return 0;
};
if ($@) {
$self->{pbot}->{logger}->log("Error in is_spam: $@");
return 0;
}
$self->{pbot}->{logger}->log("AntiSpam: spam detected!\n") if $ret;
return $ret;
}
sub antispam_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_antispam {
my ($self, $context) = @_;
my $arglist = $context->{arglist};
@ -126,7 +102,7 @@ sub antispam_cmd {
my ($namespace, $keyword) = $self->{pbot}->{interpreter}->split_args($arglist, 2);
return "Usage: antispam add <namespace> <regex>" if not defined $namespace or not defined $keyword;
my $data = {
owner => "$nick!$user\@$host",
owner => $context->{hostmask},
created_on => scalar gettimeofday
};
$self->{keywords}->add($namespace, $keyword, $data);
@ -141,4 +117,28 @@ sub antispam_cmd {
}
}
sub is_spam {
my ($self, $namespace, $text, $all_namespaces) = @_;
my $lc_namespace = lc $namespace;
return 0 if not $self->{pbot}->{registry}->get_value('antispam', 'enforce');
return 0 if $self->{pbot}->{registry}->get_value($namespace, 'dont_enforce_antispam');
my $ret = eval {
foreach my $space ($self->{keywords}->get_keys) {
if ($all_namespaces or $lc_namespace eq $space) {
foreach my $keyword ($self->{keywords}->get_keys($space)) { return 1 if $text =~ m/$keyword/i; }
}
}
return 0;
};
if ($@) {
$self->{pbot}->{logger}->log("Error in is_spam: $@");
return 0;
}
$self->{pbot}->{logger}->log("AntiSpam: spam detected!\n") if $ret;
return $ret;
}
1;

View File

@ -30,9 +30,9 @@ sub initialize {
$self->{pbot}->{registry}->add_default('text', 'banlist', 'mute_timeout', '604800');
$self->{pbot}->{registry}->add_default('text', 'banlist', 'debug', '0');
$self->{pbot}->{commands}->register(sub { $self->banlist_cmd(@_) }, "banlist", 0);
$self->{pbot}->{commands}->register(sub { $self->checkban_cmd(@_) }, "checkban", 0);
$self->{pbot}->{commands}->register(sub { $self->checkmute_cmd(@_) }, "checkmute", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_banlist(@_) }, "banlist", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_checkban(@_) }, "checkban", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_checkmute(@_) }, "checkmute", 0);
$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(@_) });
@ -64,20 +64,20 @@ sub initialize {
$self->{pbot}->{timer}->register(sub { $self->flush_unban_queue }, 30, 'Unban Queue');
}
sub banlist_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_banlist {
my ($self, $context) = @_;
if (not length $arguments) {
if (not length $context->{arguments}) {
return "Usage: banlist <channel>";
}
my $result = "Ban list for $arguments:\n";
my $result = "Ban list for $context->{arguments}:\n";
if ($self->{banlist}->exists($arguments)) {
my $count = $self->{banlist}->get_keys($arguments);
if ($self->{banlist}->exists($context->{arguments})) {
my $count = $self->{banlist}->get_keys($context->{arguments});
$result .= "$count ban" . ($count == 1 ? '' : 's') . ":\n";
foreach my $mask ($self->{banlist}->get_keys($arguments)) {
my $data = $self->{banlist}->get_data($arguments, $mask);
foreach my $mask ($self->{banlist}->get_keys($context->{arguments})) {
my $data = $self->{banlist}->get_data($context->{arguments}, $mask);
$result .= " $mask banned ";
if (defined $data->{timestamp}) {
@ -98,11 +98,11 @@ sub banlist_cmd {
$result .= "bans: none;\n";
}
if ($self->{quietlist}->exists($arguments)) {
my $count = $self->{quietlist}->get_keys($arguments);
if ($self->{quietlist}->exists($context->{arguments})) {
my $count = $self->{quietlist}->get_keys($context->{arguments});
$result .= "$count mute" . ($count == 1 ? '' : 's') . ":\n";
foreach my $mask ($self->{quietlist}->get_keys($arguments)) {
my $data = $self->{quietlist}->get_data($arguments, $mask);
foreach my $mask ($self->{quietlist}->get_keys($context->{arguments})) {
my $data = $self->{quietlist}->get_data($context->{arguments}, $mask);
$result .= " $mask muted ";
if (defined $data->{timestamp}) {
@ -127,23 +127,23 @@ sub banlist_cmd {
return $result;
}
sub checkban_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_checkban {
my ($self, $context) = @_;
my ($target, $channel) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: checkban <mask> [channel]" if not defined $target;
$channel = $from if not defined $channel;
$channel = $context->{from} if not defined $channel;
return "Please specify a channel." if $channel !~ /^#/;
return $self->checkban($channel, 'b', $target);
}
sub checkmute_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_checkmute {
my ($self, $context) = @_;
my ($target, $channel) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: checkmute <mask> [channel]" if not defined $target;
$channel = $from if not defined $channel;
$channel = $context->{from} if not defined $channel;
return "Please specify a channel." if $channel !~ /^#/;
return $self->checkban($channel, 'q', $target);

View File

@ -22,11 +22,65 @@ sub initialize {
my ($self, %conf) = @_;
$self->{filename} = $conf{filename};
$self->{blacklist} = {};
$self->{pbot}->{commands}->register(sub { $self->blacklist(@_) }, "blacklist", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_blacklist(@_) }, "blacklist", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-blacklist', 1);
$self->load_blacklist;
}
sub cmd_blacklist {
my ($self, $context) = @_;
my $arglist = $context->{arglist};
$self->{pbot}->{interpreter}->lc_args($arglist);
my $command = $self->{pbot}->{interpreter}->shift_arg($arglist);
return "Usage: blacklist <command>, where commands are: list/show, add, remove" if not defined $command;
given ($command) {
when ($_ eq "list" or $_ eq "show") {
my $text = "Blacklist:\n";
my $entries = 0;
foreach my $channel (sort keys %{$self->{blacklist}}) {
if ($channel eq '.*') { $text .= " all channels:\n"; }
else { $text .= " $channel:\n"; }
foreach my $mask (sort keys %{$self->{blacklist}->{$channel}}) {
$text .= " $mask,\n";
$entries++;
}
}
$text .= "none" if $entries == 0;
return "/msg $context->{nick} $text";
}
when ("add") {
my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2);
return "Usage: blacklist add <hostmask regex> [channel]" if not defined $mask;
$channel = '.*' if not defined $channel;
$self->{pbot}->{logger}->log("$context->{hostmask} added [$mask] to blacklist for channel [$channel]\n");
$self->add($channel, $mask);
return "/say $mask blacklisted in channel $channel";
}
when ("remove") {
my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2);
return "Usage: blacklist remove <hostmask regex> [channel]" if not defined $mask;
$channel = '.*' if not defined $channel;
if (exists $self->{blacklist}->{$channel} and not exists $self->{blacklist}->{$channel}->{$mask}) {
$self->{pbot}->{logger}->log("$context->{hostmask} attempt to remove nonexistent [$mask][$channel] from blacklist\n");
return "/say $mask not found in blacklist for channel $channel (use `blacklist list` to display blacklist)";
}
$self->remove($channel, $mask);
$self->{pbot}->{logger}->log("$context->{hostmask} removed [$mask] from blacklist for channel [$channel]\n");
return "/say $mask removed from blacklist for channel $channel";
}
default { return "Unknown command '$command'; commands are: list/show, add, remove"; }
}
}
sub add {
my ($self, $channel, $hostmask) = @_;
$self->{blacklist}->{lc $channel}->{lc $hostmask} = 1;
@ -143,58 +197,4 @@ sub check_blacklist {
return 0;
}
sub blacklist {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my $arglist = $context->{arglist};
$self->{pbot}->{interpreter}->lc_args($arglist);
my $command = $self->{pbot}->{interpreter}->shift_arg($arglist);
return "Usage: blacklist <command>, where commands are: list/show, add, remove" if not defined $command;
given ($command) {
when ($_ eq "list" or $_ eq "show") {
my $text = "Blacklist:\n";
my $entries = 0;
foreach my $channel (sort keys %{$self->{blacklist}}) {
if ($channel eq '.*') { $text .= " all channels:\n"; }
else { $text .= " $channel:\n"; }
foreach my $mask (sort keys %{$self->{blacklist}->{$channel}}) {
$text .= " $mask,\n";
$entries++;
}
}
$text .= "none" if $entries == 0;
return "/msg $nick $text";
}
when ("add") {
my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2);
return "Usage: blacklist add <hostmask regex> [channel]" if not defined $mask;
$channel = '.*' if not defined $channel;
$self->{pbot}->{logger}->log("$nick!$user\@$host added [$mask] to blacklist for channel [$channel]\n");
$self->add($channel, $mask);
return "/say $mask blacklisted in channel $channel";
}
when ("remove") {
my ($mask, $channel) = $self->{pbot}->{interpreter}->split_args($arglist, 2);
return "Usage: blacklist remove <hostmask regex> [channel]" if not defined $mask;
$channel = '.*' if not defined $channel;
if (exists $self->{blacklist}->{$channel} and not exists $self->{blacklist}->{$channel}->{$mask}) {
$self->{pbot}->{logger}->log("$nick attempt to remove nonexistent [$mask][$channel] from blacklist\n");
return "/say $mask not found in blacklist for channel $channel (use `blacklist list` to display blacklist)";
}
$self->remove($channel, $mask);
$self->{pbot}->{logger}->log("$nick!$user\@$host removed [$mask] from blacklist for channel [$channel]\n");
return "/say $mask removed from blacklist for channel $channel";
}
default { return "Unknown command '$command'; commands are: list/show, add, remove"; }
}
}
1;

View File

@ -33,6 +33,117 @@ sub initialize {
$self->add('is-whitelisted', undef, 1);
}
sub cmd_cap {
my ($self, $context) = @_;
my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
my $result;
given ($command) {
when ('list') {
my $cap = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return $self->list($cap);
}
when ('whohas') {
my $cap = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return "Usage: cap whohas <capability>; Lists all users who have <capability>" if not defined $cap;
return "No such capability $cap." if not $self->exists($cap);
my $result = "Users with capability $cap: ";
my $users = $self->{pbot}->{users}->{users};
my @matches;
foreach my $name (sort $users->get_keys) {
my $u = $users->get_data($name);
push @matches, $users->get_key_name($name) if $self->userhas($u, $cap);
}
if (@matches) {
$result .= join(', ', @matches);
} else {
$result .= 'nobody';
}
return $result;
}
when ('userhas') {
my ($name, $cap) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap userhas <username> [capability]; Lists capabilities belonging to <user>" if not defined $name;
$cap = lc $cap if defined $cap;
my $u = $self->{pbot}->{users}->{users}->get_data($name);
if (not defined $u) {
return "No such user $name.";
}
$name = $self->{pbot}->{users}->{users}->get_key_name($name);
if (defined $cap) {
return "Try again. No such capability $cap." if not $self->exists($cap);
if ($self->userhas($u, $cap)) { return "Yes. User $name has capability $cap."; }
else { return "No. User $name does not have capability $cap."; }
} else {
my $result = "User $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 = $self->{caps}->get_keys;
if ($count > 0) { push @groups, "$key ($count cap" . ($count == 1 ? '' : 's') . ")"; }
else { push @single, $key; }
}
if (@groups or @single) { $result .= join ', ', @groups, @single; }
else { $result = "User $name has no capabilities."; }
return $result;
}
}
when ('group') {
my ($cap, $subcaps) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap group <existing or new capability> <existing capabilities...>" if not defined $cap or not defined $subcaps;
my $u = $self->{pbot}->{users}->loggedin($context->{from}, $context->{hostmask});
return "You must be logged into your user account to group capabilities together." if not defined $u;
return "You must have the can-group-capabilities capability to group capabilities together." if not $self->userhas($u, 'can-group-capabilities');
my @caps = split /\s+|,/, $subcaps;
foreach my $c (@caps) {
return "No such capability $c." if not $self->exists($c);
return "You cannot group a capability with itself." if lc $cap eq lc $c;
$self->add($cap, $c);
}
if (@caps > 1) { return "Capabilities " . join(', ', @caps) . " added to the $cap capability group."; }
else { return "Capability $subcaps added to the $cap capability group."; }
}
when ('ungroup') {
my ($cap, $subcaps) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap ungroup <existing capability group> <grouped capabilities...>" if not defined $cap or not defined $subcaps;
return "No such capability $cap." if not $self->exists($cap);
my $u = $self->{pbot}->{users}->loggedin($context->{from}, $context->{hostmask});
return "You must be logged into your user account to remove capabilities from groups." if not defined $u;
return "You must have the can-ungroup-capabilities capability to remove capabilities from groups." if not $self->userhas($u, 'can-ungroup-capabilities');
my @caps = split /\s+|,/, $subcaps;
foreach my $c (@caps) {
return "No such capability $c." if not $self->exists($c);
return "Capability $c does not belong to the $cap capability group." if not $self->has($cap, $c);
$self->remove($cap, $c);
}
if (@caps > 1) { return "Capabilities " . join(', ', @caps) . " removed from the $cap capability group."; }
else { return "Capability $subcaps removed from the $cap capability group."; }
}
default {
$result =
"Usage: cap list [capability] | cap group <existing or new capability group> <existing capabilities...> | cap ungroup <existing capability group> <grouped capabilities...> | cap userhas <user> [capability] | cap whohas <capability>";
}
}
return $result;
}
sub has {
my ($self, $cap, $subcap, $depth) = @_;
my $cap_data = $self->{caps}->get_data($cap);
@ -147,115 +258,4 @@ sub list {
return $result;
}
sub capcmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
my $result;
given ($command) {
when ('list') {
my $cap = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return $self->list($cap);
}
when ('whohas') {
my $cap = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return "Usage: cap whohas <capability>; Lists all users who have <capability>" if not defined $cap;
return "No such capability $cap." if not $self->exists($cap);
my $result = "Users with capability $cap: ";
my $users = $self->{pbot}->{users}->{users};
my @matches;
foreach my $name (sort $users->get_keys) {
my $u = $users->get_data($name);
push @matches, $users->get_key_name($name) if $self->userhas($u, $cap);
}
if (@matches) {
$result .= join(', ', @matches);
} else {
$result .= 'nobody';
}
return $result;
}
when ('userhas') {
my ($name, $cap) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap userhas <username> [capability]; Lists capabilities belonging to <user>" if not defined $name;
$cap = lc $cap if defined $cap;
my $u = $self->{pbot}->{users}->{users}->get_data($name);
if (not defined $u) {
return "No such user $name.";
}
$name = $self->{pbot}->{users}->{users}->get_key_name($name);
if (defined $cap) {
return "Try again. No such capability $cap." if not $self->exists($cap);
if ($self->userhas($u, $cap)) { return "Yes. User $name has capability $cap."; }
else { return "No. User $name does not have capability $cap."; }
} else {
my $result = "User $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 = $self->{caps}->get_keys;
if ($count > 0) { push @groups, "$key ($count cap" . ($count == 1 ? '' : 's') . ")"; }
else { push @single, $key; }
}
if (@groups or @single) { $result .= join ', ', @groups, @single; }
else { $result = "User $name has no capabilities."; }
return $result;
}
}
when ('group') {
my ($cap, $subcaps) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap group <existing or new capability> <existing capabilities...>" if not defined $cap or not defined $subcaps;
my $u = $self->{pbot}->{users}->loggedin($from, "$nick!$user\@$host");
return "You must be logged into your user account to group capabilities together." if not defined $u;
return "You must have the can-group-capabilities capability to group capabilities together." if not $self->userhas($u, 'can-group-capabilities');
my @caps = split /\s+|,/, $subcaps;
foreach my $c (@caps) {
return "No such capability $c." if not $self->exists($c);
return "You cannot group a capability with itself." if lc $cap eq lc $c;
$self->add($cap, $c);
}
if (@caps > 1) { return "Capabilities " . join(', ', @caps) . " added to the $cap capability group."; }
else { return "Capability $subcaps added to the $cap capability group."; }
}
when ('ungroup') {
my ($cap, $subcaps) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cap ungroup <existing capability group> <grouped capabilities...>" if not defined $cap or not defined $subcaps;
return "No such capability $cap." if not $self->exists($cap);
my $u = $self->{pbot}->{users}->loggedin($from, "$nick!$user\@$host");
return "You must be logged into your user account to remove capabilities from groups." if not defined $u;
return "You must have the can-ungroup-capabilities capability to remove capabilities from groups." if not $self->userhas($u, 'can-ungroup-capabilities');
my @caps = split /\s+|,/, $subcaps;
foreach my $c (@caps) {
return "No such capability $c." if not $self->exists($c);
return "Capability $c does not belong to the $cap capability group." if not $self->has($cap, $c);
$self->remove($cap, $c);
}
if (@caps > 1) { return "Capabilities " . join(', ', @caps) . " removed from the $cap capability group."; }
else { return "Capability $subcaps removed from the $cap capability group."; }
}
default {
$result =
"Usage: cap list [capability] | cap group <existing or new capability group> <existing capabilities...> | cap ungroup <existing capability group> <grouped capabilities...> | cap userhas <user> [capability] | cap whohas <capability>";
}
}
return $result;
}
1;

View File

@ -21,17 +21,17 @@ sub initialize {
my ($self, %conf) = @_;
# register commands
$self->{pbot}->{commands}->register(sub { $self->ban_user(@_) }, "ban", 1);
$self->{pbot}->{commands}->register(sub { $self->unban_user(@_) }, "unban", 1);
$self->{pbot}->{commands}->register(sub { $self->mute_user(@_) }, "mute", 1);
$self->{pbot}->{commands}->register(sub { $self->unmute_user(@_) }, "unmute", 1);
$self->{pbot}->{commands}->register(sub { $self->kick_user(@_) }, "kick", 1);
$self->{pbot}->{commands}->register(sub { $self->op_user(@_) }, "op", 1);
$self->{pbot}->{commands}->register(sub { $self->deop_user(@_) }, "deop", 1);
$self->{pbot}->{commands}->register(sub { $self->voice_user(@_) }, "voice", 1);
$self->{pbot}->{commands}->register(sub { $self->devoice_user(@_) }, "devoice", 1);
$self->{pbot}->{commands}->register(sub { $self->mode(@_) }, "mode", 1);
$self->{pbot}->{commands}->register(sub { $self->invite(@_) }, "invite", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_op(@_) }, "op", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_deop(@_) }, "deop", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_voice(@_) }, "voice", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_devoice(@_) }, "devoice", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_ban(@_) }, "ban", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unban(@_) }, "unban", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_mute(@_) }, "mute", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unmute(@_) }, "unmute", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_kick(@_) }, "kick", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_mode(@_) }, "mode", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_invite(@_) }, "invite", 1);
# allow commands to set modes
$self->{pbot}->{capabilities}->add('can-ban', 'can-mode-b', 1);
@ -131,35 +131,36 @@ sub on_nosuchnick {
return 1;
}
sub invite {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_invite {
my ($self, $context) = @_;
my ($channel, $target);
if ($from !~ m/^#/) {
if ($context->{from} !~ m/^#/) {
# from /msg
my $usage = "Usage from /msg: invite <channel> [nick]; if you omit [nick] then you will be invited";
return $usage if not length $arguments;
return $usage if not length $context->{arguments};
($channel, $target) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "$channel is not a channel; $usage" if $channel !~ m/^#/;
$target = $nick if not defined $target;
$target = $context->{nick} if not defined $target;
} else {
# in channel
return "Usage: invite [channel] <nick>" if not length $arguments;
return "Usage: invite [channel] <nick>" if not length $context->{arguments};
# add current channel as default channel
$self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $from) if $context->{arglist}[0] !~ m/^#/;
$self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $context->{from}) if $context->{arglist}[0] !~ m/^#/;
($channel, $target) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
}
$self->{invites}->{lc $channel}->{lc $target} = $nick;
$self->{invites}->{lc $channel}->{lc $target} = $context->{nick};
$self->{pbot}->{chanops}->add_op_command($channel, "sl invite $target $channel");
$self->{pbot}->{chanops}->gain_ops($channel);
return ""; # responses handled by events
}
sub generic_mode_user {
my ($self, $mode_flag, $mode_name, $channel, $nick, $context) = @_;
sub generic_mode {
my ($self, $mode_flag, $mode_name, $context) = @_;
my $result = '';
my $channel = $context->{from};
my ($flag, $mode_char) = $mode_flag =~ m/(.)(.)/;
@ -174,7 +175,7 @@ sub generic_mode_user {
if (not $self->{pbot}->{chanops}->can_gain_ops($channel)) { return "I am not configured as an OP for $channel. See `chanset` command for more information."; }
# add $nick to $args if no argument
if (not $self->{pbot}->{interpreter}->arglist_size($context->{arglist})) { $self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $nick); }
if (not $self->{pbot}->{interpreter}->arglist_size($context->{arglist})) { $self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $context->{nick}); }
my $max_modes = $self->{pbot}->{ircd}->{MODES} // 1;
my $mode = $flag;
@ -190,7 +191,7 @@ sub generic_mode_user {
if ($i >= $max_modes) {
my $args = "$channel $mode $list";
$context->{arglist} = $self->{pbot}->{interpreter}->make_args($args);
$result = $self->mode($channel, $nick, $context->{user}, $context->{host}, $args, $context);
$result = $self->mode($channel, $context->{nick}, $context->{user}, $context->{host}, $args, $context);
$mode = $flag;
$list = '';
$i = 0;
@ -201,42 +202,46 @@ sub generic_mode_user {
if ($i) {
my $args = "$channel $mode $list";
$context->{arguments} = $args;
$context->{arglist} = $self->{pbot}->{interpreter}->make_args($args);
$result = $self->mode($channel, $nick, $context->{user}, $context->{host}, $args, $context);
$result = $self->cmd_mode($context);
}
return $result;
}
sub op_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return $self->generic_mode_user('+o', 'op', $from, $nick, $context);
sub cmd_op {
my ($self, $context) = @_;
return $self->generic_mode('+o', 'op', $context);
}
sub deop_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return $self->generic_mode_user('-o', 'deop', $from, $nick, $context);
sub cmd_deop {
my ($self, $context) = @_;
return $self->generic_mode('-o', 'deop', $context);
}
sub voice_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return $self->generic_mode_user('+v', 'voice', $from, $nick, $context);
sub cmd_voice {
my ($self, $context) = @_;
return $self->generic_mode('+v', 'voice', $context);
}
sub devoice_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return $self->generic_mode_user('-v', 'devoice', $from, $nick, $context);
sub cmd_devoice {
my ($self, $context) = @_;
return $self->generic_mode('-v', 'devoice', $context);
}
sub mode {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_mode {
my ($self, $context) = @_;
if (not length $arguments) { return "Usage: mode [channel] <arguments>"; }
if (not length $context->{arguments}) { return "Usage: mode [channel] <arguments>"; }
# add current channel as default channel
if ($context->{arglist}[0] !~ m/^#/) {
if ($from =~ m/^#/) { $self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $from); }
else { return "Usage from private message: mode <channel> <arguments>"; }
if ($context->{from} =~ m/^#/) {
$self->{pbot}->{interpreter}->unshift_arg($context->{arglist}, $context->{from});
} else {
return "Usage from private message: mode <channel> <arguments>";
}
}
my ($channel, $modes, $args) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
@ -248,7 +253,7 @@ sub mode {
my ($new_modes, $new_targets) = ("", "");
my $max_modes = $self->{pbot}->{ircd}->{MODES} // 1;
my $u = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->loggedin($channel, $context->{hostmask});
while ($modes =~ m/(.)/g) {
my $mode = $1;
@ -260,7 +265,7 @@ sub mode {
}
if (not $self->{pbot}->{capabilities}->userhas($u, "can-mode-$mode")) {
return "/msg $nick Your user account does not have the can-mode-$mode capability required to set this mode.";
return "/msg $context->{nick} Your user account does not have the can-mode-$mode capability required to set this mode.";
}
my $target = $targets[$arg++] // "";
@ -271,16 +276,18 @@ sub mode {
$q_target =~ s/\\\*/.*/g;
$channel = lc $channel;
if (not exists $self->{pbot}->{nicklist}->{nicklist}->{$channel}) { return "I have no nicklist for channel $channel; cannot use wildcard."; }
if (not exists $self->{pbot}->{nicklist}->{nicklist}->{$channel}) {
return "I have no nicklist for channel $channel; cannot use wildcard.";
}
my $u = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->loggedin($channel, $context->{hostmask});
if ($mode eq 'v') {
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-voice-wildcard')) {
return "/msg $nick Using wildcards with `mode v` requires the can-voice-wildcard capability, which your user account does not have.";
return "/msg $context->{nick} Using wildcards with `mode v` requires the can-voice-wildcard capability, which your user account does not have.";
}
} else {
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-op-wildcard')) {
return "/msg $nick Using wildcards with `mode o` requires the can-op-wildcard capability, which your user account does not have.";
return "/msg $context->{nick} Using wildcards with `mode o` requires the can-op-wildcard capability, which your user account does not have.";
}
}
@ -331,18 +338,18 @@ sub mode {
$self->{pbot}->{chanops}->gain_ops($channel);
if ($from !~ m/^#/) { return "Done."; }
else { return ""; }
if ($context->{from} !~ m/^#/) { return "Done."; }
else { return ""; }
}
sub ban_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_ban {
my ($self, $context) = @_;
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
$channel = '' if not defined $channel;
$length = '' if not defined $length;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
@ -350,10 +357,12 @@ sub ban_user {
if ($channel !~ m/^#/) {
$length = "$channel $length";
$length = undef if $length eq ' ';
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from;
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from if not defined $channel or not length $channel;
if (not defined $channel or not length $channel) {
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
if (not defined $target) { return "Usage: ban <mask> [channel [timeout (default: 24 hours)]]"; }
@ -391,7 +400,7 @@ sub ban_user {
$result .= "$sep$mask has $d remaining on their $channel ban";
$sep = '; ';
} else {
$self->{pbot}->{banlist}->ban_user_timed($channel, 'b', $mask, $length, "$nick!$user\@$host", undef, $immediately);
$self->{pbot}->{banlist}->ban_user_timed($channel, 'b', $mask, $length, $context->{hostmask}, undef, $immediately);
$duration = $length > 0 ? duration $length : 'all eternity';
if ($immediately) {
$result .= "$sep$mask banned in $channel for $duration";
@ -408,15 +417,14 @@ sub ban_user {
$self->{pbot}->{banlist}->flush_ban_queue;
}
$result = "/msg $nick $result" if $result !~ m/remaining on their/;
$result = "/msg $context->{nick} $result" if $result !~ m/remaining on their/;
return $result;
}
sub unban_user {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_unban {
my ($self, $context) = @_;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
@ -431,8 +439,11 @@ sub unban_user {
if (not defined $target) { return "Usage: unban <nick/mask> [channel [false value to use unban queue]]"; }
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from if not defined $channel;
$immediately = 1 if not defined $immediately;
if (not defined $channel) {
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
$immediately = 1 if not defined $immediately;
return "Usage for /msg: unban <nick/mask> <channel> [false value to use unban queue]" if $channel !~ /^#/;
@ -441,9 +452,9 @@ sub unban_user {
foreach my $t (@targets) {
if ($t eq '*') {
my $u = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->loggedin($channel, $context->{hostmask});
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-clear-bans')) {
return "/msg $nick Clearing the channel bans requires the can-clear-bans capability, which your user account does not have.";
return "/msg $context->{nick} Clearing the channel bans requires the can-clear-bans capability, which your user account does not have.";
}
$channel = lc $channel;
if ($self->{pbot}->{banlist}->{banlist}->exists($channel)) {
@ -459,29 +470,31 @@ sub unban_user {
}
$self->{pbot}->{banlist}->flush_unban_queue if not $immediately;
return "/msg $nick $target has been unbanned from $channel.";
return "/msg $context->{nick} $target has been unbanned from $channel.";
}
sub mute_user {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_mute {
my ($self, $context) = @_;
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
$channel = '' if not defined $channel;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
if (not length $channel and $from !~ m/^#/) { return "Usage from private message: mute <mask> <channel> [timeout (default: 24 hours)]"; }
if (not length $channel and $context->{from} !~ m/^#/) {
return "Usage from private message: mute <mask> <channel> [timeout (default: 24 hours)]";
}
if ($channel !~ m/^#/) {
$length = $channel . ' ' . (defined $length ? $length : '');
$length = undef if $length eq ' ';
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from;
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from};
}
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from if not defined $channel;
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from} if not defined $channel;
if ($channel !~ m/^#/) { return "Please specify a channel."; }
@ -520,7 +533,7 @@ sub mute_user {
$result .= "$sep$mask has $d remaining on their $channel mute";
$sep = '; ';
} else {
$self->{pbot}->{banlist}->ban_user_timed($channel, 'q', $t, $length, "$nick!$user\@$host", undef, $immediately);
$self->{pbot}->{banlist}->ban_user_timed($channel, 'q', $t, $length, $context->{hostmask}, undef, $immediately);
$duration = $length > 0 ? duration $length : 'all eternity';
if ($immediately) {
$result .= "$sep$mask muted in $channel for $duration";
@ -537,15 +550,14 @@ sub mute_user {
$self->{pbot}->{banlist}->flush_ban_queue;
}
$result = "/msg $nick $result" if $result !~ m/remaining on their/;
$result = "/msg $context->{nick} $result" if $result !~ m/remaining on their/;
return $result;
}
sub unmute_user {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_unmute {
my ($self, $context) = @_;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
@ -560,8 +572,8 @@ sub unmute_user {
if (not defined $target) { return "Usage: unmute <nick/mask> [channel [false value to use unban queue]]"; }
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from if not defined $channel;
$immediately = 1 if not defined $immediately;
$channel = exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from} if not defined $channel;
$immediately = 1 if not defined $immediately;
return "Usage for /msg: unmute <nick/mask> <channel> [false value to use unban queue]" if $channel !~ /^#/;
@ -570,9 +582,9 @@ sub unmute_user {
foreach my $t (@targets) {
if ($t eq '*') {
my $u = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->loggedin($channel, $context->{hostmask});
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-clear-mutes')) {
return "/msg $nick Clearing the channel mutes requires the can-clear-mutes capability, which your user account does not have.";
return "/msg $context->{nick} Clearing the channel mutes requires the can-clear-mutes capability, which your user account does not have.";
}
$channel = lc $channel;
if ($self->{pbot}->{banlist}->{quietlist}->exists($channel)) {
@ -588,28 +600,28 @@ sub unmute_user {
}
$self->{pbot}->{banlist}->flush_unban_queue if not $immediately;
return "/msg $nick $target has been unmuted in $channel.";
return "/msg $context->{nick} $target has been unmuted in $channel.";
}
sub kick_user {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_kick {
my ($self, $context) = @_;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
my ($channel, $victim, $reason);
my $arguments = $context->{arguments};
if (not $from =~ /^#/) {
if (not $context->{from} =~ /^#/) {
# used in private message
if (not $arguments =~ s/^(^#\S+) (\S+)\s*//) { return "Usage from private message: kick <channel> <nick> [reason]"; }
($channel, $victim) = ($1, $2);
} else {
# used in channel
if ($arguments =~ s/^(#\S+)\s+(\S+)\s*//) { ($channel, $victim) = ($1, $2); }
elsif ($arguments =~ s/^(\S+)\s*//) { ($victim, $channel) = ($1, exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $from); }
elsif ($arguments =~ s/^(\S+)\s*//) { ($victim, $channel) = ($1, exists $context->{admin_channel_override} ? $context->{admin_channel_override} : $context->{from}); }
else { return "Usage: kick [channel] <nick> [reason]"; }
}
@ -641,9 +653,9 @@ sub kick_user {
if (not exists $self->{pbot}->{nicklist}->{nicklist}->{$channel}) { return "I have no nicklist for channel $channel; cannot use wildcard."; }
my $u = $self->{pbot}->{users}->loggedin($channel, "$nick!$user\@$host");
my $u = $self->{pbot}->{users}->loggedin($channel, $context->{hostmask});
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-kick-wildcard')) {
return "/msg $nick Using wildcards with `kick` requires the can-kick-wildcard capability, which your user account does not have.";
return "/msg $context->{nick} Using wildcards with `kick` requires the can-kick-wildcard capability, which your user account does not have.";
}
foreach my $nl (keys %{$self->{pbot}->{nicklist}->{nicklist}->{$channel}}) {

View File

@ -18,55 +18,55 @@ sub initialize {
$self->{channels} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Channels', filename => $conf{filename});
$self->{channels}->load;
$self->{pbot}->{commands}->register(sub { $self->join_cmd(@_) }, "join", 1);
$self->{pbot}->{commands}->register(sub { $self->part_cmd(@_) }, "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);
$self->{pbot}->{commands}->register(sub { $self->cmd_join(@_) }, "join", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_part(@_) }, "part", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_set(@_) }, "chanset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unset(@_) }, "chanunset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_add(@_) }, "chanadd", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_remove(@_) }, "chanrem", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_list(@_) }, "chanlist", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-join', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-part', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-chanlist', 1);
}
sub join_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
foreach my $channel (split /[\s+,]/, $arguments) {
$self->{pbot}->{logger}->log("$nick!$user\@$host made me join $channel\n");
sub cmd_join {
my ($self, $context) = @_;
foreach my $channel (split /[\s+,]/, $context->{arguments}) {
$self->{pbot}->{logger}->log("$context->{hostmask} made me join $channel\n");
$self->join($channel);
}
return "/msg $nick Joining $arguments";
return "/msg $context->{nick} Joining $context->{arguments}";
}
sub part_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
$arguments = $from if not $arguments;
foreach my $channel (split /[\s+,]/, $arguments) {
$self->{pbot}->{logger}->log("$nick!$user\@$host made me part $channel\n");
sub cmd_part {
my ($self, $context) = @_;
$context->{arguments} = $context->{from} if not $context->{arguments};
foreach my $channel (split /[\s+,]/, $context->{arguments}) {
$self->{pbot}->{logger}->log("$context->{hostmask} made me part $channel\n");
$self->part($channel);
}
return "/msg $nick Parting $arguments";
return "/msg $context->{nick} Parting $context->{arguments}";
}
sub set {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_set {
my ($self, $context) = @_;
my ($channel, $key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
return "Usage: chanset <channel> [key [value]]" if not defined $channel;
return $self->{channels}->set($channel, $key, $value);
}
sub unset {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_unset {
my ($self, $context) = @_;
my ($channel, $key) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: chanunset <channel> <key>" if not defined $channel or not defined $key;
return $self->{channels}->unset($channel, $key);
}
sub add {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
return "Usage: chanadd <channel>" if not defined $arguments or not length $arguments;
sub cmd_add {
my ($self, $context) = @_;
return "Usage: chanadd <channel>" if not length $context->{arguments};
my $data = {
enabled => 1,
@ -74,25 +74,25 @@ sub add {
permop => 0
};
return $self->{channels}->add($arguments, $data);
return $self->{channels}->add($context->{arguments}, $data);
}
sub remove {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
return "Usage: chanrem <channel>" if not defined $arguments or not length $arguments;
sub cmd_remove {
my ($self, $context) = @_;
return "Usage: chanrem <channel>" if not length $context->{arguments};
# clear banlists
$self->{pbot}->{banlist}->remove($arguments);
$self->{pbot}->{quietlist}->remove($arguments);
$self->{pbot}->{timer}->dequeue_event("unban $arguments .*");
$self->{pbot}->{timer}->dequeue_event("unmute $arguments .*");
$self->{pbot}->{banlist}->remove($context->{arguments});
$self->{pbot}->{quietlist}->remove($context->{arguments});
$self->{pbot}->{timer}->dequeue_event("unban $context->{arguments} .*");
$self->{pbot}->{timer}->dequeue_event("unmute $context->{arguments} .*");
# TODO: ignores, etc?
return $self->{channels}->remove($arguments);
return $self->{channels}->remove($context->{arguments});
}
sub list {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_list {
my ($self, $context) = @_;
my $result;
foreach my $channel (sort $self->{channels}->get_keys) {
$result .= $self->{channels}->get_key_name($channel) . ': {';

View File

@ -24,15 +24,123 @@ sub initialize {
$self->{metadata} = PBot::HashObject->new(pbot => $self->{pbot}, name => 'Commands', filename => $conf{filename});
$self->{metadata}->load;
$self->register(sub { $self->cmdset(@_) }, "cmdset", 1);
$self->register(sub { $self->cmdunset(@_) }, "cmdunset", 1);
$self->register(sub { $self->help(@_) }, "help", 0);
$self->register(sub { $self->uptime(@_) }, "uptime", 0);
$self->register(sub { $self->in_channel(@_) }, "in", 1);
$self->register(sub { $self->cmd_set(@_) }, "cmdset", 1);
$self->register(sub { $self->cmd_unset(@_) }, "cmdunset", 1);
$self->register(sub { $self->cmd_help(@_) }, "help", 0);
$self->register(sub { $self->cmd_uptime(@_) }, "uptime", 0);
$self->register(sub { $self->cmd_in_channel(@_) }, "in", 0);
$self->{pbot}->{capabilities}->add('admin', 'can-in', 1);
}
sub cmd_set {
my ($self, $context) = @_;
my ($command, $key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
return "Usage: cmdset <command> [key [value]]" if not defined $command;
return $self->{metadata}->set($command, $key, $value);
}
sub cmd_unset {
my ($self, $context) = @_;
my ($command, $key) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cmdunset <command> <key>" if not defined $command or not defined $key;
return $self->{metadata}->unset($command, $key);
}
sub cmd_help {
my ($self, $context) = @_;
if (not length $context->{arguments}) {
return "For general help, see <https://github.com/pragma-/pbot/tree/master/doc>. For help about a specific command or factoid, use `help <keyword> [channel]`.";
}
my $keyword = lc $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
# check built-in commands first
if ($self->exists($keyword)) {
if ($self->{metadata}->exists($keyword)) {
my $name = $self->{metadata}->get_key_name($keyword);
my $requires_cap = $self->{metadata}->get_data($keyword, 'requires_cap');
my $help = $self->{metadata}->get_data($keyword, 'help');
my $result = "/say $name: ";
$result .= "[Requires can-$keyword] " if $requires_cap;
if (not defined $help or not length $help) { $result .= "I have no help text for this command yet. To add help text, use the command `cmdset $keyword help <text>`."; }
else { $result .= $help; }
return $result;
}
return "$keyword is a built-in command, but I have no help for it yet.";
}
# then factoids
my $channel_arg = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
$channel_arg = $context->{from} if not defined $channel_arg or not length $channel_arg;
$channel_arg = '.*' if $channel_arg !~ m/^#/;
my @factoids = $self->{pbot}->{factoids}->find_factoid($channel_arg, $keyword, exact_trigger => 1);
if (not @factoids or not $factoids[0]) { return "I don't know anything about $keyword."; }
my ($channel, $trigger);
if (@factoids > 1) {
if (not grep { $_->[0] eq $channel_arg } @factoids) {
return
"/say $keyword found in multiple channels: "
. (join ', ', sort map { $_->[0] eq '.*' ? 'global' : $_->[0] } @factoids)
. "; use `help $keyword <channel>` to disambiguate.";
} else {
foreach my $factoid (@factoids) {
if ($factoid->[0] eq $channel_arg) {
($channel, $trigger) = ($factoid->[0], $factoid->[1]);
last;
}
}
}
} else {
($channel, $trigger) = ($factoids[0]->[0], $factoids[0]->[1]);
}
my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_key_name($channel);
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_key_name($channel, $trigger);
$channel_name = 'global channel' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $result = "/say ";
$result .= "[$channel_name] " if $channel ne $context->{from} and $channel ne '.*';
$result .= "$trigger_name: ";
my $help = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'help');
if (not defined $help or not length $help) { return "/say $trigger_name is a factoid for $channel_name, but I have no help text for it yet. To add help text, use the command `factset $trigger_name help <text>`."; }
$result .= $help;
return $result;
}
sub cmd_uptime {
my ($self, $context) = @_;
return localtime($self->{pbot}->{startup_timestamp}) . " [" . duration(time - $self->{pbot}->{startup_timestamp}) . "]";
}
sub cmd_in_channel {
my ($self, $context) = @_;
my $usage = "Usage: in <channel> <command>";
return $usage if not length $context->{arguments};
my ($channel, $command) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2, 0, 1);
return $usage if not defined $channel or not defined $command;
if (not $self->{pbot}->{nicklist}->is_present($channel, $context->{nick})) {
return "You must be present in $channel to do this.";
}
$context->{from} = $channel;
$context->{command} = $command;
return $self->{pbot}->{interpreter}->interpret($context);
}
sub register {
my ($self, $subref, $name, $requires_cap) = @_;
Carp::croak("Missing parameters to Commands::register") if not defined $subref or not defined $name;
@ -65,6 +173,18 @@ sub exists {
return 0;
}
sub set_meta {
my ($self, $command, $key, $value, $save) = @_;
return undef if not $self->{metadata}->exists($command);
$self->{metadata}->set($command, $key, $value, !$save);
return 1;
}
sub get_meta {
my ($self, $command, $key) = @_;
return $self->{metadata}->get_data($command, $key);
}
sub interpreter {
my ($self, $context) = @_;
my $result;
@ -100,7 +220,7 @@ sub interpreter {
} else {
if (not defined $user) {
my ($found_chan, $found_mask) = $self->{pbot}->{users}->find_user_account($cmd_channel, "$context->{nick}!$context->{user}\@$context->{host}", 1);
if (not defined $found_chan) { return "/msg $context->{nick} You must have a user account to use $keyword."; }
if (not defined $found_chan) { return "/msg $context->{nick} You must have a user account to use $keyword. You may use the `my` command to create a personal user account. See `help my`."; }
else { return "/msg $context->{nick} You must have a user account in $cmd_channel to use $keyword. (You have an account in $found_chan.)"; }
} elsif (not $user->{loggedin}) {
return "/msg $context->{nick} You must be logged into your user account to use $keyword.";
@ -122,12 +242,12 @@ sub interpreter {
my $timeout = $self->get_meta($keyword, 'process-timeout') // $self->{pbot}->{registry}->get_value('processmanager', 'default_timeout');
$self->{pbot}->{process_manager}->execute_process(
$context,
sub { $context->{result} = $ref->{subref}->($context->{from}, $context->{nick}, $context->{user}, $context->{host}, $context->{arguments}, $context) },
sub { $context->{result} = $ref->{subref}->($context) },
$timeout
);
return "";
} else {
my $result = $ref->{subref}->($context->{from}, $context->{nick}, $context->{user}, $context->{host}, $context->{arguments}, $context);
my $result = $ref->{subref}->($context);
return undef if $context->{referenced} and $result =~ m/(?:usage:|no results)/i;
return $result;
}
@ -136,122 +256,4 @@ sub interpreter {
return undef;
}
sub set_meta {
my ($self, $command, $key, $value, $save) = @_;
return undef if not $self->{metadata}->exists($command);
$self->{metadata}->set($command, $key, $value, !$save);
return 1;
}
sub get_meta {
my ($self, $command, $key) = @_;
return $self->{metadata}->get_data($command, $key);
}
sub cmdset {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($command, $key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
return "Usage: cmdset <command> [key [value]]" if not defined $command;
return $self->{metadata}->set($command, $key, $value);
}
sub cmdunset {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($command, $key) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: cmdunset <command> <key>" if not defined $command or not defined $key;
return $self->{metadata}->unset($command, $key);
}
sub help {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
if (not length $arguments) {
return "For general help, see <https://github.com/pragma-/pbot/tree/master/doc>. For help about a specific command or factoid, use `help <keyword> [channel]`.";
}
my $keyword = lc $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
# check built-in commands first
if ($self->exists($keyword)) {
if ($self->{metadata}->exists($keyword)) {
my $name = $self->{metadata}->get_key_name($keyword);
my $requires_cap = $self->{metadata}->get_data($keyword, 'requires_cap');
my $help = $self->{metadata}->get_data($keyword, 'help');
my $result = "/say $name: ";
$result .= "[Requires can-$keyword] " if $requires_cap;
if (not defined $help or not length $help) { $result .= "I have no help text for this command yet. To add help text, use the command `cmdset $keyword help <text>`."; }
else { $result .= $help; }
return $result;
}
return "$keyword is a built-in command, but I have no help for it yet.";
}
# then factoids
my $channel_arg = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
$channel_arg = $from if not defined $channel_arg or not length $channel_arg;
$channel_arg = '.*' if $channel_arg !~ m/^#/;
my @factoids = $self->{pbot}->{factoids}->find_factoid($channel_arg, $keyword, exact_trigger => 1);
if (not @factoids or not $factoids[0]) { return "I don't know anything about $keyword."; }
my ($channel, $trigger);
if (@factoids > 1) {
if (not grep { $_->[0] eq $channel_arg } @factoids) {
return
"/say $keyword found in multiple channels: "
. (join ', ', sort map { $_->[0] eq '.*' ? 'global' : $_->[0] } @factoids)
. "; use `help $keyword <channel>` to disambiguate.";
} else {
foreach my $factoid (@factoids) {
if ($factoid->[0] eq $channel_arg) {
($channel, $trigger) = ($factoid->[0], $factoid->[1]);
last;
}
}
}
} else {
($channel, $trigger) = ($factoids[0]->[0], $factoids[0]->[1]);
}
my $channel_name = $self->{pbot}->{factoids}->{factoids}->get_key_name($channel);
my $trigger_name = $self->{pbot}->{factoids}->{factoids}->get_key_name($channel, $trigger);
$channel_name = 'global channel' if $channel_name eq '.*';
$trigger_name = "\"$trigger_name\"" if $trigger_name =~ / /;
my $result = "/say ";
$result .= "[$channel_name] " if $channel ne $from and $channel ne '.*';
$result .= "$trigger_name: ";
my $help = $self->{pbot}->{factoids}->{factoids}->get_data($channel, $trigger, 'help');
if (not defined $help or not length $help) { return "/say $trigger_name is a factoid for $channel_name, but I have no help text for it yet. To add help text, use the command `factset $trigger_name help <text>`."; }
$result .= $help;
return $result;
}
sub uptime {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return localtime($self->{pbot}->{startup_timestamp}) . " [" . duration(time - $self->{pbot}->{startup_timestamp}) . "]";
}
sub in_channel {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my $usage = "Usage: in <channel> <command>";
return $usage if not $arguments;
my ($channel, $command) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2, 0, 1);
return $usage if not defined $channel or not defined $command;
if (not $self->{pbot}->{nicklist}->is_present($channel, $nick)) { return "You must be present in $channel to do this."; }
$context->{from} = $channel;
$context->{command} = $command;
return $self->{pbot}->{interpreter}->interpret($context);
}
1;

File diff suppressed because it is too large Load Diff

View File

@ -27,7 +27,7 @@ use feature 'unicode_strings';
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->do_func(@_) }, 'func', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_func(@_) }, 'func', 0);
$self->register(
'help',
@ -48,18 +48,8 @@ sub initialize {
);
}
sub register {
my ($self, $func, $data) = @_;
$self->{funcs}->{$func} = $data;
}
sub unregister {
my ($self, $func) = @_;
delete $self->{funcs}->{$func};
}
sub do_func {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_func {
my ($self, $context) = @_;
my $func = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return "Usage: func <keyword> [arguments]; see also: func help" if not defined $func;
return "[No such func '$func']" if not exists $self->{funcs}->{$func};
@ -72,6 +62,16 @@ sub do_func {
return $result;
}
sub register {
my ($self, $func, $data) = @_;
$self->{funcs}->{$func} = $data;
}
sub unregister {
my ($self, $func) = @_;
delete $self->{funcs}->{$func};
}
sub func_help {
my ($self, $func) = @_;
return "func: invoke built-in functions; usage: func <keyword> [arguments]; to list available functions: func list [regex]" if not length $func;

View File

@ -122,7 +122,18 @@ sub on_motd {
sub on_self_join {
my ($self, $event_type, $event) = @_;
my $send_who = $self->{pbot}->{registry}->get_value('general', 'send_who_on_join') // 1;
return 0 if not $self->{pbot}->{registry}->get_value('general', 'send_who_on_join') // 1;
my $send_who = 0;
if ($self->{pbot}->{registry}->get_value('general', 'send_who_chanop_only') // 1) {
if ($self->{pbot}->{channels}->get_meta($event->{channel}, 'chanop')) {
$send_who = 1;
}
} else {
$send_who = 1;
}
$self->send_who($event->{channel}) if $send_who;
return 0;
}

View File

@ -24,8 +24,8 @@ sub initialize {
$self->{ignorelist}->load;
$self->enqueue_ignores;
$self->{pbot}->{commands}->register(sub { $self->ignore_cmd(@_) }, "ignore", 1);
$self->{pbot}->{commands}->register(sub { $self->unignore_cmd(@_) }, "unignore", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_ignore(@_) }, "ignore", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unignore(@_) }, "unignore", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-ignore', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-unignore', 1);
@ -34,6 +34,60 @@ sub initialize {
$self->{pbot}->{capabilities}->add('chanop', 'can-unignore', 1);
}
sub cmd_ignore {
my ($self, $context) = @_;
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
return "Usage: ignore <hostmask> [channel [timeout]] | ignore list" if not defined $target;
if ($target =~ /^list$/i) {
my $text = "Ignored:\n\n";
my $now = time;
my $ignored = 0;
foreach my $channel (sort $self->{ignorelist}->get_keys) {
$text .= $channel eq '.*' ? "global:\n" : "$channel:\n";
my @list;
foreach my $hostmask (sort $self->{ignorelist}->get_keys($channel)) {
my $timeout = $self->{ignorelist}->get_data($channel, $hostmask, 'timeout');
if ($timeout == -1) {
push @list, " $hostmask";
} else {
push @list, " $hostmask (" . (concise duration $timeout - $now) . ')';
}
$ignored++;
}
$text .= join ";\n", @list;
$text .= "\n";
}
return "Ignore list is empty." if not $ignored;
return "/msg $context->{nick} $text";
}
if (not defined $channel) {
$channel = ".*"; # all channels
}
if (not defined $length) {
$length = -1; # permanently
} else {
my $error;
($length, $error) = $self->{pbot}->{parsedate}->parsedate($length);
return $error if defined $error;
}
return $self->add($channel, $target, $length, $context->{hostmask});
}
sub cmd_unignore {
my ($self, $context) = @_;
my ($target, $channel) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (not defined $target) { return "Usage: unignore <hostmask> [channel]"; }
if (not defined $channel) { $channel = '.*'; }
return $self->remove($channel, $target);
}
sub enqueue_ignores {
my ($self) = @_;
my $now = time;
@ -126,61 +180,4 @@ sub is_ignored {
return 0;
}
sub ignore_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($target, $channel, $length) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
return "Usage: ignore <hostmask> [channel [timeout]] | ignore list" if not defined $target;
if ($target =~ /^list$/i) {
my $text = "Ignored:\n\n";
my $now = time;
my $ignored = 0;
foreach my $channel (sort $self->{ignorelist}->get_keys) {
$text .= $channel eq '.*' ? "global:\n" : "$channel:\n";
my @list;
foreach my $hostmask (sort $self->{ignorelist}->get_keys($channel)) {
my $timeout = $self->{ignorelist}->get_data($channel, $hostmask, 'timeout');
if ($timeout == -1) {
push @list, " $hostmask";
} else {
push @list, " $hostmask (" . (concise duration $timeout - $now) . ')';
}
$ignored++;
}
$text .= join ";\n", @list;
$text .= "\n";
}
return "Ignore list is empty." if not $ignored;
return "/msg $nick $text";
}
if (not defined $channel) {
$channel = ".*"; # all channels
}
if (not defined $length) {
$length = -1; # permanently
} else {
my $error;
($length, $error) = $self->{pbot}->{parsedate}->parsedate($length);
return $error if defined $error;
}
return $self->add($channel, $target, $length, "$nick!$user\@$host");
}
sub unignore_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($target, $channel) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (not defined $target) { return "Usage: unignore <hostmask> [channel]"; }
if (not defined $channel) { $channel = '.*'; }
return $self->remove($channel, $target);
}
1;

View File

@ -34,11 +34,11 @@ sub process_line {
my ($from, $nick, $user, $host, $text) = @_;
$from = lc $from if defined $from;
my $context = {from => $from, nick => $nick, user => $user, host => $host, text => $text};
my $context = {from => $from, nick => $nick, user => $user, host => $host, hostmask => "$nick!$user\@$host", text => $text};
my $pbot = $self->{pbot};
my $message_account = $pbot->{messagehistory}->get_message_account($nick, $user, $host);
$pbot->{messagehistory}->add_message($message_account, "$nick!$user\@$host", $from, $text, $pbot->{messagehistory}->{MSG_CHAT});
$pbot->{messagehistory}->add_message($message_account, $context->{hostmask}, $from, $text, $pbot->{messagehistory}->{MSG_CHAT});
$context->{message_account} = $message_account;
my $flood_threshold = $pbot->{registry}->get_value($from, 'chat_flood_threshold');
@ -165,7 +165,7 @@ sub process_line {
}
sub interpret {
my ($self, $context) = @_;
my ($self, $context) = @_;
my ($keyword, $arguments) = ('', '');
my $text;
my $pbot = $self->{pbot};
@ -174,7 +174,7 @@ sub interpret {
$pbot->{logger}->log("=== [$context->{interpret_depth}] Got command: ("
. (defined $context->{from} ? $context->{from} : "undef")
. ") $context->{nick}!$context->{user}\@$context->{host}: $context->{command}\n");
. ") $context->{hostmask}: $context->{command}\n");
$context->{special} = "" unless exists $self->{special};
@ -321,6 +321,7 @@ sub interpret {
$context->{arguments} = $context->{original_arguments};
delete $context->{args_utf8};
}
return $result;
}

View File

@ -43,7 +43,7 @@ sub initialize {
'lag check'
);
$self->{pbot}->{commands}->register(sub { $self->lagcheck(@_) }, "lagcheck", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_lagcheck(@_) }, "lagcheck", 0);
$self->{pbot}->{event_dispatcher}->register_handler('irc.pong', sub { $self->on_pong(@_) });
}
@ -114,8 +114,8 @@ sub lagstring {
return $lag;
}
sub lagcheck {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_lagcheck {
my ($self, $context) = @_;
if (defined $self->{pong_received} and $self->{pong_received} == 0) {
# a ping has been sent (pong_received is not undef) and no pong has been received yet

View File

@ -40,11 +40,11 @@ sub initialize {
$self->{pbot}->{registry}->add_default('text', 'messagehistory', 'max_recall_time', $conf{max_recall_time} // 0);
$self->{pbot}->{registry}->add_default('text', 'messagehistory', 'max_messages', 32);
$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", 1);
$self->{pbot}->{commands}->register(sub { $self->aka_link(@_) }, "akalink", 1);
$self->{pbot}->{commands}->register(sub { $self->aka_unlink(@_) }, "akaunlink", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_list_also_known_as(@_) }, "aka", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_recall_message(@_) }, "recall", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_rebuild_aliases(@_) }, "rebuildaliases", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_aka_link(@_) }, "akalink", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_aka_unlink(@_) }, "akaunlink", 1);
$self->{pbot}->{capabilities}->add('admin', 'can-akalink', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-akaunlink', 1);
@ -52,69 +52,12 @@ sub initialize {
$self->{pbot}->{atexit}->register(sub { $self->{database}->end(); return; });
}
sub get_message_account {
my ($self, $nick, $user, $host) = @_;
return $self->{database}->get_message_account($nick, $user, $host);
}
sub add_message {
my ($self, $account, $mask, $channel, $text, $mode) = @_;
$self->{database}->add_message($account, $mask, $channel, {timestamp => scalar gettimeofday, msg => $text, mode => $mode});
}
sub rebuild_aliases {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
$self->{database}->rebuild_aliases_table;
}
sub aka_link {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my ($id, $alias, $type) = split /\s+/, $arguments;
$type = $self->{database}->{alias_type}->{STRONG} if not defined $type;
if (not $id or not $alias) { return "Usage: link <target id> <alias id> [type]"; }
my $source = $self->{database}->find_most_recent_hostmask($id);
my $target = $self->{database}->find_most_recent_hostmask($alias);
if (not $source) { return "No such id $id found."; }
if (not $target) { return "No such id $alias found."; }
if ($self->{database}->link_alias($id, $alias, $type)) {
return "/say $source " . ($type == $self->{database}->{alias_type}->{WEAK} ? "weakly" : "strongly") . " linked to $target.";
} else {
return "Link failed.";
}
}
sub aka_unlink {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my ($id, $alias) = split /\s+/, $arguments;
if (not $id or not $alias) { return "Usage: unlink <target id> <alias id>"; }
my $source = $self->{database}->find_most_recent_hostmask($id);
my $target = $self->{database}->find_most_recent_hostmask($alias);
if (not $source) { return "No such id $id found."; }
if (not $target) { return "No such id $alias found."; }
if ($self->{database}->unlink_alias($id, $alias)) { return "/say $source unlinked from $target."; }
else { return "Unlink failed."; }
}
sub list_also_known_as {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_list_also_known_as {
my ($self, $context) = @_;
my $usage = "Usage: aka [-hingr] <nick>; -h show hostmasks; -i show ids; -n show nickserv accounts; -g show gecos, -r show relationships";
if (not length $arguments) { return $usage; }
if (not length $context->{arguments}) { return $usage; }
my $getopt_error;
local $SIG{__WARN__} = sub {
@ -125,7 +68,7 @@ sub list_also_known_as {
Getopt::Long::Configure("bundling");
my ($show_hostmasks, $show_gecos, $show_nickserv, $show_id, $show_relationship, $show_weak, $dont_use_aliases_table);
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'h' => \$show_hostmasks,
@ -183,18 +126,19 @@ sub list_also_known_as {
}
}
sub recall_message {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_recall_message {
my ($self, $context) = @_;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
my $usage =
'Usage: recall [nick [history [channel]]] [-c <channel>] [-t <text>] [-b <context before>] [-a <context after>] [-x <filter to nick>] [-n <count>] [-r raw mode] [+ ...]';
my $usage = 'Usage: recall [nick [history [channel]]] [-c <channel>] [-t <text>] [-b <context before>] [-a <context after>] [-x <filter to nick>] [-n <count>] [-r raw mode] [+ ...]';
if (not defined $arguments or not length $arguments) { return $usage; }
my $arguments = $context->{arguments};
if (not length $arguments) { return $usage; }
$arguments = lc $arguments;
@ -273,18 +217,18 @@ sub recall_message {
}
# skip recall command if recalling self without arguments
$recall_history = $nick eq $recall_nick ? 2 : 1 if defined $recall_nick and not defined $recall_history;
$recall_history = $context->{nick} eq $recall_nick ? 2 : 1 if defined $recall_nick and not defined $recall_history;
# set history to most recent message if not specified
$recall_history = '1' if not defined $recall_history;
# set channel to current channel if not specified
$recall_channel = $from if not defined $recall_channel;
$recall_channel = $context->{from} if not defined $recall_channel;
# yet another sanity check for people using it wrong
if ($recall_channel !~ m/^#/) {
$recall_history = "$recall_history $recall_channel";
$recall_channel = $from;
$recall_channel = $context->{from};
}
if (not defined $recall_nick and defined $recall_context) { $recall_nick = $recall_context; }
@ -338,8 +282,8 @@ sub recall_message {
if (not defined $context_account) { return "I don't know anybody named $recall_context."; }
}
if ($from =~ /^#/ and ($recall_count > 5 or $recall_after > 5 or $recall_before > 5)) {
return "Please use `recall` from private message when recalling multiple messages. Just add \"-c $from\" to the command and /msg it to me.";
if ($context->{from} =~ /^#/ and ($recall_count > 5 or $recall_after > 5 or $recall_before > 5)) {
return "Please use `recall` from private message when recalling multiple messages. Just add \"-c $context->{from}\" to the command and /msg it to me.";
}
my $messages = $self->{database}->get_message_context($message, $recall_before, $recall_after, $recall_count, $recall_history, $context_account);
@ -347,7 +291,7 @@ sub recall_message {
my $max_recall_time = $self->{pbot}->{registry}->get_value('messagehistory', 'max_recall_time');
foreach my $msg (@$messages) {
if ($max_recall_time && gettimeofday - $msg->{timestamp} > $max_recall_time && not $self->{pbot}->{users}->loggedin_admin($from, "$nick!$user\@$host")) {
if ($max_recall_time && gettimeofday - $msg->{timestamp} > $max_recall_time && not $self->{pbot}->{users}->loggedin_admin($context->{from}, $context->{hostmask})) {
$max_recall_time = duration($max_recall_time);
$recall_text .= "Sorry, you can not recall messages older than $max_recall_time.";
return $recall_text;
@ -374,4 +318,60 @@ sub recall_message {
return $recall_text;
}
sub cmd_rebuild_aliases {
my ($self, $context) = @_;
$self->{database}->rebuild_aliases_table;
}
sub cmd_aka_link {
my ($self, $context) = @_;
my ($id, $alias, $type) = split /\s+/, $context->{arguments};
$type = $self->{database}->{alias_type}->{STRONG} if not defined $type;
if (not $id or not $alias) { return "Usage: link <target id> <alias id> [type]"; }
my $source = $self->{database}->find_most_recent_hostmask($id);
my $target = $self->{database}->find_most_recent_hostmask($alias);
if (not $source) { return "No such id $id found."; }
if (not $target) { return "No such id $alias found."; }
if ($self->{database}->link_alias($id, $alias, $type)) {
return "/say $source " . ($type == $self->{database}->{alias_type}->{WEAK} ? "weakly" : "strongly") . " linked to $target.";
} else {
return "Link failed.";
}
}
sub cmd_aka_unlink {
my ($self, $context) = @_;
my ($id, $alias) = split /\s+/, $context->{arguments};
if (not $id or not $alias) { return "Usage: unlink <target id> <alias id>"; }
my $source = $self->{database}->find_most_recent_hostmask($id);
my $target = $self->{database}->find_most_recent_hostmask($alias);
if (not $source) { return "No such id $id found."; }
if (not $target) { return "No such id $alias found."; }
if ($self->{database}->unlink_alias($id, $alias)) { return "/say $source unlinked from $target."; }
else { return "Unlink failed."; }
}
sub get_message_account {
my ($self, $nick, $user, $host) = @_;
return $self->{database}->get_message_account($nick, $user, $host);
}
sub add_message {
my ($self, $account, $mask, $channel, $text, $mode) = @_;
$self->{database}->add_message($account, $mask, $channel, {timestamp => scalar gettimeofday, msg => $text, mode => $mode});
}
1;

View File

@ -17,27 +17,27 @@ use Encode;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->load_cmd(@_) }, "load", 1);
$self->{pbot}->{commands}->register(sub { $self->unload_cmd(@_) }, "unload", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_load(@_) }, "load", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unload(@_) }, "unload", 1);
}
sub load_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_load {
my ($self, $context) = @_;
my $factoids = $self->{pbot}->{factoids}->{factoids};
my ($keyword, $module) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
return "Usage: load <keyword> <module>" if not defined $module;
if ($factoids->exists('.*', $keyword)) { return 'There is already a keyword named ' . $factoids->get_data('.*', $keyword, '_name') . '.'; }
$self->{pbot}->{factoids}->add_factoid('module', '.*', "$nick!$user\@$host", $keyword, $module, 1);
$self->{pbot}->{factoids}->add_factoid('module', '.*', $context->{hostmask}, $keyword, $module, 1);
$factoids->set('.*', $keyword, 'add_nick', 1, 1);
$factoids->set('.*', $keyword, 'nooverride', 1);
$self->{pbot}->{logger}->log("$nick!$user\@$host loaded module $keyword => $module\n");
$self->{pbot}->{logger}->log("$context->{hostmask} loaded module $keyword => $module\n");
return "Loaded module $keyword => $module";
}
sub unload_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_unload {
my ($self, $context) = @_;
my $module = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
return "Usage: unload <keyword>" if not defined $module;
my $factoids = $self->{pbot}->{factoids}->{factoids};
@ -47,7 +47,7 @@ sub unload_cmd {
my $name = $factoids->get_data('.*', $module, '_name');
$factoids->remove('.*', $module);
$self->{pbot}->{logger}->log("$nick!$user\@$host unloaded module $module\n");
$self->{pbot}->{logger}->log("$context->{hostmask} unloaded module $module\n");
return "/say $name unloaded.";
}

View File

@ -27,7 +27,7 @@ sub initialize {
$self->{nicklist} = {};
$self->{pbot}->{registry}->add_default('text', 'nicklist', 'debug', '0');
$self->{pbot}->{commands}->register(sub { $self->show_nicklist(@_) }, "nicklist", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_nicklist(@_) }, "nicklist", 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.namreply', sub { $self->on_namreply(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) });
@ -43,16 +43,18 @@ sub initialize {
$self->{pbot}->{event_dispatcher}->register_handler('pbot.part', sub { $self->on_part_channel(@_) });
}
sub show_nicklist {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_nicklist {
my ($self, $context) = @_;
my $nicklist;
return "Usage: nicklist <channel> [nick]" if not length $arguments;
return "Usage: nicklist <channel> [nick]" if not length $context->{arguments};
my @args = split / /, $arguments;
my @args = split / /, $context->{arguments};
if (@args == 1) {
if (not exists $self->{nicklist}->{lc $arguments}) { return "No nicklist for $arguments."; }
$nicklist = Dumper($self->{nicklist}->{lc $arguments});
if (not exists $self->{nicklist}->{lc $context->{arguments}}) {
return "No nicklist for $context->{arguments}.";
}
$nicklist = Dumper($self->{nicklist}->{lc $context->{arguments}});
} else {
if (not exists $self->{nicklist}->{lc $args[0]}) { return "No nicklist for $args[0]."; }
elsif (not exists $self->{nicklist}->{lc $args[0]}->{lc $args[1]}) { return "No such nick $args[1] in channel $args[0]."; }

View File

@ -145,15 +145,15 @@ sub initialize {
$self->{commands} = PBot::Commands->new(pbot => $self, filename => "$data_dir/commands", %conf);
# add some commands
$self->{commands}->register(sub { $self->listcmd(@_) }, "list");
$self->{commands}->register(sub { $self->ack_die(@_) }, "die", 1);
$self->{commands}->register(sub { $self->export(@_) }, "export", 1);
$self->{commands}->register(sub { $self->reload(@_) }, "reload", 1);
$self->{commands}->register(sub { $self->evalcmd(@_) }, "eval", 1);
$self->{commands}->register(sub { $self->sl(@_) }, "sl", 1);
$self->{commands}->register(sub { $self->cmd_list(@_) }, "list");
$self->{commands}->register(sub { $self->cmd_die(@_) }, "die", 1);
$self->{commands}->register(sub { $self->cmd_export(@_) }, "export", 1);
$self->{commands}->register(sub { $self->cmd_reload(@_) }, "reload", 1);
$self->{commands}->register(sub { $self->cmd_eval(@_) }, "eval", 1);
$self->{commands}->register(sub { $self->cmd_sl(@_) }, "sl", 1);
# add 'cap' capability command
$self->{commands}->register(sub { $self->{capabilities}->capcmd(@_) }, "cap");
$self->{commands}->register(sub { $self->{capabilities}->cmd_cap(@_) }, "cap");
# prepare the version
$self->{version} = PBot::VERSION->new(pbot => $self, %conf);
@ -361,16 +361,15 @@ sub change_botnick_trigger {
$self->{conn}->nick($newvalue) if $self->{connected};
}
sub listcmd {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
sub cmd_list {
my ($self, $context) = @_;
my $text;
my $usage = "Usage: list <modules|commands>";
if (not defined $arguments) { return $usage; }
return $usage if not length $context->{arguments};
if ($arguments =~ /^modules$/i) {
if ($context->{arguments} =~ /^modules$/i) {
$text = "Loaded modules: ";
foreach my $channel (sort $self->{factoids}->{factoids}->get_keys) {
foreach my $command (sort $self->{factoids}->{factoids}->get_keys($channel)) {
@ -380,10 +379,11 @@ sub listcmd {
}
}
}
return $text;
}
if ($arguments =~ /^commands$/i) {
if ($context->{arguments} =~ /^commands$/i) {
$text = "Registered commands: ";
foreach my $command (sort { $a->{name} cmp $b->{name} } @{$self->{commands}->{handlers}}) {
if ($command->{requires_cap}) { $text .= "+$command->{name} "; }
@ -394,40 +394,35 @@ sub listcmd {
return $usage;
}
sub sl {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
return "Usage: sl <ircd command>" if not length $arguments;
$self->{conn}->sl($arguments);
return "";
sub cmd_sl {
my ($self, $context) = @_;
return "Usage: sl <ircd command>" if not length $context->{arguments};
$self->{conn}->sl($context->{arguments});
return "/msg $context->{nick} sl: command sent. See log for result.";
}
sub ack_die {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
$self->{logger}->log("$nick!$user\@$host made me exit.\n");
sub cmd_die {
my ($self, $context) = @_;
$self->{logger}->log("$context->{hostmask} made me exit.\n");
$self->atexit();
$self->{conn}->privmsg($from, "Good-bye.") if defined $from;
$self->{conn}->quit("Departure requested.");
$self->{conn}->privmsg($context->{from}, "Good-bye.") if defined $context->{from};
$self->{conn}->quit("Departure requested.") if defined $self->{conn};
exit 0;
}
sub export {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
return "Usage: export <factoids>" if not defined $arguments;
if ($arguments =~ /^factoids$/i) { return $self->{factoids}->export_factoids; }
sub cmd_export {
my ($self, $context) = @_;
return "Usage: export <factoids>" if not length $context->{arguments};
if ($context->{arguments} =~ /^factoids$/i) { return $self->{factoids}->export_factoids; }
}
sub evalcmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_eval {
my ($self, $context) = @_;
$self->{logger}->log("[$from] $nick!$user\@$host Evaluating [$arguments]\n");
$self->{logger}->log("eval: $context->{from} $context->{hostmask} evaluating `$context->{arguments}`\n");
my $ret = '';
my $result = eval $arguments;
my $result = eval $context->{arguments};
if ($@) {
if (length $result) { $ret .= "[Error: $@] "; }
else { $ret .= "Error: $@"; }
@ -438,9 +433,8 @@ sub evalcmd {
return "/say $ret $result";
}
sub reload {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
sub cmd_reload {
my ($self, $context) = @_;
my %reloadables = (
'capabilities' => sub {
@ -499,14 +493,14 @@ sub reload {
}
);
if (not length $arguments or not exists $reloadables{$arguments}) {
if (not length $context->{arguments} or not exists $reloadables{$context->{arguments}}) {
my $usage = 'Usage: reload <';
$usage .= join '|', sort keys %reloadables;
$usage .= '>';
return $usage;
}
return $reloadables{$arguments}();
return $reloadables{$context->{arguments}}();
}
1;

View File

@ -18,10 +18,55 @@ use File::Basename;
sub initialize {
my ($self, %conf) = @_;
$self->{plugins} = {};
$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);
$self->{pbot}->{commands}->register(sub { $self->cmd_plug(@_) }, "plug", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_unplug(@_) }, "unplug", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_replug(@_) }, "replug", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_pluglist(@_) }, "pluglist", 0);
}
sub cmd_plug {
my ($self, $context) = @_;
my $plugin = $context->{arguments};
if (not length $plugin) { return "Usage: plug <plugin>"; }
if ($self->load($plugin)) { return "Loaded $plugin plugin."; }
else { return "Plugin $plugin failed to load."; }
}
sub cmd_unplug {
my ($self, $context) = @_;
my $plugin = $context->{arguments};
if (not length $plugin) { return "Usage: unplug <plugin>"; }
if ($self->unload($plugin)) { return "Unloaded $plugin plugin."; }
else { return "Plugin $plugin is not loaded."; }
}
sub cmd_replug {
my ($self, $context) = @_;
my $plugin = $context->{arguments};
if (not length $plugin) { return "Usage: replug <plugin>"; }
my $unload_result = $self->cmd_unplug($context);
my $load_result = $self->cmd_plug($context);
my $result = "";
$result .= "$unload_result " if $unload_result =~ m/^Unloaded/;
$result .= $load_result;
return $result;
}
sub cmd_pluglist {
my ($self, $context) = @_;
my @plugins = sort keys %{$self->{plugins}};
return "No plugins loaded." if not @plugins;
return scalar @plugins . ' plugin' . (@plugins == 1 ? '' : 's') . ' loaded: ' . join (', ', @plugins);
}
sub autoload {
@ -121,46 +166,4 @@ sub unload {
}
}
sub reload_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not length $arguments) { return "Usage: replug <plugin>"; }
my $unload_result = $self->unload_cmd($from, $nick, $user, $host, $arguments);
my $load_result = $self->load_cmd($from, $nick, $user, $host, $arguments);
my $result = "";
$result .= "$unload_result " if $unload_result =~ m/^Unloaded/;
$result .= $load_result;
return $result;
}
sub load_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not length $arguments) { return "Usage: plug <plugin>"; }
if ($self->load($arguments)) { return "Loaded $arguments plugin."; }
else { return "Plugin $arguments failed to load."; }
}
sub unload_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
if (not length $arguments) { return "Usage: unplug <plugin>"; }
if ($self->unload($arguments)) { return "Unloaded $arguments plugin."; }
else { return "Plugin $arguments is not loaded."; }
}
sub list_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my @plugins = sort keys %{$self->{plugins}};
return "No plugins loaded." if not @plugins;
return scalar @plugins . ' plugin' . (@plugins == 1 ? '' : 's') . ' loaded: ' . join (', ', @plugins);
}
1;

View File

@ -22,8 +22,8 @@ use JSON;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->ps_cmd(@_) }, 'ps', 0);
$self->{pbot}->{commands}->register(sub { $self->kill_cmd(@_) }, 'kill', 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_ps(@_) }, 'ps', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_kill(@_) }, 'kill', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-kill', 1);
$self->{processes} = {};
@ -33,8 +33,8 @@ sub initialize {
};
}
sub ps_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_ps {
my ($self, $context) = @_;
my $usage = 'Usage: ps [-atu]; -a show all information; -t show running time; -u show user/channel';
my $getopt_error;
@ -46,7 +46,7 @@ sub ps_cmd {
Getopt::Long::Configure("bundling");
my ($show_all, $show_user, $show_running_time);
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'all|a' => \$show_all,
@ -82,8 +82,8 @@ sub ps_cmd {
return $result;
}
sub kill_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_kill {
my ($self, $context) = @_;
my $usage = 'Usage: kill [-a] [-t <seconds>] [-s <signal>] [pids...]; -a kill all processes; -t <seconds> kill processes running longer than <seconds>; -s send <signal> to processes';
my $getopt_error;
@ -95,7 +95,7 @@ sub kill_cmd {
Getopt::Long::Configure("bundling");
my ($kill_all, $kill_time, $signal);
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, preserve_escapes => 1, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, preserve_escapes => 1, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'all|a' => \$kill_all,

View File

@ -21,11 +21,11 @@ use File::Basename;
sub initialize {
my ($self, %conf) = @_;
$self->{refresher} = Module::Refresh->new;
$self->{pbot}->{commands}->register(sub { $self->refresh(@_) }, "refresh", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_refresh(@_) }, "refresh", 1);
}
sub refresh {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_refresh {
my ($self, $context) = @_;
my $last_update = $self->{pbot}->{updater}->get_last_update_version;
my @updates = $self->{pbot}->{updater}->get_available_updates($last_update);
@ -46,14 +46,14 @@ sub refresh {
};
my $result = eval {
if (not $arguments) {
if (not $context->{arguments}) {
$self->{pbot}->{logger}->log("Refreshing all modified modules\n");
$self->{refresher}->refresh;
return "Error refreshing: $refresh_error" if defined $refresh_error;
return "Refreshed all modified modules.\n";
} else {
$self->{pbot}->{logger}->log("Refreshing module $arguments\n");
$self->{refresher}->refresh_module($arguments);
$self->{pbot}->{logger}->log("Refreshing module $context->{arguments}\n");
$self->{refresher}->refresh_module($context->{arguments});
return "Error refreshing: $refresh_error" if defined $refresh_error;
$self->{pbot}->{logger}->log("Refreshed module.\n");
return "Refreshed module.\n";

View File

@ -15,18 +15,17 @@ use feature 'unicode_strings';
sub initialize {
my ($self, %conf) = @_;
$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);
$self->{pbot}->{commands}->register(sub { $self->cmd_regset(@_) }, "regset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_regunset(@_) }, "regunset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_regshow(@_) }, "regshow", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_regsetmeta(@_) }, "regsetmeta", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_regunsetmeta(@_) }, "regunsetmeta", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_regchange(@_) }, "regchange", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_regfind(@_) }, "regfind", 0);
}
sub regset {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_regset {
my ($self, $context) = @_;
my $usage = "Usage: regset <section>.<item> [value]";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -44,13 +43,12 @@ sub regset {
if (defined $value) { $self->{pbot}->{registry}->add('text', $section, $item, $value); }
else { return $self->{pbot}->{registry}->set($section, $item, 'value'); }
$self->{pbot}->{logger}->log("$nick!$user\@$host set registry entry [$section] $item => $value\n");
$self->{pbot}->{logger}->log("$context->{hostmask} set registry entry [$section] $item => $value\n");
return "$section.$item set to $value";
}
sub regunset {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_regunset {
my ($self, $context) = @_;
my $usage = "Usage: regunset <section>.<item>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -65,14 +63,13 @@ sub regunset {
if (not $self->{pbot}->{registry}->{registry}->exists($section, $item)) { return "No such item $item in section $section."; }
$self->{pbot}->{logger}->log("$nick!$user\@$host removed registry entry $section.$item\n");
$self->{pbot}->{logger}->log("$context->{hostmask} removed registry entry $section.$item\n");
$self->{pbot}->{registry}->remove($section, $item);
return "$section.$item deleted from registry";
}
sub regsetmeta {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_regsetmeta {
my ($self, $context) = @_;
my $usage = "Usage: regsetmeta <section>.<item> [key [value]]";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -92,9 +89,8 @@ sub regsetmeta {
return $self->{pbot}->{registry}->set($section, $item, $key, $value);
}
sub regunsetmeta {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_regunsetmeta {
my ($self, $context) = @_;
my $usage = "Usage: regunsetmeta <section>.<item> <key>";
# support "<section>.<key>" syntax in addition to "<section> <key>"
@ -111,9 +107,8 @@ sub regunsetmeta {
return $self->{pbot}->{registry}->unset($section, $item, $key);
}
sub regshow {
my $self = shift;
my ($from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_regshow {
my ($self, $context) = @_;
my $registry = $self->{pbot}->{registry}->{registry};
my $usage = "Usage: regshow <section>.<item>";
@ -137,11 +132,11 @@ sub regshow {
return $result;
}
sub regfind {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
sub cmd_regfind {
my ($self, $context) = @_;
my $registry = $self->{pbot}->{registry}->{registry};
my $usage = "Usage: regfind [-showvalues] [-section section] <regex>";
my $arguments = $context->{arguments};
return $usage if not defined $arguments;
@ -193,7 +188,7 @@ sub regfind {
}
};
return "/msg $nick $arguments: $@" if $@;
return "/msg $context->{nick} $context->{arguments}: $@" if $@;
if ($i == 1) {
chop $text;
@ -212,12 +207,12 @@ sub regfind {
}
}
sub regchange {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
sub cmd_regchange {
my ($self, $context) = @_;
my ($section, $item, $delim, $tochange, $changeto, $modifier);
my $arguments = $context->{arguments};
if (defined $arguments) {
if (length $arguments) {
if ($arguments =~ /^(.+?)\.([^\s]+)\s+s(.)/ or $arguments =~ /^([^\s]+) ([^\s]+)\s+s(.)/) {
$section = $1;
$item = $2;
@ -245,16 +240,16 @@ sub regchange {
my $ret = eval {
use re::engine::RE2 -strict => 1;
if (not $registry->get_data($section, $item, 'value') =~ s|$tochange|$changeto|) {
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: failed to change $section.$item 's$delim$tochange$delim$changeto$delim$modifier\n");
return "/msg $nick Change $section.$item failed.";
$self->{pbot}->{logger}->log("($context->{from}) $context->{hostmask}: failed to change $section.$item 's$delim$tochange$delim$changeto$delim$modifier\n");
return "/msg $context->{nick} Change $section.$item failed.";
} else {
$self->{pbot}->{logger}->log("($from) $nick!$user\@$host: changed $section.$item 's/$tochange/$changeto/\n");
$self->{pbot}->{logger}->log("($context->{from}) $context->{hostmask}: changed $section.$item 's/$tochange/$changeto/\n");
$self->{pbot}->{registry}->process_trigger($section, $item, 'value', $registry->get_data($section, $item, 'value'));
$self->{pbot}->{registry}->save;
return "$section.$item set to " . $registry->get_data($section, $item, 'value');
}
};
return "/msg $nick Failed to change $section.$item: $@" if $@;
return "/msg $context->{nick} Failed to change $section.$item: $@" if $@;
return $ret;
}

View File

@ -43,14 +43,14 @@ sub initialize {
$self->{last} = $seconds;
$self->{timeout} = $timeout;
$self->{pbot}->{commands}->register(sub { $self->event_queue_cmd(@_) }, 'eventqueue', 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_eventqueue(@_) }, 'eventqueue', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-eventqueue', 1);
$self->{timer_func} = sub { $self->on_tick_handler(@_) };
}
sub event_queue_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_eventqueue {
my ($self, $context) = @_;
my $usage = "Usage: eventqueue list [filter regex] | add <relative time> <command> [-repeat] | remove <event>";
@ -109,13 +109,13 @@ sub event_queue_cmd {
$repeating = 1 if $command =~ s/^-repeat\s+|\s+-repeat$//g;
my $cmd = {
nick => $nick,
user => $user,
host => $host,
nick => $context->{nick},
user => $context->{user},
host => $context->{host},
command => $command,
};
$self->{pbot}->{interpreter}->add_to_command_queue($from, $cmd, $delay, $repeating);
$self->{pbot}->{interpreter}->add_to_command_queue($context->{from}, $cmd, $delay, $repeating);
return "Command added to event queue.";
}

View File

@ -17,15 +17,15 @@ sub initialize {
my ($self, %conf) = @_;
$self->{users} = PBot::HashObject->new(name => 'Users', filename => $conf{filename}, pbot => $conf{pbot});
$self->{pbot}->{commands}->register(sub { $self->logincmd(@_) }, "login", 0);
$self->{pbot}->{commands}->register(sub { $self->logoutcmd(@_) }, "logout", 0);
$self->{pbot}->{commands}->register(sub { $self->useradd(@_) }, "useradd", 1);
$self->{pbot}->{commands}->register(sub { $self->userdel(@_) }, "userdel", 1);
$self->{pbot}->{commands}->register(sub { $self->userset(@_) }, "userset", 1);
$self->{pbot}->{commands}->register(sub { $self->userunset(@_) }, "userunset", 1);
$self->{pbot}->{commands}->register(sub { $self->users(@_) }, "users", 0);
$self->{pbot}->{commands}->register(sub { $self->mycmd(@_) }, "my", 0);
$self->{pbot}->{commands}->register(sub { $self->idcmd(@_) }, "id", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_login(@_) }, "login", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_logout(@_) }, "logout", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_useradd(@_) }, "useradd", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_userdel(@_) }, "userdel", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_userset(@_) }, "userset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_userunset(@_) }, "userunset", 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_users(@_) }, "users", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_my(@_) }, "my", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_id(@_) }, "id", 0);
$self->{pbot}->{capabilities}->add('admin', 'can-useradd', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-userdel', 1);
@ -33,10 +33,10 @@ sub initialize {
$self->{pbot}->{capabilities}->add('admin', 'can-userunset', 1);
$self->{pbot}->{capabilities}->add('can-modify-admins', undef, 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
$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->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('pbot.part', sub { $self->on_self_part(@_) });
$self->{user_index} = {};
@ -102,6 +102,352 @@ sub on_self_part {
delete $self->{user_cache}->{lc $event->{channel}};
}
sub cmd_login {
my ($self, $context) = @_;
my $channel = $context->{from};
return "Usage: login [channel] password" if not $context->{arguments};
my $arguments = $context->{arguments};
if ($arguments =~ m/^([^ ]+)\s+(.+)/) {
$channel = $1;
$arguments = $2;
}
my ($user_channel, $user_hostmask) = $self->find_user_account($channel, $context->{hostmask});
return "/msg $context->{nick} You do not have a user account. You may use the `my` command to create a personal user account. See `help my`." if not defined $user_channel;
my $name = $self->{user_index}->{$user_channel}->{$user_hostmask};
my $u = $self->{users}->get_data($name);
my $channel_text = $user_channel eq 'global' ? '' : " for $user_channel";
if ($u->{loggedin}) {
return "/msg $context->{nick} You are already logged into " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text.";
}
my $result = $self->login($user_channel, $user_hostmask, $arguments);
return "/msg $context->{nick} $result";
}
sub cmd_logout {
my ($self, $context) = @_;
$context->{from} = $context->{arguments} if length $context->{arguments};
my ($user_channel, $user_hostmask) = $self->find_user_account($context->{from}, $context->{hostmask});
return "/msg $context->{nick} You do not have a user account. You may use the `my` command to create a personal user account. See `help my`." if not defined $user_channel;
my $name = $self->{user_index}->{$user_channel}->{$user_hostmask};
my $u = $self->{users}->get_data($name);
my $channel_text = $user_channel eq 'global' ? '' : " for $user_channel";
return "/msg $context->{nick} You are not logged into " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text." if not $u->{loggedin};
$self->logout($user_channel, $user_hostmask);
return "/msg $context->{nick} Logged out of " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text.";
}
sub cmd_users {
my ($self, $context) = @_;
my $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
my $include_global = '';
if (not defined $channel) {
$channel = $context->{from};
$include_global = 'global';
} else {
$channel = 'global' if $channel !~ /^#/;
}
my $text = "Users: ";
my $last_channel = "";
my $sep = "";
foreach my $chan (sort keys %{$self->{user_index}}) {
next if $context->{from} =~ m/^#/ and $chan ne $channel and $chan ne $include_global;
next if $context->{from} !~ m/^#/ and $channel =~ m/^#/ and $chan ne $channel;
if ($last_channel ne $chan) {
$text .= "$sep$chan: ";
$last_channel = $chan;
$sep = "";
}
foreach my $hostmask (sort { $self->{user_index}->{$chan}->{$a} cmp $self->{user_index}->{$chan}->{$b} }
keys %{$self->{user_index}->{$chan}})
{
my $name = $self->{user_index}->{$chan}->{$hostmask};
$text .= $sep;
my $has_cap = 0;
foreach my $key ($self->{users}->get_keys($name)) {
if ($self->{pbot}->{capabilities}->exists($key)) {
$has_cap = 1;
last;
}
}
$text .= '+' if $has_cap;
$text .= $self->{users}->get_key_name($name);
$sep = " ";
}
$sep = "; ";
}
return $text;
}
sub cmd_useradd {
my ($self, $context) = @_;
my ($name, $hostmasks, $channels, $capabilities, $password) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 5);
$capabilities //= 'none';
if (not defined $name or not defined $hostmasks) { return "Usage: useradd <username> <hostmasks> [channels [capabilities [password]]]"; }
$channels = 'global' if $channels !~ /^#/;
my $u;
foreach my $channel (sort split /\s*,\s*/, lc $channels) {
$u = $self->{pbot}->{users}->find_user($channel, $context->{hostmask});
if (not defined $u) {
return "You do not have a user account for $channel; cannot add users to that channel.\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.";
}
foreach my $cap (split /\s*,\s*/, lc $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."; }
if ($self->{pbot}->{capabilities}->has($cap, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To set the $cap capability your user account must have the can-modify-admins capability.";
}
}
$self->{pbot}->{users}->add_user($name, $channels, $hostmasks, $capabilities, $password);
return "User added.";
}
sub cmd_userdel {
my ($self, $context) = @_;
if (not length $context->{arguments}) { return "Usage: userdel <username>"; }
my $u = $self->find_user($context->{from}, $context->{hostmask});
my $t = $self->{users}->get_data($context->{arguments});
if ($self->{pbot}->{capabilities}->userhas($t, 'botowner') and not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) {
return "Only botowners may delete botowner user accounts.";
}
if ($self->{pbot}->{capabilities}->userhas($t, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To delete admin user accounts your user account must have the can-modify-admins capability.";
}
return $self->remove_user($context->{arguments});
}
sub cmd_userset {
my ($self, $context) = @_;
my ($name, $key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
if (not defined $name) { return "Usage: userset <username> [key [value]]"; }
my $channel = $context->{from};
my $u = $self->find_user($channel, $context->{hostmask}, 1);
my $target = $self->{users}->get_data($name);
if (not $u) {
$channel = 'global' if $channel !~ /^#/;
return "You do not have a user account for $channel; cannot modify their users.";
}
if (not $target) {
return "There is no user account $name.";
}
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 $value and $self->{pbot}->{capabilities}->userhas($target, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To modify admin user accounts your user account must have the can-modify-admins capability.";
}
if (defined $key and $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." unless $self->{pbot}->{capabilities}->userhas($u, 'botowner');
}
my $result = $self->{users}->set($name, $key, $value);
print "result [$result]\n";
$result =~ s/^password => .*;?$/password => <private>;/m;
if (defined $key and ($key eq 'channels' or $key eq 'hostmasks') and defined $value) {
$self->rebuild_user_index;
}
return $result;
}
sub cmd_userunset {
my ($self, $context) = @_;
my ($name, $key) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (not defined $name or not defined $key) { return "Usage: userunset <username> <key>"; }
$key = lc $key;
my @disallowed = qw/channels hostmasks password/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata cannot be unset. Use the `userset` command to modify it.";
}
my $channel = $context->{from};
my $u = $self->find_user($channel, $context->{hostmask}, 1);
my $target = $self->{users}->get_data($name);
if (not $u) {
$channel = 'global' if $channel !~ /^#/;
return "You do not have a user account for $channel; cannot modify their users.";
}
if (not $target) {
return "There is no user account $name.";
}
if (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 ($self->{pbot}->{capabilities}->userhas($target, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To modify admin user accounts your user account must have the can-modify-admins capability.";
}
if ($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." unless $self->{pbot}->{capabilities}->userhas($u, 'botowner');
}
return $self->{users}->unset($name, $key);
}
sub cmd_my {
my ($self, $context) = @_;
my ($key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (defined $value) {
$value =~ s/^is\s+//;
$value = undef if not length $value;
}
my $channel = $context->{from};
my $hostmask = $context->{hostmask};
my ($u, $name) = $self->find_user($channel, $hostmask, 1);
if (not $u) {
$channel = 'global';
$hostmask = "$context->{nick}!$context->{user}\@" . $self->{pbot}->{antiflood}->address_to_mask($context->{host});
$name = $context->{nick};
$u = $self->{users}->get_data($name);
if ($u) {
$self->{pbot}->{logger}->log("Adding additional hostmask $hostmask to user account $name\n");
$u->{hostmasks} .= ",$hostmask";
$self->rebuild_user_index;
} else {
$u = $self->add_user($name, $channel, $hostmask, undef, undef, 1);
$u->{loggedin} = 1;
$u->{stayloggedin} = 1;
$u->{autologin} = 1;
$self->save;
}
}
my $result = '';
if (defined $key) {
$key = lc $key;
if (defined $value) {
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-capabilities')) {
if ($key =~ m/^is-/ or $key =~ m/^can-/ or $self->{pbot}->{capabilities}->exists($key)) {
return "The $key metadata requires the can-modify-capabilities capability, which your user account does not have.";
}
}
if (not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) {
my @disallowed = qw/can-modify-admins botowner can-modify-capabilities channels/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata requires the botowner capability to set, which your user account does not have.";
}
}
if (not $self->{pbot}->{capabilities}->userhas($u, 'admin')) {
my @disallowed = qw/name autoop autovoice chanop admin hostmasks/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata requires the admin capability to set, which your user account does not have.";
}
}
}
} else {
$result = "Usage: my <key> [value]; ";
}
$result .= $self->{users}->set($name, $key, $value);
$result =~ s/^password => .*;?$/password => <private>;/m;
return $result;
}
sub cmd_id {
my ($self, $context) = @_;
my $target = length $context->{arguments} ? $context->{arguments} : $context->{nick};
my ($message_account, $hostmask);
if ($target =~ m/^\d+$/) {
$hostmask = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_id($target);
return "I don't know anybody with id $target." if not $hostmask;
$message_account = $target;
} else {
($message_account, $hostmask) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($target);
return "I don't know anybody named $target." if not $message_account;
}
my $ancestor_id = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($message_account);
my $nickserv = $self->{pbot}->{messagehistory}->{database}->get_current_nickserv_account($message_account);
my ($u, $name) = $self->find_user($context->{from}, $hostmask, 1);
my $result = "$target ($hostmask): user id: $message_account; ";
if ($message_account != $ancestor_id) {
my $ancestor_hostmask = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_id($ancestor_id);
$ancestor_hostmask = 'undefined' if not $ancestor_hostmask;
$result .= "parent user id: $ancestor_id ($ancestor_hostmask); ";
}
if (defined $u) {
$result .= "user account: $name (";
$result .= ($u->{loggedin} ? "logged in" : "not logged in") . '); ';
}
if (defined $nickserv and length $nickserv) {
$result .= "NickServ: $nickserv";
}
return $result;
}
sub add_user {
my ($self, $name, $channels, $hostmasks, $capabilities, $password, $dont_save) = @_;
$channels = 'global' if $channels !~ m/^#/;
@ -180,6 +526,7 @@ sub rebuild_user_index {
sub cache_user {
my ($self, $channel, $hostmask, $username, $account_mask) = @_;
return if not length $username or not length $account_mask;
$self->{user_cache}->{lc $channel}->{lc $hostmask} = [ $username, $account_mask ];
}
@ -260,32 +607,18 @@ sub find_admin {
return $user;
}
sub loggedin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->find_user($channel, $hostmask);
return $user if defined $user and $user->{loggedin};
return undef;
}
sub loggedin_admin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->loggedin($channel, $hostmask);
return $user if defined $user and $self->{pbot}->{capabilities}->userhas($user, 'admin');
return undef;
}
sub login {
my ($self, $channel, $hostmask, $password) = @_;
my $user = $self->find_user($channel, $hostmask);
my $channel_text = $channel eq 'global' ? '' : " for $channel";
if (not defined $user) {
$self->{pbot}->{logger}->log("Attempt to login non-existent [$channel][$hostmask] failed\n");
$self->{pbot}->{logger}->log("Attempt to login non-existent $channel $hostmask failed\n");
return "You do not have a user account$channel_text.";
}
if (defined $password and $user->{password} ne $password) {
$self->{pbot}->{logger}->log("Bad login password for [$channel][$hostmask]\n");
$self->{pbot}->{logger}->log("Bad login password for $channel $hostmask\n");
return "I don't think so.";
}
@ -302,6 +635,20 @@ sub logout {
delete $user->{loggedin} if defined $user;
}
sub loggedin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->find_user($channel, $hostmask);
return $user if defined $user and $user->{loggedin};
return undef;
}
sub loggedin_admin {
my ($self, $channel, $hostmask) = @_;
my $user = $self->loggedin($channel, $hostmask);
return $user if defined $user and $self->{pbot}->{capabilities}->userhas($user, 'admin');
return undef;
}
sub get_user_metadata {
my ($self, $channel, $hostmask, $key) = @_;
my $user = $self->find_user($channel, $hostmask, 1);
@ -316,332 +663,4 @@ sub get_loggedin_user_metadata {
return undef;
}
sub logincmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my $channel = $from;
return "Usage: login [channel] password" if not $arguments;
if ($arguments =~ m/^([^ ]+)\s+(.+)/) {
$channel = $1;
$arguments = $2;
}
my ($user_channel, $user_hostmask) = $self->find_user_account($channel, "$nick!$user\@$host");
return "/msg $nick You do not have a user account." if not defined $user_channel;
my $name = $self->{user_index}->{$user_channel}->{$user_hostmask};
my $u = $self->{users}->get_data($name);
my $channel_text = $user_channel eq 'global' ? '' : " for $user_channel";
if ($u->{loggedin}) {
return "/msg $nick You are already logged into " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text.";
}
my $result = $self->login($user_channel, $user_hostmask, $arguments);
return "/msg $nick $result";
}
sub logoutcmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
$from = $arguments if length $arguments;
my ($user_channel, $user_hostmask) = $self->find_user_account($from, "$nick!$user\@$host");
return "/msg $nick You do not have a user account." if not defined $user_channel;
my $name = $self->{user_index}->{$user_channel}->{$user_hostmask};
my $u = $self->{users}->get_data($name);
my $channel_text = $user_channel eq 'global' ? '' : " for $user_channel";
return "/msg $nick You are not logged into " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text." if not $u->{loggedin};
$self->logout($user_channel, $user_hostmask);
return "/msg $nick Logged out of " . $self->{users}->get_key_name($name) . " ($user_hostmask)$channel_text.";
}
sub users {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
my $include_global = '';
if (not defined $channel) {
$channel = $from;
$include_global = 'global';
} else {
$channel = 'global' if $channel !~ /^#/;
}
my $text = "Users: ";
my $last_channel = "";
my $sep = "";
foreach my $chan (sort keys %{$self->{user_index}}) {
next if $from =~ m/^#/ and $chan ne $channel and $chan ne $include_global;
next if $from !~ m/^#/ and $channel =~ m/^#/ and $chan ne $channel;
if ($last_channel ne $chan) {
$text .= "$sep$chan: ";
$last_channel = $chan;
$sep = "";
}
foreach my $hostmask (sort { $self->{user_index}->{$chan}->{$a} cmp $self->{user_index}->{$chan}->{$b} }
keys %{$self->{user_index}->{$chan}})
{
my $name = $self->{user_index}->{$chan}->{$hostmask};
$text .= $sep;
my $has_cap = 0;
foreach my $key ($self->{users}->get_keys($name)) {
if ($self->{pbot}->{capabilities}->exists($key)) {
$has_cap = 1;
last;
}
}
$text .= '+' if $has_cap;
$text .= $self->{users}->get_key_name($name);
$sep = " ";
}
$sep = "; ";
}
return $text;
}
sub useradd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($name, $hostmasks, $channels, $capabilities, $password) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 5);
$capabilities //= 'none';
if (not defined $name or not defined $hostmasks) { return "Usage: useradd <username> <hostmasks> [channels [capabilities [password]]]"; }
$channels = 'global' if $channels !~ /^#/;
my $u;
foreach my $channel (sort split /\s*,\s*/, lc $channels) {
$u = $self->{pbot}->{users}->find_user($channel, "$nick!$user\@$host");
if (not defined $u) {
return "You do not have a user account for $channel; cannot add users to that channel.\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.";
}
foreach my $cap (split /\s*,\s*/, lc $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."; }
if ($self->{pbot}->{capabilities}->has($cap, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To set the $cap capability your user account must have the can-modify-admins capability.";
}
}
$self->{pbot}->{users}->add_user($name, $channels, $hostmasks, $capabilities, $password);
return "User added.";
}
sub userdel {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
if (not length $arguments) { return "Usage: userdel <username>"; }
my $u = $self->find_user($from, "$nick!$user\@$host");
my $t = $self->{users}->get_data($arguments);
if ($self->{pbot}->{capabilities}->userhas($t, 'botowner') and not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) {
return "Only botowners may delete botowner user accounts.";
}
if ($self->{pbot}->{capabilities}->userhas($t, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To delete admin user accounts your user account must have the can-modify-admins capability.";
}
return $self->remove_user($arguments);
}
sub userset {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($name, $key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 3);
if (not defined $name) { return "Usage: userset <username> [key [value]]"; }
my $u = $self->find_user($from, "$nick!$user\@$host", 1);
my $target = $self->{users}->get_data($name);
if (not $u) {
$from = 'global' if $from !~ /^#/;
return "You do not have a user account for $from; cannot modify their users.";
}
if (not $target) {
return "There is no user account $name.";
}
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 $value and $self->{pbot}->{capabilities}->userhas($target, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To modify admin user accounts your user account must have the can-modify-admins capability.";
}
if (defined $key and $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." unless $self->{pbot}->{capabilities}->userhas($u, 'botowner');
}
my $result = $self->{users}->set($name, $key, $value);
print "result [$result]\n";
$result =~ s/^password => .*;?$/password => <private>;/m;
if (defined $key and ($key eq 'channels' or $key eq 'hostmasks') and defined $value) {
$self->rebuild_user_index;
}
return $result;
}
sub userunset {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($name, $key) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (not defined $name or not defined $key) { return "Usage: userunset <username> <key>"; }
$key = lc $key;
my @disallowed = qw/channels hostmasks password/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata cannot be unset. Use the `userset` command to modify it.";
}
my $u = $self->find_user($from, "$nick!$user\@$host", 1);
my $target = $self->{users}->get_data($name);
if (not $u) {
$from = 'global' if $from !~ /^#/;
return "You do not have a user account for $from; cannot modify their users.";
}
if (not $target) {
return "There is no user account $name.";
}
if (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 ($self->{pbot}->{capabilities}->userhas($target, 'admin') and not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-admins')) {
return "To modify admin user accounts your user account must have the can-modify-admins capability.";
}
if ($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." unless $self->{pbot}->{capabilities}->userhas($u, 'botowner');
}
return $self->{users}->unset($name, $key);
}
sub mycmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my ($key, $value) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 2);
if (defined $value) {
$value =~ s/^is\s+//;
$value = undef if not length $value;
}
my $channel = $from;
my $hostmask = "$nick!$user\@$host";
my ($u, $name) = $self->find_user($channel, $hostmask, 1);
if (not $u) {
$channel = 'global';
$hostmask = "$nick!$user\@" . $self->{pbot}->{antiflood}->address_to_mask($host);
$name = $nick;
$u = $self->{users}->get_data($name);
if ($u) {
$self->{pbot}->{logger}->log("Adding additional hostmask $hostmask to user account $name\n");
$u->{hostmasks} .= ",$hostmask";
$self->rebuild_user_index;
} else {
$u = $self->add_user($name, $channel, $hostmask, undef, undef, 1);
$u->{loggedin} = 1;
$u->{stayloggedin} = 1;
$u->{autologin} = 1;
$self->save;
}
}
my $result = '';
if (defined $key) {
$key = lc $key;
if (defined $value) {
if (not $self->{pbot}->{capabilities}->userhas($u, 'can-modify-capabilities')) {
if ($key =~ m/^is-/ or $key =~ m/^can-/ or $self->{pbot}->{capabilities}->exists($key)) {
return "The $key metadata requires the can-modify-capabilities capability, which your user account does not have.";
}
}
if (not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) {
my @disallowed = qw/can-modify-admins botowner can-modify-capabilities/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata requires the botowner capability to set, which your user account does not have.";
}
}
if (not $self->{pbot}->{capabilities}->userhas($u, 'admin')) {
my @disallowed = qw/name autoop autovoice chanop admin/;
if (grep { $_ eq $key } @disallowed) {
return "The $key metadata requires the admin capability to set, which your user account does not have.";
}
}
}
} else {
$result = "Usage: my <key> [value]; ";
}
$result .= $self->{users}->set($name, $key, $value);
$result =~ s/^password => .*;?$/password => <private>;/m;
return $result;
}
sub idcmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
my $target = length $arguments ? $arguments : $nick;
my ($message_account, $hostmask) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($target);
my $ancestor_id = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($message_account);
my $nickserv = $self->{pbot}->{messagehistory}->{database}->get_current_nickserv_account($message_account);
my ($u, $name) = $self->find_user($from, $hostmask, 1);
my $result = "$target ($hostmask): user id: $message_account; ";
if ($message_account != $ancestor_id) {
$result .= "parent user id: $ancestor_id; ";
}
if (defined $u) {
$result .= "user account: $name (";
$result .= ($u->{loggedin} ? "logged in" : "not logged in") . '); ';
}
if (defined $nickserv and length $nickserv) {
$result .= "NickServ: $nickserv";
}
return $result;
}
1;

View File

@ -25,14 +25,12 @@ use constant {
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->version_cmd(@_) }, "version", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_version(@_) }, "version", 0);
$self->{last_check} = {timestamp => 0, version => BUILD_REVISION, date => BUILD_DATE};
}
sub version { return BUILD_NAME . " version " . BUILD_REVISION . " " . BUILD_DATE; }
sub version_cmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_version {
my ($self, $context) = @_;
my $ratelimit = $self->{pbot}->{registry}->get_value('version', 'check_limit') // 300;
@ -55,7 +53,7 @@ sub version_cmd {
}
my $target_nick;
$target_nick = $self->{pbot}->{nicklist}->is_present_similar($from, $arguments) if length $arguments;
$target_nick = $self->{pbot}->{nicklist}->is_present_similar($context->{from}, $context->{arguments}) if length $context->{arguments};
my $result = '/say ';
$result .= "$target_nick: " if $target_nick;
@ -65,4 +63,6 @@ sub version_cmd {
return $result;
}
sub version { return BUILD_NAME . " version " . BUILD_REVISION . " " . BUILD_DATE; }
1;

View File

@ -41,7 +41,7 @@ use Time::HiRes qw/gettimeofday/;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->actiontrigger(@_) }, 'actiontrigger', 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_actiontrigger(@_) }, 'actiontrigger', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-actiontrigger', 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
@ -228,7 +228,7 @@ sub get_trigger {
sub on_kick {
my ($self, $event_type, $event) = @_;
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($victim, $reason) = ($event->{event}->to, $event->{event}->{args}[1]);
my $channel = $event->{event}->{args}[0];
return 0 if $event->{interpreted};
@ -321,8 +321,8 @@ sub check_trigger {
return 0;
}
sub actiontrigger {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_actiontrigger {
my ($self, $context) = @_;
return "Internal error." if not $self->{dbh};
my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
@ -331,8 +331,8 @@ sub actiontrigger {
when ('list') {
my $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
if (not defined $channel) {
if ($from !~ /^#/) { $channel = 'global'; }
else { $channel = $from; }
if ($context->{from} !~ /^#/) { $channel = 'global'; }
else { $channel = $context->{from}; }
} elsif ($channel !~ m/^#/ and $channel ne 'global') {
return "Invalid channel $channel. Usage: actiontrigger list [#channel or global]";
}
@ -357,7 +357,7 @@ sub actiontrigger {
# TODO: use GetOpt flags instead of positional arguments
when ('add') {
my $channel;
if ($from =~ m/^#/) { $channel = $from; }
if ($context->{from} =~ m/^#/) { $channel = $context->{from}; }
else {
$channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
@ -372,7 +372,7 @@ sub actiontrigger {
my ($cap_override, $repeatdelay, $trigger, $action) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 4, 0, 1);
if (not defined $trigger or not defined $action) {
if ($from !~ m/^#/) {
if ($context->{from} !~ m/^#/) {
$result =
"To use this command from private message the <channel> argument is required. Usage: actiontrigger add <#channel or global> <capability> <repeat delay (in seconds)> <regex trigger> <command>";
} else {
@ -385,21 +385,21 @@ sub actiontrigger {
if (defined $exists) { return "Trigger already exists."; }
if ($repeatdelay !~ m/^\d+$/) { return "$nick: Missing repeat delay argument?\n"; }
if ($repeatdelay !~ m/^\d+$/) { return "$context->{nick}: Missing repeat delay argument?\n"; }
if ($cap_override ne 'none') {
if (not $self->{pbot}->{capabilities}->exists($cap_override)) { return "$nick: Capability '$cap_override' does not exist. Use 'none' to omit.\n"; }
my $u = $self->{pbot}->{users}->find_user($channel, "$nick!$user\@$host");
if (not $self->{pbot}->{capabilities}->exists($cap_override)) { return "$context->{nick}: Capability '$cap_override' does not exist. Use 'none' to omit.\n"; }
my $u = $self->{pbot}->{users}->find_user($channel, $context->{hostmask});
if (not $self->{pbot}->{capabilities}->userhas($u, $cap_override)) { return "You may not set a capability that you do not have."; }
}
if ($self->add_trigger($channel, $trigger, $action, "$nick!$user\@$host", $cap_override, $repeatdelay)) { $result = "Trigger added."; }
if ($self->add_trigger($channel, $trigger, $action, $context->{hostmask}, $cap_override, $repeatdelay)) { $result = "Trigger added."; }
else { $result = "Failed to add trigger."; }
}
when ('delete') {
my $channel;
if ($from =~ m/^#/) { $channel = $from; }
if ($context->{from} =~ m/^#/) { $channel = $context->{from}; }
else {
$channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist});
if ($channel !~ m/^#/ and $channel ne 'global') {
@ -410,7 +410,7 @@ sub actiontrigger {
my ($trigger) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 1);
if (not defined $trigger) {
if ($from !~ m/^#/) {
if ($context->{from} !~ m/^#/) {
$result = "To use this command from private message the <channel> argument is required. Usage: from private message: actiontrigger delete <channel> <regex trigger>";
} else {
$result = "Usage: actiontrigger delete <regex trigger>";
@ -428,7 +428,7 @@ sub actiontrigger {
}
default {
if ($from !~ m/^#/) {
if ($context->{from} !~ m/^#/) {
$result =
"Usage from private message: actiontrigger list [#channel or global] | actiontrigger add <#channel or global> <capability> <repeat delay (in seconds)> <regex trigger> <command> | actiontrigger delete <#channel or global> <regex trigger>";
} else {

View File

@ -21,7 +21,7 @@ $Data::Dumper::Sortkeys = 1;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->battleship_cmd(@_) }, 'battleship', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_battleship(@_) }, 'battleship', 0);
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
@ -49,7 +49,7 @@ sub unload {
sub on_kick {
my ($self, $event_type, $event) = @_;
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($victim, $reason) = ($event->{event}->to, $event->{event}->{args}[1]);
my $channel = $event->{event}->{args}[0];
return 0 if lc $channel ne $self->{channel};
@ -92,14 +92,13 @@ my %color = (
reset => "\x0F",
);
sub battleship_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
$arguments =~ s/^\s+|\s+$//g;
sub cmd_battleship {
my ($self, $context) = @_;
$context->{arguments} =~ s/^\s+|\s+$//g;
my $usage = "Usage: battleship challenge|accept|bomb|board|score|quit|players|kick|abort; for more information about a command: battleship help <command>";
my $command;
($command, $arguments) = split / /, $arguments, 2;
my ($command, $arguments) = split / /, $context->{arguments}, 2;
$command = lc $command;
my ($channel, $result);
@ -125,8 +124,8 @@ sub battleship_cmd {
$self->{current_state} = 'accept';
$self->{state_data} = {players => [], counter => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $player = {id => $id, name => $nick, missedinputs => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = {id => $id, name => $context->{nick}, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
$player = {id => -1, name => undef, missedinputs => 0};
@ -137,7 +136,7 @@ sub battleship_cmd {
}, 1, 'battleship loop', 1
);
return "/msg $self->{channel} $nick has made an open challenge! Use `accept` to accept their challenge.";
return "/msg $self->{channel} $context->{nick} has made an open challenge! Use `accept` to accept their challenge.";
}
my $challengee = $self->{pbot}->{nicklist}->is_present($self->{channel}, $arguments);
@ -147,8 +146,8 @@ sub battleship_cmd {
$self->{current_state} = 'accept';
$self->{state_data} = {players => [], counter => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $player = {id => $id, name => $nick, missedinputs => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = {id => $id, name => $context->{nick}, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
($id) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($challengee);
@ -160,31 +159,31 @@ sub battleship_cmd {
}, 1, 'battleship loop', 1
);
return "/msg $self->{channel} $nick has challenged $challengee to Battleship! Use `accept` to accept their challenge.";
return "/msg $self->{channel} $context->{nick} has challenged $challengee to Battleship! Use `accept` to accept their challenge.";
}
when ('accept') {
if ($self->{current_state} ne 'accept') { return "/msg $nick This is not the time to use `accept`."; }
if ($self->{current_state} ne 'accept') { return "/msg $context->{nick} This is not the time to use `accept`."; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = $self->{state_data}->{players}->[1];
# open challenge
if ($player->{id} == -1) {
$player->{id} = $id;
$player->{name} = $nick;
$player->{name} = $context->{nick};
}
if ($player->{id} == $id) {
$player->{accepted} = 1;
return "/msg $self->{channel} $nick has accepted $self->{state_data}->{players}->[0]->{name}'s challenge!";
return "/msg $self->{channel} $context->{nick} has accepted $self->{state_data}->{players}->[0]->{name}'s challenge!";
} else {
return "/msg $nick You have not been challenged to a game of Battleship yet.";
return "/msg $context->{nick} You have not been challenged to a game of Battleship yet.";
}
}
when ($_ eq 'decline' or $_ eq 'quit' or $_ eq 'forfeit' or $_ eq 'concede') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $removed = 0;
for (my $i = 0; $i < @{$self->{state_data}->{players}}; $i++) {
@ -198,20 +197,22 @@ sub battleship_cmd {
if ($self->{state_data}->{current_player} >= @{$self->{state_data}->{players}}) { $self->{state_data}->{current_player} = @{$self->{state_data}->{players}} - 1 }
if (@{$self->{state_data}->{players}} == 2 and ($self->{state_data}->{players}->[1]->{id} == -1 || not $self->{state_data}->{players}->[1]->{accepted})) {
return "/msg $self->{channel} $nick declined the challenge.";
return "/msg $self->{channel} $context->{nick} declined the challenge.";
} else {
return "/msg $self->{channel} $nick has left the game!";
return "/msg $self->{channel} $context->{nick} has left the game!";
}
} else {
return "$nick: But you are not even playing the game.";
return "$context->{nick}: But you are not even playing the game.";
}
}
when ('abort') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may abort the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) {
return "$context->{nick}: Only admins may abort the game.";
}
$self->{current_state} = 'gameover';
return "/msg $self->{channel} $nick: The game has been aborted.";
return "/msg $self->{channel} $context->{nick}: The game has been aborted.";
}
when ('score') {
@ -230,7 +231,9 @@ sub battleship_cmd {
}
when ('kick') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may kick people from the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) {
return "$context->{nick}: Only admins may kick people from the game.";
}
if (not length $arguments) { return "Usage: battleship kick <nick>"; }
@ -245,18 +248,18 @@ sub battleship_cmd {
if ($removed) {
if ($self->{state_data}->{current_player} >= @{$self->{state_data}->{players}}) { $self->{state_data}->{current_player} = @{$self->{state_data}->{players}} - 1 }
return "/msg $self->{channel} $nick: $arguments has been kicked from the game.";
return "/msg $self->{channel} $context->{nick}: $arguments has been kicked from the game.";
} else {
return "$nick: $arguments isn't even in the game.";
return "$context->{nick}: $arguments isn't even in the game.";
}
}
when ('bomb') {
if ($self->{debug}) { $self->{pbot}->{logger}->log("Battleship: bomb state: $self->{current_state}\n" . Dumper $self->{state_data}); }
if ($self->{current_state} ne 'playermove' and $self->{current_state} ne 'checkplayer') { return "$nick: It's not time to do that now."; }
if ($self->{current_state} ne 'playermove' and $self->{current_state} ne 'checkplayer') { return "$context->{nick}: It's not time to do that now."; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player;
if ($self->{state_data}->{players}->[0]->{id} == $id) { $player = 0; }
@ -264,11 +267,11 @@ sub battleship_cmd {
else { return "You are not playing in this game."; }
if (not length $arguments) {
if (delete $self->{state_data}->{players}->[$player]->{location}) { return "$nick: Attack location cleared."; }
else { return "$nick: Usage: bomb <location>"; }
if (delete $self->{state_data}->{players}->[$player]->{location}) { return "$context->{nick}: Attack location cleared."; }
else { return "$context->{nick}: Usage: bomb <location>"; }
}
if ($arguments !~ m/^[a-zA-Z][0-9]+$/) { return "$nick: Usage: battleship bomb <location>; <location> must be in the form of A15, B3, C9, etc."; }
if ($arguments !~ m/^[a-zA-Z][0-9]+$/) { return "$context->{nick}: Usage: battleship bomb <location>; <location> must be in the form of A15, B3, C9, etc."; }
$arguments = uc $arguments;
@ -278,17 +281,17 @@ sub battleship_cmd {
$x = ord($x) - 65;
if ($x < 0 || $x > $self->{N_Y} || $y < 0 || $y > $self->{N_X}) { return "$nick: Target out of range, try again."; }
if ($x < 0 || $x > $self->{N_Y} || $y < 0 || $y > $self->{N_X}) { return "$context->{nick}: Target out of range, try again."; }
if ($self->{state_data}->{current_player} != $player) {
my $msg;
if (not exists $self->{state_data}->{players}->[$player]->{location}) { $msg = "$nick: You will attack $arguments when it is your turn."; }
else { $msg = "$nick: You will now attack $arguments instead of $self->{state_data}->{players}->[$player]->{location} when it is your turn."; }
if (not exists $self->{state_data}->{players}->[$player]->{location}) { $msg = "$context->{nick}: You will attack $arguments when it is your turn."; }
else { $msg = "$context->{nick}: You will now attack $arguments instead of $self->{state_data}->{players}->[$player]->{location} when it is your turn."; }
$self->{state_data}->{players}->[$player]->{location} = $arguments;
return $msg;
}
if ($self->{player}->[$player]->{done}) { return "$nick: You have already attacked this turn."; }
if ($self->{player}->[$player]->{done}) { return "$context->{nick}: You have already attacked this turn."; }
if ($self->bomb($player, uc $arguments)) {
if ($self->{player}->[$player]->{won}) {
@ -308,7 +311,7 @@ sub battleship_cmd {
when ($_ eq 'specboard' or $_ eq 'board') {
if ($self->{current_state} eq 'nogame' or $self->{current_state} eq 'accept' or $self->{current_state} eq 'genboard' or $self->{current_state} eq 'gameover') {
return "$nick: There is no board to show right now.";
return "$context->{nick}: There is no board to show right now.";
}
if ($_ eq 'specboard') {
@ -316,10 +319,10 @@ sub battleship_cmd {
return;
}
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
for (my $i = 0; $i < 2; $i++) {
if ($self->{state_data}->{players}->[$i]->{id} == $id) {
$self->send_message($self->{channel}, "$nick surveys the battlefield!");
$self->send_message($self->{channel}, "$context->{nick} surveys the battlefield!");
$self->show_battlefield($i);
return;
}
@ -328,22 +331,24 @@ sub battleship_cmd {
}
when ('fullboard') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may see the full board."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) {
return "$context->{nick}: Only admins may see the full board.";
}
if ($self->{current_state} eq 'nogame' or $self->{current_state} eq 'accept' or $self->{current_state} eq 'genboard' or $self->{current_state} eq 'gameover') {
return "$nick: There is no board to show right now.";
return "$context->{nick}: There is no board to show right now.";
}
# show real board if admin is actually in the game ... no cheating!
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
for (my $i = 0; $i < 2; $i++) {
if ($self->{state_data}->{players}->[$i]->{id} == $id) {
$self->send_message($self->{channel}, "$nick surveys the battlefield!");
$self->send_message($self->{channel}, "$context->{nick} surveys the battlefield!");
$self->show_battlefield($i);
return;
}
}
$self->show_battlefield(4, $nick);
$self->show_battlefield(4, $context->{nick});
}
default { return $usage; }

View File

@ -19,7 +19,7 @@ $Data::Dumper::Sortkeys = 1;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->connect4_cmd(@_) }, 'connect4', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_connect4(@_) }, 'connect4', 0);
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
@ -41,7 +41,7 @@ sub unload {
sub on_kick {
my ($self, $event_type, $event) = @_;
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($victim, $reason) = ($event->{event}->to, $event->{event}->{args}[1]);
my $channel = $event->{event}->{args}[0];
return 0 if lc $channel ne $self->{channel};
@ -124,15 +124,15 @@ sub parse_challenge {
return 0;
}
sub connect4_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
my ($options, $command, $err);
sub cmd_connect4 {
my ($self, $context) = @_;
my $err;
$arguments =~ s/^\s+|\s+$//g;
$context->{arguments} =~ s/^\s+|\s+$//g;
my $usage = "Usage: connect4 challenge|accept|play|board|quit|players|kick|abort; for more information about a command: connect4 help <command>";
($command, $arguments, $options) = split / /, $arguments, 3;
my ($command, $arguments, $options) = split / /, $context->{arguments}, 3;
$command = lc $command;
given ($command) {
@ -166,13 +166,13 @@ sub connect4_cmd {
}, 1, 'connect4 loop', 1
);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $player = {id => $id, name => $nick, missedinputs => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = {id => $id, name => $context->{nick}, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
$player = {id => -1, name => undef, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
return "/msg $self->{channel} $nick has made an open challenge (Connect-$self->{CONNECTIONS} @ "
return "/msg $self->{channel} $context->{nick} has made an open challenge (Connect-$self->{CONNECTIONS} @ "
. "$self->{N_Y}x$self->{N_X} board)! Use `accept` to accept their challenge.";
}
@ -195,40 +195,40 @@ sub connect4_cmd {
}, 1, 'connect4 loop', 1
);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $player = {id => $id, name => $nick, missedinputs => 0};
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = {id => $id, name => $context->{nick}, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
($id) = $self->{pbot}->{messagehistory}->{database}->find_message_account_by_nick($challengee);
$player = {id => $id, name => $challengee, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
return "/msg $self->{channel} $nick has challenged $challengee to "
return "/msg $self->{channel} $context->{nick} has challenged $challengee to "
. "Connect-$self->{CONNECTIONS} @ $self->{N_Y}x$self->{N_X} board! Use `accept` to accept their challenge.";
}
when ('accept') {
if ($self->{current_state} ne 'accept') { return "/msg $nick This is not the time to use `accept`."; }
if ($self->{current_state} ne 'accept') { return "/msg $context->{nick} This is not the time to use `accept`."; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player = $self->{state_data}->{players}->[1];
# open challenge
if ($player->{id} == -1) {
$player->{id} = $id;
$player->{name} = $nick;
$player->{name} = $context->{nick};
}
if ($player->{id} == $id) {
$player->{accepted} = 1;
return "/msg $self->{channel} $nick has accepted $self->{state_data}->{players}->[0]->{name}'s challenge!";
return "/msg $self->{channel} $context->{nick} has accepted $self->{state_data}->{players}->[0]->{name}'s challenge!";
} else {
return "/msg $nick You have not been challenged to a game of Connect4 yet.";
return "/msg $context->{nick} You have not been challenged to a game of Connect4 yet.";
}
}
when ($_ eq 'decline' or $_ eq 'quit' or $_ eq 'forfeit' or $_ eq 'concede') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $removed = 0;
for (my $i = 0; $i < @{$self->{state_data}->{players}}; $i++) {
@ -240,17 +240,19 @@ sub connect4_cmd {
if ($removed) {
if ($self->{state_data}->{current_player} >= @{$self->{state_data}->{players}}) { $self->{state_data}->{current_player} = @{$self->{state_data}->{players}} - 1 }
return "/msg $self->{channel} $nick has left the game!";
return "/msg $self->{channel} $context->{nick} has left the game!";
} else {
return "$nick: But you are not even playing the game.";
return "$context->{nick}: But you are not even playing the game.";
}
}
when ('abort') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may abort the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) {
return "$context->{nick}: Only admins may abort the game.";
}
$self->{current_state} = 'gameover';
return "/msg $self->{channel} $nick: The game has been aborted.";
return "/msg $self->{channel} $context->{nick}: The game has been aborted.";
}
when ('players') {
@ -260,7 +262,9 @@ sub connect4_cmd {
}
when ('kick') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may kick people from the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) {
return "$context->{nick}: Only admins may kick people from the game.";
}
if (not length $arguments) { return "Usage: connect4 kick <nick>"; }
@ -275,29 +279,29 @@ sub connect4_cmd {
if ($removed) {
if ($self->{state_data}->{current_player} >= @{$self->{state_data}->{players}}) { $self->{state_data}->{current_player} = @{$self->{state_data}->{players}} - 1 }
return "/msg $self->{channel} $nick: $arguments has been kicked from the game.";
return "/msg $self->{channel} $context->{nick}: $arguments has been kicked from the game.";
} else {
return "$nick: $arguments isn't even in the game.";
return "$context->{nick}: $arguments isn't even in the game.";
}
}
when ('play') {
if ($self->{debug}) { $self->{pbot}->{logger}->log("Connect4: play state: $self->{current_state}\n" . Dumper $self->{state_data}); }
if ($self->{current_state} ne 'playermove') { return "$nick: It's not time to do that now."; }
if ($self->{current_state} ne 'playermove') { return "$context->{nick}: It's not time to do that now."; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
my $player;
if ($self->{state_data}->{players}->[0]->{id} == $id) { $player = 0; }
elsif ($self->{state_data}->{players}->[1]->{id} == $id) { $player = 1; }
else { return "You are not playing in this game."; }
if ($self->{state_data}->{current_player} != $player) { return "$nick: It is not your turn to attack!"; }
if ($self->{state_data}->{current_player} != $player) { return "$context->{nick}: It is not your turn to attack!"; }
if ($self->{player}->[$player]->{done}) { return "$nick: You have already played this turn."; }
if ($self->{player}->[$player]->{done}) { return "$context->{nick}: You have already played this turn."; }
if ($arguments !~ m/^\d+$/) { return "$nick: Usage: connect4 play <location>; <location> must be in the [1, $self->{N_X}] range."; }
if ($arguments !~ m/^\d+$/) { return "$context->{nick}: Usage: connect4 play <location>; <location> must be in the [1, $self->{N_X}] range."; }
if ($self->play($player, uc $arguments)) {
if ($self->{player}->[$player]->{won}) {
@ -318,13 +322,13 @@ sub connect4_cmd {
when ('board') {
if ($self->{current_state} eq 'nogame' or $self->{current_state} eq 'accept' or $self->{current_state} eq 'genboard' or $self->{current_state} eq 'gameover') {
return "$nick: There is no board to show right now.";
return "$context->{nick}: There is no board to show right now.";
}
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
for (my $i = 0; $i < 2; $i++) {
if ($self->{state_data}->{players}->[$i]->{id} == $id) {
$self->send_message($self->{channel}, "$nick surveys the board!");
$self->send_message($self->{channel}, "$context->{nick} surveys the board!");
$self->show_board;
return "";
}

View File

@ -17,12 +17,12 @@ use Time::HiRes qw/gettimeofday/;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->counteradd(@_) }, 'counteradd', 0);
$self->{pbot}->{commands}->register(sub { $self->counterdel(@_) }, 'counterdel', 0);
$self->{pbot}->{commands}->register(sub { $self->counterreset(@_) }, 'counterreset', 0);
$self->{pbot}->{commands}->register(sub { $self->countershow(@_) }, 'countershow', 0);
$self->{pbot}->{commands}->register(sub { $self->counterlist(@_) }, 'counterlist', 0);
$self->{pbot}->{commands}->register(sub { $self->countertrigger(@_) }, 'countertrigger', 1);
$self->{pbot}->{commands}->register(sub { $self->cmd_counteradd(@_) }, 'counteradd', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_counterdel(@_) }, 'counterdel', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_counterreset(@_) }, 'counterreset', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_countershow(@_) }, 'countershow', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_counterlist(@_) }, 'counterlist', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_countertrigger(@_) }, 'countertrigger', 1);
$self->{pbot}->{capabilities}->add('admin', 'can-countertrigger', 1);
$self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) });
@ -260,40 +260,40 @@ sub get_trigger {
return $target;
}
sub counteradd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_counteradd {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my ($channel, $name, $description);
if ($from !~ m/^#/) {
($channel, $name, $description) = split /\s+/, $arguments, 3;
if ($context->{from} !~ m/^#/) {
($channel, $name, $description) = split /\s+/, $context->{arguments}, 3;
if (not defined $channel or not defined $name or not defined $description or $channel !~ m/^#/) {
return "Usage from private message: counteradd <channel> <name> <description>";
}
} else {
$channel = $from;
($name, $description) = split /\s+/, $arguments, 2;
$channel = $context->{from};
($name, $description) = split /\s+/, $context->{arguments}, 2;
if (not defined $name or not defined $description) { return "Usage: counteradd <name> <description>"; }
}
my $result;
if ($self->add_counter("$nick!$user\@$host", $channel, $name, $description)) { $result = "Counter added."; }
else { $result = "Counter '$name' already exists."; }
if ($self->add_counter($context->{hostmask}, $channel, $name, $description)) { $result = "Counter added."; }
else { $result = "Counter '$name' already exists."; }
$self->dbi_end;
return $result;
}
sub counterdel {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_counterdel {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
($channel, $name) = split /\s+/, $arguments, 2;
if ($context->{from} !~ m/^#/) {
($channel, $name) = split /\s+/, $context->{arguments}, 2;
if (not defined $channel or not defined $name or $channel !~ m/^#/) { return "Usage from private message: counterdel <channel> <name>"; }
} else {
$channel = $from;
($name) = split /\s+/, $arguments, 1;
$channel = $context->{from};
($name) = split /\s+/, $context->{arguments}, 1;
if (not defined $name) { return "Usage: counterdel <name>"; }
}
@ -304,17 +304,17 @@ sub counterdel {
return $result;
}
sub counterreset {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_counterreset {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
($channel, $name) = split /\s+/, $arguments, 2;
if ($context->{from} !~ m/^#/) {
($channel, $name) = split /\s+/, $context->{arguments}, 2;
if (not defined $channel or not defined $name or $channel !~ m/^#/) { return "Usage from private message: counterreset <channel> <name>"; }
} else {
$channel = $from;
($name) = split /\s+/, $arguments, 1;
$channel = $context->{from};
($name) = split /\s+/, $context->{arguments}, 1;
if (not defined $name) { return "Usage: counterreset <name>"; }
}
@ -331,17 +331,17 @@ sub counterreset {
return $result;
}
sub countershow {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_countershow {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my ($channel, $name);
if ($from !~ m/^#/) {
($channel, $name) = split /\s+/, $arguments, 2;
if ($context->{from} !~ m/^#/) {
($channel, $name) = split /\s+/, $context->{arguments}, 2;
if (not defined $channel or not defined $name or $channel !~ m/^#/) { return "Usage from private message: countershow <channel> <name>"; }
} else {
$channel = $from;
($name) = split /\s+/, $arguments, 1;
$channel = $context->{from};
($name) = split /\s+/, $context->{arguments}, 1;
if (not defined $name) { return "Usage: countershow <name>"; }
}
@ -359,16 +359,16 @@ sub countershow {
return $result;
}
sub counterlist {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_counterlist {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my $channel;
if ($from !~ m/^#/) {
if (not length $arguments or $arguments !~ m/^#/) { return "Usage from private message: counterlist <channel>"; }
$channel = $arguments;
if ($context->{from} !~ m/^#/) {
if (not length $context->{arguments} or $context->{arguments} !~ m/^#/) { return "Usage from private message: counterlist <channel>"; }
$channel = $context->{arguments};
} else {
$channel = $from;
$channel = $context->{from};
}
my @counters = $self->list_counters($channel);
@ -388,19 +388,19 @@ sub counterlist {
return $result;
}
sub countertrigger {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_countertrigger {
my ($self, $context) = @_;
return "Internal error." if not $self->dbi_begin;
my $command;
($command, $arguments) = split / /, $arguments, 2;
($command, $context->{arguments}) = split / /, $context->{arguments}, 2;
my ($channel, $result);
given ($command) {
when ('list') {
if ($from =~ m/^#/) { $channel = $from; }
if ($context->{from} =~ m/^#/) { $channel = $context->{from}; }
else {
($channel) = split / /, $arguments, 1;
($channel) = split / /, $context->{arguments}, 1;
if ($channel !~ m/^#/) {
$self->dbi_end;
return "Usage from private message: countertrigger list <channel>";
@ -421,19 +421,19 @@ sub countertrigger {
}
when ('add') {
if ($from =~ m/^#/) { $channel = $from; }
if ($context->{from} =~ m/^#/) { $channel = $context->{from}; }
else {
($channel, $arguments) = split / /, $arguments, 2;
($channel, $context->{arguments}) = split / /, $context->{arguments}, 2;
if ($channel !~ m/^#/) {
$self->dbi_end;
return "Usage from private message: countertrigger add <channel> <regex> <target>";
}
}
my ($trigger, $target) = split / /, $arguments, 2;
my ($trigger, $target) = split / /, $context->{arguments}, 2;
if (not defined $trigger or not defined $target) {
if ($from !~ m/^#/) { $result = "Usage from private message: countertrigger add <channel> <regex> <target>"; }
if ($context->{from} !~ m/^#/) { $result = "Usage from private message: countertrigger add <channel> <regex> <target>"; }
else { $result = "Usage: countertrigger add <regex> <target>"; }
$self->dbi_end;
return $result;
@ -451,19 +451,19 @@ sub countertrigger {
}
when ('delete') {
if ($from =~ m/^#/) { $channel = $from; }
if ($context->{from} =~ m/^#/) { $channel = $context->{from}; }
else {
($channel, $arguments) = split / /, $arguments, 2;
($channel, $context->{arguments}) = split / /, $context->{arguments}, 2;
if ($channel !~ m/^#/) {
$self->dbi_end;
return "Usage from private message: countertrigger delete <channel> <regex>";
}
}
my ($trigger) = split / /, $arguments, 1;
my ($trigger) = split / /, $context->{arguments}, 1;
if (not defined $trigger) {
if ($from !~ m/^#/) { $result = "Usage from private message: countertrigger delete <channel> <regex>"; }
if ($context->{from} !~ m/^#/) { $result = "Usage from private message: countertrigger delete <channel> <regex>"; }
else { $result = "Usage: countertrigger delete <regex>"; }
$self->dbi_end;
return $result;

View File

@ -18,7 +18,7 @@ use Getopt::Long qw(GetOptionsFromArray);
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{registry}->add_default('text', 'date', 'default_timezone', 'UTC');
$self->{pbot}->{commands}->register(sub { $self->datecmd(@_) }, "date", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_date(@_) }, "date", 0);
}
sub unload {
@ -26,8 +26,8 @@ sub unload {
$self->{pbot}->{commands}->unregister("date");
}
sub datecmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_date {
my ($self, $context) = @_;
my $usage = "date [-u <user account>] [timezone]";
my $getopt_error;
local $SIG{__WARN__} = sub {
@ -38,7 +38,7 @@ sub datecmd {
Getopt::Long::Configure("bundling");
my ($user_override, $show_usage);
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'u=s' => \$user_override,
@ -47,7 +47,7 @@ sub datecmd {
return $usage if $show_usage;
return "/say $getopt_error -- $usage" if defined $getopt_error;
$arguments = "@opt_args";
$context->{arguments} = "@opt_args";
my $tz_override;
@ -57,19 +57,25 @@ sub datecmd {
return "User account does not have `timezone` set." if not exists $userdata->{timezone};
$tz_override = $userdata->{timezone};
} else {
$tz_override = $self->{pbot}->{users}->get_user_metadata($from, "$nick!$user\@$host", 'timezone') // '';
$tz_override = $self->{pbot}->{users}->get_user_metadata($context->{from}, $context->{hostmask}, 'timezone') // '';
}
my $timezone = $self->{pbot}->{registry}->get_value('date', 'default_timezone') // 'UTC';
$timezone = $tz_override if $tz_override;
$timezone = $arguments if length $arguments;
$timezone = $context->{arguments} if length $context->{arguments};
if (defined $user_override and not length $tz_override) { return "No timezone set or user account does not exist."; }
my $newcontext = {
from => $from, nick => $nick, user => $user, host => $host,
command => "date_module $timezone", root_channel => $from, root_keyword => "date_module",
keyword => "date_module", arguments => "$timezone"
from => $context->{from},
nick => $context->{nick},
user => $context->{user},
host => $context->{host},
command => "date_module $timezone",
root_channel => $context->{from},
root_keyword => "date_module",
keyword => "date_module",
arguments => "$timezone"
};
$self->{pbot}->{modules}->execute_module($newcontext);

View File

@ -22,7 +22,7 @@ sub initialize {
$self->{pbot}->{registry}->set_default('googlesearch', 'api_key', 'private', 1);
$self->{pbot}->{registry}->set_default('googlesearch', 'context', 'private', 1);
$self->{pbot}->{commands}->register(sub { $self->googlesearch(@_) }, 'google', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_googlesearch(@_) }, 'google', 0);
}
sub unload {
@ -30,32 +30,32 @@ sub unload {
$self->{pbot}->{commands}->unregister('google');
}
sub googlesearch {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
return "Usage: google [number of results] query\n" if not length $arguments;
sub cmd_googlesearch {
my ($self, $context) = @_;
return "Usage: google [number of results] query\n" if not length $context->{arguments};
my $matches = 1;
$matches = $1 if $arguments =~ s/^-n\s+([0-9]+)\s*//;
$matches = $1 if $context->{arguments} =~ s/^-n\s+([0-9]+)\s*//;
my $api_key = $self->{pbot}->{registry}->get_value('googlesearch', 'api_key'); # https://developers.google.com/custom-search/v1/overview
my $cx = $self->{pbot}->{registry}->get_value('googlesearch', 'context'); # https://cse.google.com/all
if (not length $api_key) {
return "$nick: Registry item googlesearch.api_key is not set. See https://developers.google.com/custom-search/v1/overview to get an API key.";
return "$context->{nick}: Registry item googlesearch.api_key is not set. See https://developers.google.com/custom-search/v1/overview to get an API key.";
}
if (not length $cx) { return "$nick: Registry item googlesearch.context is not set. See https://cse.google.com/all to set up a context."; }
if (not length $cx) { return "$context->{nick}: Registry item googlesearch.context is not set. See https://cse.google.com/all to set up a context."; }
my $engine = WWW::Google::CustomSearch->new(api_key => $api_key, cx => $cx, quotaUser => "$nick!$user\@$host");
my $engine = WWW::Google::CustomSearch->new(api_key => $api_key, cx => $cx, quotaUser => $context->{hostmask});
if ($arguments =~ m/(.*)\svs\s(.*)/i) {
if ($context->{arguments} =~ m/(.*)\s+vs\s+(.*)/i) {
my ($a, $b) = ($1, $2);
my $result1 = $engine->search("\"$a\" -\"$b\"");
my $result2 = $engine->search("\"$b\" -\"$a\"");
if (not defined $result1 or not defined $result1->items or not @{$result1->items}) { return "$nick: No results for $a"; }
if (not defined $result1 or not defined $result1->items or not @{$result1->items}) { return "$context->{nick}: No results for $a"; }
if (not defined $result2 or not defined $result2->items or not @{$result2->items}) { return "$nick: No results for $b"; }
if (not defined $result2 or not defined $result2->items or not @{$result2->items}) { return "$context->{nick}: No results for $b"; }
my $title1 = $result1->items->[0]->title;
my $title2 = $result2->items->[0]->title;
@ -64,7 +64,7 @@ sub googlesearch {
utf8::decode $title2;
return
"$nick: $a: ("
"$context->{nick}: $a: ("
. $result1->formattedTotalResults . ") "
. decode_entities($title1) . " <"
. $result1->items->[0]->link
@ -74,11 +74,11 @@ sub googlesearch {
. $result2->items->[0]->link . ">";
}
my $result = $engine->search($arguments);
my $result = $engine->search($context->{arguments});
if (not defined $result or not defined $result->items or not @{$result->items}) { return "$nick: No results found"; }
if (not defined $result or not defined $result->items or not @{$result->items}) { return "$context->{nick}: No results found"; }
my $output = "$nick: (" . $result->formattedTotalResults . " results) ";
my $output = "$context->{nick}: (" . $result->formattedTotalResults . " results) ";
my $comma = "";
foreach my $item (@{$result->items}) {

View File

@ -15,7 +15,7 @@ use feature 'unicode_strings';
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { return $self->magic(@_) }, "mc", 90);
$self->{pbot}->{commands}->register(sub { return $self->cmd_magic(@_) }, "mc", 90);
}
sub unload {
@ -23,9 +23,8 @@ sub unload {
$self->{pbot}->{commands}->unregister("mc");
}
sub magic {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
sub cmd_magic {
my ($self, $context) = @_;
# do something magical!
return "Did something magical.";

View File

@ -14,7 +14,7 @@ use Time::Duration qw/duration/;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { return $self->pd(@_) }, "pd", 0);
$self->{pbot}->{commands}->register(sub { return $self->cmd_parsedate(@_) }, "pd", 0);
}
sub unload {
@ -22,10 +22,9 @@ sub unload {
$self->{pbot}->{commands}->unregister("pd");
}
sub pd {
my $self = shift;
my ($from, $nick, $user, $host, $arguments) = @_;
my ($seconds, $error) = $self->{pbot}->{parsedate}->parsedate($arguments);
sub cmd_parsedate {
my ($self, $context) = @_;
my ($seconds, $error) = $self->{pbot}->{parsedate}->parsedate($context->{arguments});
return $error if defined $error;
return duration $seconds;
}

View File

@ -37,10 +37,10 @@ sub initialize {
$self->{pbot}->{atexit}->register(sub { $self->{database}->end(); return; });
$self->{pbot}->{commands}->register(sub { $self->grab_quotegrab(@_) }, 'grab', 0);
$self->{pbot}->{commands}->register(sub { $self->show_quotegrab(@_) }, 'getq', 0);
$self->{pbot}->{commands}->register(sub { $self->delete_quotegrab(@_) }, 'delq', 0);
$self->{pbot}->{commands}->register(sub { $self->show_random_quotegrab(@_) }, 'rq', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_grab_quotegrab(@_) }, 'grab', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_show_quotegrab(@_) }, 'getq', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_delete_quotegrab(@_) }, 'delq', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_show_random_quotegrab(@_) }, 'rq', 0);
}
sub unload {
@ -58,7 +58,7 @@ sub export_quotegrabs {
$self->{export_path} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/quotegrabs.html';
my $quotegrabs = $self->{database}->get_all_quotegrabs();
my $quotegrabs = $self->{database}->get_all_quotegrabs;
my $text;
my $table_id = 1;
@ -141,30 +141,30 @@ sub export_quotegrabs {
return "$i quotegrabs exported.";
}
sub grab_quotegrab {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_grab_quotegrab {
my ($self, $context) = @_;
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
if (not defined $arguments or not length $arguments) {
if (not defined $context->{arguments} or not length $context->{arguments}) {
return
"Usage: grab <nick> [history [channel]] [+ <nick> [history [channel]] ...] -- where [history] is an optional regex argument; e.g., to grab a message containing 'pizza', use `grab nick pizza`; you can chain grabs with + to grab multiple messages";
}
$arguments = lc $arguments;
$context->{arguments} = lc $context->{arguments};
my @grabs = split /\s\+\s/, $arguments;
my @grabs = split /\s\+\s/, $context->{arguments};
my ($grab_nick, $grab_history, $channel, $grab_nicks, $grab_text);
foreach my $grab (@grabs) {
($grab_nick, $grab_history, $channel) = $self->{pbot}->{interpreter}->split_line($grab, strip_quotes => 1);
$grab_history = $nick eq $grab_nick ? 2 : 1 if not defined $grab_history; # skip grab command if grabbing self without arguments
$channel = $from if not defined $channel;
$grab_history = $context->{nick} eq $grab_nick ? 2 : 1 if not defined $grab_history; # skip grab command if grabbing self without arguments
$channel = $context->{from} if not defined $channel;
if (not $channel =~ m/^#/) {
return "'$channel' is not a valid channel; usage: grab <nick> [[history] channel] (you must specify a history parameter before the channel parameter)";
@ -195,7 +195,7 @@ sub grab_quotegrab {
if (not defined $message) { return "No such message for nick $grab_nick in channel $channel containing text '$grab_history'"; }
}
$self->{pbot}->{logger}->log("$nick ($from) grabbed <$grab_nick/$channel> $message->{msg}\n");
$self->{pbot}->{logger}->log("$context->{nick} ($context->{from}) grabbed <$grab_nick/$channel> $message->{msg}\n");
if (not defined $grab_nicks) { $grab_nicks = $grab_nick; }
else { $grab_nicks .= "+$grab_nick"; }
@ -213,7 +213,7 @@ sub grab_quotegrab {
$quotegrab->{nick} = $grab_nicks;
$quotegrab->{channel} = $channel;
$quotegrab->{timestamp} = gettimeofday;
$quotegrab->{grabbed_by} = "$nick!$user\@$host";
$quotegrab->{grabbed_by} = $context->{hostmask};
$quotegrab->{text} = validate_string($grab_text);
$quotegrab->{id} = undef;
@ -237,34 +237,34 @@ sub grab_quotegrab {
}
}
sub delete_quotegrab {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_delete_quotegrab {
my ($self, $context) = @_;
my $quotegrab = $self->{database}->get_quotegrab($arguments);
my $quotegrab = $self->{database}->get_quotegrab($context->{arguments});
if (not defined $quotegrab) { return "/msg $nick No quotegrab matching id $arguments found."; }
if (not defined $quotegrab) { return "/msg $context->{nick} No quotegrab matching id $context->{arguments} found."; }
if (not $self->{pbot}->{users}->loggedin_admin($from, "$nick!$user\@$host") and $quotegrab->{grabbed_by} ne "$nick!$user\@$host") {
if (not $self->{pbot}->{users}->loggedin_admin($context->{from}, $context->{hostmask}) and $quotegrab->{grabbed_by} ne $context->{hostmask}) {
return "You are not the grabber of this quote.";
}
$self->{database}->delete_quotegrab($arguments);
$self->{database}->delete_quotegrab($context->{arguments});
$self->export_quotegrabs();
my $text = $quotegrab->{text};
my ($first_nick) = split /\+/, $quotegrab->{nick}, 2;
if ($text =~ s/^\/me\s+//) { return "Deleted $arguments: * $first_nick $text"; }
else { return "Deleted $arguments: <$first_nick> $text"; }
if ($text =~ s/^\/me\s+//) { return "Deleted $context->{arguments}: * $first_nick $text"; }
else { return "Deleted $context->{arguments}: <$first_nick> $text"; }
}
sub show_quotegrab {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_show_quotegrab {
my ($self, $context) = @_;
my $quotegrab = $self->{database}->get_quotegrab($arguments);
my $quotegrab = $self->{database}->get_quotegrab($context->{arguments});
if (not defined $quotegrab) { return "/msg $nick No quotegrab matching id $arguments found."; }
if (not defined $quotegrab) { return "/msg $context->{nick} No quotegrab matching id $context->{arguments} found."; }
my $timestamp = $quotegrab->{timestamp};
my $ago = ago(gettimeofday - $timestamp);
@ -272,32 +272,32 @@ sub show_quotegrab {
my ($first_nick) = split /\+/, $quotegrab->{nick}, 2;
if ($text =~ s/^\/me\s+//) {
return "$arguments: grabbed by $quotegrab->{grabbed_by} in $quotegrab->{channel} on " . localtime($timestamp) . " [$ago] * $first_nick $text";
return "$context->{arguments}: grabbed by $quotegrab->{grabbed_by} in $quotegrab->{channel} on " . localtime($timestamp) . " [$ago] * $first_nick $text";
} else {
return "$arguments: grabbed by $quotegrab->{grabbed_by} in $quotegrab->{channel} on " . localtime($timestamp) . " [$ago] <$first_nick> $text";
return "$context->{arguments}: grabbed by $quotegrab->{grabbed_by} in $quotegrab->{channel} on " . localtime($timestamp) . " [$ago] <$first_nick> $text";
}
}
sub show_random_quotegrab {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_show_random_quotegrab {
my ($self, $context) = @_;
my @quotes = ();
my ($nick_search, $channel_search, $text_search);
if (not defined $from) {
if (not defined $context->{from}) {
$self->{pbot}->{logger}->log("Command missing ~from parameter!\n");
return "";
}
my $usage = 'Usage: rq [nick [channel [text]]] [-c <channel>] [-t <text>]';
if (defined $arguments) {
if (defined $context->{arguments}) {
my $getopt_error;
local $SIG{__WARN__} = sub {
$getopt_error = shift;
chomp $getopt_error;
};
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, preserve_escapes => 1, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, preserve_escapes => 1, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'channel|c=s' => \$channel_search,
@ -316,11 +316,11 @@ sub show_random_quotegrab {
$nick_search = $tmp;
}
if (not defined $channel_search) { $channel_search = $from; }
if (not defined $channel_search) { $channel_search = $context->{from}; }
}
if (defined $channel_search and $channel_search !~ /^#/) {
if ($channel_search eq $nick) { $channel_search = undef; }
if ($channel_search eq $context->{nick}) { $channel_search = undef; }
elsif ($channel_search =~ m/^\./) {
# do nothing
} else {
@ -346,9 +346,9 @@ sub show_random_quotegrab {
my ($first_nick) = split /\+/, $quotegrab->{nick}, 2;
if ($text =~ s/^\/me\s+//) {
return "$quotegrab->{id}: " . (($channel_search eq '.*' or $quotegrab->{channel} ne $from) ? "[$quotegrab->{channel}] " : "") . "* $first_nick $text";
return "$quotegrab->{id}: " . (($channel_search eq '.*' or $quotegrab->{channel} ne $context->{from}) ? "[$quotegrab->{channel}] " : "") . "* $first_nick $text";
} else {
return "$quotegrab->{id}: " . (($channel_search eq '.*' or $quotegrab->{channel} ne $from) ? "[$quotegrab->{channel}] " : "") . "<$first_nick> $text";
return "$quotegrab->{id}: " . (($channel_search eq '.*' or $quotegrab->{channel} ne $context->{from}) ? "[$quotegrab->{channel}] " : "") . "<$first_nick> $text";
}
}

View File

@ -18,7 +18,7 @@ use Getopt::Long qw(GetOptionsFromArray);
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->remindme(@_) }, 'remindme', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_remindme(@_) }, 'remindme', 0);
$self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/reminders.sqlite3';
$self->dbi_begin;
$self->create_database;
@ -261,14 +261,14 @@ sub do_reminder {
}
}
sub remindme {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_remindme {
my ($self, $context) = @_;
if (not $self->{dbh}) { return "Internal error."; }
my $usage = "Usage: remindme [-c channel] [-r count] message -t time | remindme -l [nick] | remindme -d id";
return $usage if not length $arguments;
return $usage if not length $context->{arguments};
my ($target, $repeat, $text, $alarm, $list_reminders, $delete_id);
@ -280,7 +280,7 @@ sub remindme {
Getopt::Long::Configure("bundling");
my @opt_args = $self->{pbot}->{interpreter}->split_line($arguments, strip_quotes => 1);
my @opt_args = $self->{pbot}->{interpreter}->split_line($context->{arguments}, strip_quotes => 1);
GetOptionsFromArray(
\@opt_args,
'r:i' => \$repeat,
@ -304,7 +304,7 @@ sub remindme {
($nick_override) = $hostmask =~ m/^([^!]+)!/;
} else {
$account = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
$account = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
}
$account = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($account);
@ -331,7 +331,7 @@ sub remindme {
}
if ($delete_id) {
my $admininfo = $self->{pbot}->{users}->loggedin_admin($target ? $target : $from, "$nick!$user\@$host");
my $admininfo = $self->{pbot}->{users}->loggedin_admin($target ? $target : $context->{from}, $context->{hostmask});
# admins can delete any reminders (perhaps check admin levels against owner level?)
if ($admininfo) {
@ -341,7 +341,7 @@ sub remindme {
else { return "Could not delete reminder $delete_id."; }
}
my $account = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $account = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
$account = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($account);
my $reminder = $self->get_reminder($delete_id);
@ -358,7 +358,7 @@ sub remindme {
return "Please specify a point in time for this reminder." if not $alarm;
return "Please specify a reminder message." if not $text;
my $admininfo = $self->{pbot}->{users}->loggedin_admin($target ? $target : $from, "$nick!$user\@$host");
my $admininfo = $self->{pbot}->{users}->loggedin_admin($target ? $target : $context->{from}, $context->{hostmask});
if ($target) {
if (not defined $admininfo) { return "Only admins can create channel reminders."; }
@ -379,7 +379,7 @@ sub remindme {
$alarm = gettimeofday + $length;
my $account = $self->{pbot}->{messagehistory}->{database}->get_message_account($nick, $user, $host);
my $account = $self->{pbot}->{messagehistory}->{database}->get_message_account($context->{nick}, $context->{user}, $context->{host});
$account = $self->{pbot}->{messagehistory}->{database}->get_ancestor_id($account);
if (not defined $admininfo) {
@ -387,7 +387,7 @@ sub remindme {
if (@$reminders >= 3) { return "You may only set 3 reminders at a time. Use `remindme -d id` to remove a reminder."; }
}
if (my $id = $self->add_reminder($account, $target, $text, $alarm, $length, $repeat, "$nick!$user\@$host")) { return "Reminder $id added."; }
if (my $id = $self->add_reminder($account, $target, $text, $alarm, $length, $repeat, $context->{hostmask})) { return "Reminder $id added."; }
else { return "Failed to add reminder."; }
}

View File

@ -18,7 +18,7 @@ use Storable qw/dclone/;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->modcmd(@_) }, 'mod', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_mod(@_) }, 'mod', 0);
$self->{pbot}->{commands}->set_meta(
'mod', 'help',
'Provides restricted moderation abilities to voiced users. They can kick/ban/etc only users that are not admins, whitelisted, voiced or opped.'
@ -76,7 +76,7 @@ sub generic_command {
return "Voiced moderation is not enabled for this channel. Use `regset $channel.restrictedmod 1` to enable."
if not $self->{pbot}->{registry}->get_value($channel, 'restrictedmod');
my $hostmask = "$context->{nick}!$context->{user}\@$context->{host}";
my $hostmask = $context->{hostmask};
my $user = $self->{pbot}->{users}->loggedin($channel, $hostmask) // {admin => 0, chanmod => 0};
my $voiced = $self->{pbot}->{nicklist}->get_meta($channel, $context->{nick}, '+v');
@ -178,8 +178,8 @@ sub kb {
return $self->kick($context);
}
sub modcmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_mod {
my ($self, $context) = @_;
my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}) // '';
$command = lc $command;
@ -188,8 +188,11 @@ sub modcmd {
return $self->{commands}->{$command}->{subref}->($context);
} else {
my $commands = join ', ', sort keys %{$self->{commands}};
if ($from !~ m/^#/) { return "Usage: mod <channel> <command> [arguments]; commands are: $commands; see `mod help <command>` for more information."; }
else { return "Usage: mod <command> [arguments]; commands are: $commands; see `mod help <command>` for more information."; }
if ($context->{from} !~ m/^#/) {
return "Usage: mod <channel> <command> [arguments]; commands are: $commands; see `mod help <command>` for more information.";
} else {
return "Usage: mod <command> [arguments]; commands are: $commands; see `mod help <command>` for more information.";
}
}
}

View File

@ -43,7 +43,7 @@ use Plugins::Spinach::Rank;
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->spinach_cmd(@_) }, 'spinach', 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_spinach(@_) }, 'spinach', 0);
$self->{pbot}->{event_dispatcher}->register_handler('irc.part', sub { $self->on_departure(@_) });
$self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) });
@ -85,7 +85,7 @@ sub unload {
sub on_kick {
my ($self, $event_type, $event) = @_;
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($nick, $user, $host) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host);
my ($victim, $reason) = ($event->{event}->to, $event->{event}->{args}[1]);
my $channel = $event->{event}->{args}[0];
return 0 if lc $channel ne $self->{channel};
@ -228,8 +228,9 @@ my %color = (
reset => "\x0F",
);
sub spinach_cmd {
my ($self, $from, $nick, $user, $host, $arguments) = @_;
sub cmd_spinach {
my ($self, $context) = @_;
my $arguments = $context->{arguments};
$arguments =~ s/^\s+|\s+$//g;
my $usage =
@ -292,9 +293,9 @@ sub spinach_cmd {
}
when ('edit') {
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host");
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask});
if (not $admin) { return "$nick: Sorry, only admins may edit questions."; }
if (not $admin) { return "$context->{nick}: Sorry, only admins may edit questions."; }
my ($id, $key, $value) = split /\s+/, $arguments, 3;
@ -310,30 +311,30 @@ sub spinach_cmd {
}
}
if (not defined $question) { return "$nick: No such question."; }
if (not defined $question) { return "$context->{nick}: No such question."; }
if (not defined $key) {
my $dump = Dumper $question;
$dump =~ s/\$VAR\d+ = \{\s*//;
$dump =~ s/ \};\s*$//;
return "$nick: Question $id: $dump";
return "$context->{nick}: Question $id: $dump";
}
if (not defined $value) {
my $v = $question->{$key} // 'unset';
return "$nick: Question $id: $key => $v";
return "$context->{nick}: Question $id: $key => $v";
}
if ($key !~ m/^(?:question|answer|category)$/i) { return "$nick: You may not edit that key."; }
if ($key !~ m/^(?:question|answer|category)$/i) { return "$context->{nick}: You may not edit that key."; }
$question->{$key} = $value;
$self->save_questions;
return "$nick: Question $id: $key set to $value";
return "$context->{nick}: Question $id: $key set to $value";
}
when ('load') {
my $u = $self->{pbot}->{users}->loggedin($self->{channel}, "$nick!$user\@$host");
if (not $u or not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) { return "$nick: Sorry, only botowners may reload the questions."; }
my $u = $self->{pbot}->{users}->loggedin($self->{channel}, $context->{hostmask});
if (not $u or not $self->{pbot}->{capabilities}->userhas($u, 'botowner')) { return "$context->{nick}: Sorry, only botowners may reload the questions."; }
$arguments = undef if not length $arguments;
return $self->load_questions($arguments);
@ -350,59 +351,59 @@ sub spinach_cmd {
);
}
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
foreach my $player (@{$self->{state_data}->{players}}) {
if ($player->{id} == $id) { return "$nick: You have already joined this game."; }
if ($player->{id} == $id) { return "$context->{nick}: You have already joined this game."; }
}
my $player = {id => $id, name => $nick, score => 0, ready => $self->{current_state} eq 'getplayers' ? 0 : 1, missedinputs => 0};
my $player = {id => $id, name => $context->{nick}, score => 0, ready => $self->{current_state} eq 'getplayers' ? 0 : 1, missedinputs => 0};
push @{$self->{state_data}->{players}}, $player;
$self->{state_data}->{counter} = 0;
return "/msg $self->{channel} $nick has joined the game!";
return "/msg $self->{channel} $context->{nick} has joined the game!";
}
when ('ready') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
foreach my $player (@{$self->{state_data}->{players}}) {
if ($player->{id} == $id) {
if ($self->{current_state} ne 'getplayers') { return "/msg $nick This is not the time to use `ready`."; }
if ($self->{current_state} ne 'getplayers') { return "/msg $context->{nick} This is not the time to use `ready`."; }
if ($player->{ready} == 0) {
$player->{ready} = 1;
$player->{score} = 0;
return "/msg $self->{channel} $nick is ready!";
return "/msg $self->{channel} $context->{nick} is ready!";
} else {
return "/msg $nick You are already ready.";
return "/msg $context->{nick} You are already ready.";
}
}
}
return "$nick: You haven't joined this game yet. Use `j` to play now!";
return "$context->{nick}: You haven't joined this game yet. Use `j` to play now!";
}
when ('unready') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
foreach my $player (@{$self->{state_data}->{players}}) {
if ($player->{id} == $id) {
if ($self->{current_state} ne 'getplayers') { return "/msg $nick This is not the time to use `unready`."; }
if ($self->{current_state} ne 'getplayers') { return "/msg $context->{nick} This is not the time to use `unready`."; }
if ($player->{ready} != 0) {
$player->{ready} = 0;
return "/msg $self->{channel} $nick is no longer ready!";
return "/msg $self->{channel} $context->{nick} is no longer ready!";
} else {
return "/msg $nick You are already not ready.";
return "/msg $context->{nick} You are already not ready.";
}
}
}
return "$nick: You haven't joined this game yet. Use `j` to play now!";
return "$context->{nick}: You haven't joined this game yet. Use `j` to play now!";
}
when ('exit') {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $removed = 0;
for (my $i = 0; $i < @{$self->{state_data}->{players}}; $i++) {
@ -418,20 +419,20 @@ sub spinach_cmd {
if (not @{$self->{state_data}->{players}}) {
$self->{current_state} = 'nogame';
$self->{pbot}->{timer}->update_repeating('spinach loop', 0);
return "/msg $self->{channel} $nick has left the game! All players have left. The game has been stopped.";
return "/msg $self->{channel} $context->{nick} has left the game! All players have left. The game has been stopped.";
} else {
return "/msg $self->{channel} $nick has left the game!";
return "/msg $self->{channel} $context->{nick} has left the game!";
}
} else {
return "$nick: But you are not even playing the game.";
return "$context->{nick}: But you are not even playing the game.";
}
}
when ('abort') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may abort the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) { return "$context->{nick}: Sorry, only admins may abort the game."; }
$self->{current_state} = 'gameover';
return "/msg $self->{channel} $nick: The game has been aborted.";
return "/msg $self->{channel} $context->{nick}: The game has been aborted.";
}
when ($_ eq 'score' or $_ eq 'players') {
@ -460,7 +461,7 @@ sub spinach_cmd {
}
when ('kick') {
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host")) { return "$nick: Sorry, only admins may kick people from the game."; }
if (not $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask})) { return "$context->{nick}: Sorry, only admins may kick people from the game."; }
if (not length $arguments) { return "Usage: spinach kick <nick>"; }
@ -475,9 +476,9 @@ sub spinach_cmd {
if ($removed) {
if ($self->{state_data}->{current_player} >= @{$self->{state_data}->{players}}) { $self->{state_data}->{current_player} = @{$self->{state_data}->{players}} - 1 }
return "/msg $self->{channel} $nick: $arguments has been kicked from the game.";
return "/msg $self->{channel} $context->{nick}: $arguments has been kicked from the game.";
} else {
return "$nick: $arguments isn't even in the game.";
return "$context->{nick}: $arguments isn't even in the game.";
}
}
@ -490,7 +491,7 @@ sub spinach_cmd {
when ('reroll') {
if ($self->{current_state} =~ /getlies$/) {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $player;
my $rerolled = 0;
@ -508,7 +509,7 @@ sub spinach_cmd {
}
}
if (not $player) { return "$nick: You are not playing in this game. Use `j` to start playing now!"; }
if (not $player) { return "$context->{nick}: You are not playing in this game. Use `j` to start playing now!"; }
my $needed = int(@{$self->{state_data}->{players}} / 2) + 1;
$needed -= $rerolled;
@ -519,15 +520,15 @@ sub spinach_cmd {
elsif ($needed > 1) { $votes_needed = "$needed more votes to reroll!"; }
else { $votes_needed = "Rerolling..."; }
return "/msg $self->{channel} $color{red}$nick has voted to reroll for another question from the same category! $color{reset}$votes_needed";
return "/msg $self->{channel} $color{red}$context->{nick} has voted to reroll for another question from the same category! $color{reset}$votes_needed";
} else {
return "$nick: This command can be used only during the \"submit lies\" stage.";
return "$context->{nick}: This command can be used only during the \"submit lies\" stage.";
}
}
when ('skip') {
if ($self->{current_state} =~ /getlies$/) {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $player;
my $skipped = 0;
@ -545,7 +546,7 @@ sub spinach_cmd {
}
}
if (not $player) { return "$nick: You are not playing in this game. Use `j` to start playing now!"; }
if (not $player) { return "$context->{nick}: You are not playing in this game. Use `j` to start playing now!"; }
my $needed = int(@{$self->{state_data}->{players}} / 2) + 1;
$needed -= $skipped;
@ -556,15 +557,15 @@ sub spinach_cmd {
elsif ($needed > 1) { $votes_needed = "$needed more votes to skip!"; }
else { $votes_needed = "Skipping..."; }
return "/msg $self->{channel} $color{red}$nick has voted to skip this category! $color{reset}$votes_needed";
return "/msg $self->{channel} $color{red}$context->{nick} has voted to skip this category! $color{reset}$votes_needed";
} else {
return "$nick: This command can be used only during the \"submit lies\" stage.";
return "$context->{nick}: This command can be used only during the \"submit lies\" stage.";
}
}
when ('keep') {
if ($self->{current_state} =~ /getlies$/) {
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $player;
foreach my $i (@{$self->{state_data}->{players}}) {
@ -577,11 +578,11 @@ sub spinach_cmd {
}
}
if (not $player) { return "$nick: You are not playing in this game. Use `j` to start playing now!"; }
if (not $player) { return "$context->{nick}: You are not playing in this game. Use `j` to start playing now!"; }
return "/msg $self->{channel} $color{green}$nick has voted to keep playing the current question!";
return "/msg $self->{channel} $color{green}$context->{nick} has voted to keep playing the current question!";
} else {
return "$nick: This command can be used only during the \"submit lies\" stage.";
return "$context->{nick}: This command can be used only during the \"submit lies\" stage.";
}
}
@ -590,37 +591,37 @@ sub spinach_cmd {
if ($self->{current_state} =~ /choosecategory$/) {
if (not length $arguments) { return "Usage: spinach choose <integer>"; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
if (not @{$self->{state_data}->{players}} or $id != $self->{state_data}->{players}->[$self->{state_data}->{current_player}]->{id}) {
return "$nick: It is not your turn to choose a category.";
return "$context->{nick}: It is not your turn to choose a category.";
}
if ($arguments !~ /^[0-9]+$/) { return "$nick: Please choose a category number. $self->{state_data}->{categories_text}"; }
if ($arguments !~ /^[0-9]+$/) { return "$context->{nick}: Please choose a category number. $self->{state_data}->{categories_text}"; }
$arguments--;
if ($arguments < 0 or $arguments >= @{$self->{state_data}->{category_options}}) {
return "$nick: Choice out of range. Please choose a valid category. $self->{state_data}->{categories_text}";
return "$context->{nick}: Choice out of range. Please choose a valid category. $self->{state_data}->{categories_text}";
}
if ($arguments == @{$self->{state_data}->{category_options}} - 2) {
$arguments = (@{$self->{state_data}->{category_options}} - 2) * rand;
$self->{state_data}->{current_category} = $self->{state_data}->{category_options}->[$arguments];
return "/msg $self->{channel} $nick has chosen RANDOM CATEGORY! Randomly choosing category: $self->{state_data}->{current_category}!";
return "/msg $self->{channel} $context->{nick} has chosen RANDOM CATEGORY! Randomly choosing category: $self->{state_data}->{current_category}!";
} elsif ($arguments == @{$self->{state_data}->{category_options}} - 1) {
$self->{state_data}->{reroll_category} = 1;
return "/msg $self->{channel} $nick has chosen REROLL CATEGORIES! Rerolling categories...";
return "/msg $self->{channel} $context->{nick} has chosen REROLL CATEGORIES! Rerolling categories...";
} else {
$self->{state_data}->{current_category} = $self->{state_data}->{category_options}->[$arguments];
return "/msg $self->{channel} $nick has chosen $self->{state_data}->{current_category}!";
return "/msg $self->{channel} $context->{nick} has chosen $self->{state_data}->{current_category}!";
}
}
if ($self->{current_state} =~ /getlies$/) {
if (not length $arguments) { return "Usage: spinach lie <text>"; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $player;
foreach my $i (@{$self->{state_data}->{players}}) {
@ -630,7 +631,7 @@ sub spinach_cmd {
}
}
if (not $player) { return "$nick: You are not playing in this game. Use `j` to start playing now!"; }
if (not $player) { return "$context->{nick}: You are not playing in this game. Use `j` to start playing now!"; }
$arguments = $self->normalize_text($arguments);
@ -639,7 +640,7 @@ sub spinach_cmd {
=cut
if (@truth_count > 1 and @lie_count == 1) {
return "/msg $nick Your lie cannot be one word for this question. Please try again.";
return "/msg $context->{nick} Your lie cannot be one word for this question. Please try again.";
}
=cut
@ -654,24 +655,24 @@ sub spinach_cmd {
}
}
if (not $found_truth and ++$player->{lie_count} > 2) { return "/msg $nick You cannot change your lie again this round."; }
if (not $found_truth and ++$player->{lie_count} > 2) { return "/msg $context->{nick} You cannot change your lie again this round."; }
if ($found_truth) {
$self->send_message($self->{channel}, "$color{yellow}$nick has found the truth!$color{reset}");
return "$nick: Your lie is too similar to the truth! Please submit a different lie.";
$self->send_message($self->{channel}, "$color{yellow}$context->{nick} has found the truth!$color{reset}");
return "$context->{nick}: Your lie is too similar to the truth! Please submit a different lie.";
}
my $changed = exists $player->{lie};
$player->{lie} = $arguments;
if ($changed) { return "/msg $self->{channel} $nick has changed their lie!"; }
else { return "/msg $self->{channel} $nick has submitted a lie!"; }
if ($changed) { return "/msg $self->{channel} $context->{nick} has changed their lie!"; }
else { return "/msg $self->{channel} $context->{nick} has submitted a lie!"; }
}
if ($self->{current_state} =~ /findtruth$/) {
if (not length $arguments) { return "Usage: spinach truth <integer>"; }
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($nick, $user, $host);
my $id = $self->{pbot}->{messagehistory}->{database}->get_message_account_ancestor($context->{nick}, $context->{user}, $context->{host});
my $player;
foreach my $i (@{$self->{state_data}->{players}}) {
@ -681,14 +682,14 @@ sub spinach_cmd {
}
}
if (not $player) { return "$nick: You are not playing in this game. Use `j` to start playing now!"; }
if (not $player) { return "$context->{nick}: You are not playing in this game. Use `j` to start playing now!"; }
if ($arguments !~ /^[0-9]+$/) { return "$nick: Please select a truth number. $self->{state_data}->{current_choices_text}"; }
if ($arguments !~ /^[0-9]+$/) { return "$context->{nick}: Please select a truth number. $self->{state_data}->{current_choices_text}"; }
$arguments--;
if ($arguments < 0 or $arguments >= @{$self->{state_data}->{current_choices}}) {
return "$nick: Selection out of range. Please select a valid truth. $self->{state_data}->{current_choices_text}";
return "$context->{nick}: Selection out of range. Please select a valid truth. $self->{state_data}->{current_choices_text}";
}
my $changed = exists $player->{truth};
@ -696,14 +697,14 @@ sub spinach_cmd {
if ($player->{truth} eq $player->{lie}) {
delete $player->{truth};
return "$nick: You cannot select your own lie!";
return "$context->{nick}: You cannot select your own lie!";
}
if ($changed) { return "/msg $self->{channel} $nick has selected a different truth!"; }
else { return "/msg $self->{channel} $nick has selected a truth!"; }
if ($changed) { return "/msg $self->{channel} $context->{nick} has selected a different truth!"; }
else { return "/msg $self->{channel} $context->{nick} has selected a truth!"; }
}
return "$nick: It is not time to use this command.";
return "$context->{nick}: It is not time to use this command.";
}
when ('show') {
@ -712,7 +713,7 @@ sub spinach_cmd {
return;
}
return "$nick: There is nothing to show right now.";
return "$context->{nick}: There is nothing to show right now.";
}
when ('categories') {
@ -795,8 +796,8 @@ sub spinach_cmd {
if ($command eq 'set') {
if (not length $args) { return "Usage: spinach state set <new state>"; }
my $u = $self->{pbot}->{users}->loggedin($self->{channel}, "$nick!$user\@$host");
if (not $self->{pbot}->{capabilities}->userhas($u, 'admin')) { return "$nick: Sorry, only admins may set game state."; }
my $u = $self->{pbot}->{users}->loggedin($self->{channel}, $context->{hostmask});
if (not $self->{pbot}->{capabilities}->userhas($u, 'admin')) { return "$context->{nick}: Sorry, only admins may set game state."; }
$self->{previous_state} = $self->{current_state};
$self->{current_state} = $args;
@ -806,8 +807,8 @@ sub spinach_cmd {
if ($command eq 'result') {
if (not length $args) { return "Usage: spinach state result <current state result>"; }
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host");
if (not $admin) { return "$nick: Sorry, only admins may set game state."; }
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask});
if (not $admin) { return "$context->{nick}: Sorry, only admins may set game state."; }
$self->{state_data}->{previous_result} = $self->{state_data}->{result};
$self->{state_data}->{result} = $args;
@ -826,8 +827,8 @@ sub spinach_cmd {
return "Spinach stats setting cannot be modified while a game is in progress.";
}
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host");
if (defined $value and not $admin) { return "$nick: Sorry, only Spinach admins may set game settings."; }
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask});
if (defined $value and not $admin) { return "$context->{nick}: Sorry, only Spinach admins may set game settings."; }
return $self->{metadata}->set($index, $key, $value);
}
@ -841,8 +842,8 @@ sub spinach_cmd {
return "Spinach stats setting cannot be modified while a game is in progress.";
}
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, "$nick!$user\@$host");
if (not $admin) { return "$nick: Sorry, only Spinach admins may set game settings."; }
my $admin = $self->{pbot}->{users}->loggedin_admin($self->{channel}, $context->{hostmask});
if (not $admin) { return "$context->{nick}: Sorry, only Spinach admins may set game settings."; }
return $self->{metadata}->unset($index, $key);
}

View File

@ -20,7 +20,7 @@ use Getopt::Long qw(GetOptionsFromArray);
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->weathercmd(@_) }, "weather", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_weather(@_) }, "weather", 0);
}
sub unload {
@ -28,8 +28,8 @@ sub unload {
$self->{pbot}->{commands}->unregister("weather");
}
sub weathercmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_weather {
my ($self, $context) = @_;
my $usage = "Usage: weather [-u <user account>] [location]";
my $getopt_error;
local $SIG{__WARN__} = sub {
@ -37,6 +37,8 @@ sub weathercmd {
chomp $getopt_error;
};
my $arguments = $context->{arguments};
Getopt::Long::Configure("bundling");
my ($user_override, $show_usage);
@ -51,8 +53,8 @@ sub weathercmd {
return "/say $getopt_error -- $usage" if defined $getopt_error;
$arguments = "@opt_args";
my $hostmask = defined $user_override ? $user_override : "$nick!$user\@$host";
my $location_override = $self->{pbot}->{users}->get_user_metadata($from, $hostmask, 'location') // '';
my $hostmask = defined $user_override ? $user_override : $context->{hostmask};
my $location_override = $self->{pbot}->{users}->get_user_metadata($context->{from}, $hostmask, 'location') // '';
$arguments = $location_override if not length $arguments;
if (defined $user_override and not length $location_override) { return "No location set or user account does not exist."; }

View File

@ -26,7 +26,7 @@ use Getopt::Long qw(GetOptionsFromArray);
sub initialize {
my ($self, %conf) = @_;
$self->{pbot}->{commands}->register(sub { $self->wttrcmd(@_) }, "wttr", 0);
$self->{pbot}->{commands}->register(sub { $self->cmd_wttr(@_) }, "wttr", 0);
}
sub unload {
@ -34,8 +34,10 @@ sub unload {
$self->{pbot}->{commands}->unregister("wttr");
}
sub wttrcmd {
my ($self, $from, $nick, $user, $host, $arguments, $context) = @_;
sub cmd_wttr {
my ($self, $context) = @_;
my $arguments = $context->{arguments};
my @wttr_options = (
"conditions",
@ -92,7 +94,7 @@ sub wttrcmd {
$arguments = $userdata->{location};
} else {
if (not length $arguments) {
$arguments = $self->{pbot}->{users}->get_user_metadata($from, "$nick!$user\@$host", 'location') // '';
$arguments = $self->{pbot}->{users}->get_user_metadata($context->{from}, $context->{hostmask}, 'location') // '';
}
}