diff --git a/PBot/Interpreter.pm b/PBot/Interpreter.pm index f844bb66..b2bbeafa 100644 --- a/PBot/Interpreter.pm +++ b/PBot/Interpreter.pm @@ -438,6 +438,7 @@ sub interpret { nick => $context->{nick}, user => $context->{user}, host => $context->{host}, + hostmask => $context->{hostmask}, command => $context->{command}, checkflood => 1, message => "$context->{nick}: Why would I want to do that to myself?", @@ -659,6 +660,7 @@ sub handle_result { nick => $context->{nick}, user => $context->{user}, host => $context->{host}, + hostmask => $context->{hostmask}, command => $context->{command}, message => $message, checkflood => 1 @@ -682,6 +684,7 @@ sub handle_result { nick => $context->{nick}, user => $context->{user}, host => $context->{host}, + hostmask => $context->{hostmask}, command => $context->{command}, message => $line, checkflood => 1, @@ -891,6 +894,7 @@ sub add_message_to_output_queue { nick => $message->{nick}, user => $message->{user}, host => $message->{host}, + hostmask => $message->{hostmask}, output => $message->{message}, command => $message->{command}, checkflood => $message->{checkflood} @@ -912,6 +916,7 @@ sub add_to_command_queue { nick => $command->{nick}, user => $command->{user}, host => $command->{host}, + hostmask => $command->{hostmask}, command => $command->{command}, interpret_depth => 0, checkflood => 0, @@ -935,12 +940,14 @@ sub add_botcmd_to_command_queue { my ($self, $channel, $command, $delay) = @_; my $botcmd = { - nick => $self->{pbot}->{registry}->get_value('irc', 'botnick'), - user => 'stdin', - host => 'pbot', - command => $command + nick => $self->{pbot}->{registry}->get_value('irc', 'botnick'), + user => 'stdin', + host => 'pbot', + command => $command }; + $botcmd->{hostmask} = "$botcmd->{nick}!stdin\@pbot"; + $self->add_to_command_queue($channel, $botcmd, $delay); } diff --git a/PBot/Timer.pm b/PBot/Timer.pm index d9d7cbdb..0f746487 100644 --- a/PBot/Timer.pm +++ b/PBot/Timer.pm @@ -22,8 +22,8 @@ use PBot::Imports; use Time::Duration qw/concise duration/; -our $seconds ||= 0; -our $waitfor ||= 1; +our $seconds //= 0; +our $waitfor //= 1; our @timer_funcs; # alarm signal handler (poor-man's timer) @@ -204,8 +204,9 @@ sub enqueue_event_unless_exists { sub enqueue_event { my ($self, $ref, $interval, $id, $repeating) = @_; - $id ||= 'anonymous event'; - $repeating ||= 0; + $id //= 'anonymous event'; + $repeating //= 0; + $interval //= 0; my $event = { id => $id, diff --git a/Plugins/ActionTrigger.pm b/Plugins/ActionTrigger.pm index 5bda0cec..b8fe4750 100644 --- a/Plugins/ActionTrigger.pm +++ b/Plugins/ActionTrigger.pm @@ -1,14 +1,9 @@ -# This Source Code Form is subject to the terms of the Mozilla Public -# License, v. 2.0. If a copy of the MPL was not distributed with this -# file, You can obtain one at http://mozilla.org/MPL/2.0/. - -package Plugins::ActionTrigger; -use parent 'Plugins::Plugin'; - -# purpose: provides interface to set/remove/modify regular expression triggers +# File: ActionTrigger.pm +# +# Purpose: provides interface to set/remove/modify regular expression triggers # to execute a command. # -# Usage: actiontrigger add <#channel or global> +# Usage: actiontrigger add <#channel or global> # # Examples: # @@ -28,8 +23,13 @@ use parent 'Plugins::Plugin'; # actiontrigger add #channel none 0 "(?i)how is the weather (?:in|for) (.*) today" weather $1 # # These are basic examples; more complex examples can be crafted. -# -# TODO: share actually useful examples from personal bot + +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +package Plugins::ActionTrigger; +use parent 'Plugins::Plugin'; use PBot::Imports; @@ -39,9 +39,14 @@ use Time::HiRes qw/gettimeofday/; sub initialize { my ($self, %conf) = @_; + + # register bot command $self->{pbot}->{commands}->register(sub { $self->cmd_actiontrigger(@_) }, 'actiontrigger', 1); + + # add capability to admin group $self->{pbot}->{capabilities}->add('admin', 'can-actiontrigger', 1); + # register IRC handlers $self->{pbot}->{event_dispatcher}->register_handler('irc.public', sub { $self->on_public(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.caction', sub { $self->on_action(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.join', sub { $self->on_join(@_) }); @@ -49,18 +54,27 @@ sub initialize { $self->{pbot}->{event_dispatcher}->register_handler('irc.quit', sub { $self->on_departure(@_) }); $self->{pbot}->{event_dispatcher}->register_handler('irc.kick', sub { $self->on_kick(@_) }); + # database file $self->{filename} = $self->{pbot}->{registry}->get_value('general', 'data_dir') . '/triggers.sqlite3'; + # open and initialize database $self->dbi_begin; $self->create_database; - $self->update_database; } sub unload { - my $self = shift; + my ($self) = @_; + + # close database $self->dbi_end; + + # unregister bot command $self->{pbot}->{commands}->unregister('actiontrigger'); + + # remove capability $self->{pbot}->{capabilities}->remove('can-actiontrigger'); + + # remove IRC handlers $self->{pbot}->{event_dispatcher}->remove_handler('irc.public'); $self->{pbot}->{event_dispatcher}->remove_handler('irc.caction'); $self->{pbot}->{event_dispatcher}->remove_handler('irc.join'); @@ -69,8 +83,168 @@ sub unload { $self->{pbot}->{event_dispatcher}->remove_handler('irc.kick'); } +sub cmd_actiontrigger { + my ($self, $context) = @_; + + # database not available + return "Internal error." if not $self->{dbh}; + + my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); + + given ($command) { + when ('list') { + my $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); + + if (not defined $channel) { + if ($context->{from} !~ /^#/) { + # used from /msg + $channel = 'global'; + } else { + # used in channel + $channel = $context->{from}; + } + } + elsif ($channel !~ m/^#/ and $channel ne 'global') { + return "Invalid channel $channel. Usage: actiontrigger list [#channel or global]"; + } + + my @triggers = $self->list_triggers($channel); + + if (not @triggers) { + return "No action triggers set for $channel."; + } + else { + my $result = "Triggers for $channel:\n"; + my @items; + + foreach my $trigger (@triggers) { + $trigger->{cap_override} //= 'none'; + $trigger->{ratelimit} //= 0; + + my $item = "$trigger->{trigger} -> $trigger->{action}"; + + if ($trigger->{cap_override} and $trigger->{cap_override} ne 'none') { + $item .= " (capability=$trigger->{cap_override})"; + } + + if ($trigger->{ratelimit} != 0) { + $item .= " (ratelimit=$trigger->{ratelimit})"; + } + + push @items, $item; + } + + $result .= join ",\n", @items; + return $result; + } + } + + when ('add') { + # TODO: use GetOpt flags instead of positional arguments + + my $channel; + + if ($context->{from} =~ m/^#/) { + $channel = $context->{from}; + } + else { + $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); + + if (not defined $channel) { + return + "To use this command from private message the argument is required. Usage: actiontrigger add <#channel or global> "; + } + elsif ($channel !~ m/^#/ and $channel ne 'global') { + return "Invalid channel $channel. Usage: actiontrigger add <#channel or global> "; + } + } + + # split into 4 arguments, offset 0, preserving quotes + my ($cap_override, $ratelimit, $trigger, $action) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 4, 0, 1); + + if (not defined $trigger or not defined $action) { + if ($context->{from} !~ m/^#/) { + return + "To use this command from private message the argument is required. Usage: actiontrigger add <#channel or global> "; + } else { + return "Usage: actiontrigger add "; + } + } + + if (defined $self->get_trigger($channel, $trigger)) { + return "Trigger already exists."; + } + + if ($ratelimit !~ m/^\d+$/) { + return "$context->{nick}: Missing rate-limit argument?\n"; + } + + if ($cap_override ne 'none') { + 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, $context->{hostmask}, $cap_override, $ratelimit)) { + return "Trigger added."; + } else { + return "Failed to add trigger."; + } + } + + when ('delete') { + my $channel; + + if ($context->{from} =~ m/^#/) { + $channel = $context->{from}; + } + else { + $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); + + if ($channel !~ m/^#/ and $channel ne 'global') { + return "To use this command from private message the argument is required. Usage: actiontrigger delete <#channel or global> "; + } + } + + my ($trigger) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 1); + + if (not defined $trigger) { + if ($context->{from} !~ m/^#/) { + return "To use this command from private message the argument is required. Usage: from private message: actiontrigger delete "; + } else { + return "Usage: actiontrigger delete "; + } + } + + if (not defined $self->get_trigger($channel, $trigger)) { + return "No such trigger."; + } else { + $self->delete_trigger($channel, $trigger); + return "Trigger deleted."; + } + } + + default { + if ($context->{from} !~ m/^#/) { + return + "Usage from private message: actiontrigger list [#channel or global] | actiontrigger add <#channel or global> | actiontrigger delete <#channel or global> "; + } else { + return + "Usage: actiontrigger list [#channel or global] | actiontrigger add | actiontrigger delete "; + } + } + } +} + sub create_database { my $self = shift; + return if not $self->{dbh}; eval { @@ -81,7 +255,7 @@ CREATE TABLE IF NOT EXISTS Triggers ( action TEXT, owner TEXT, cap_override TEXT, - repeatdelay INTEGER, + ratelimit INTEGER, lastused NUMERIC ) SQL @@ -90,30 +264,9 @@ SQL $self->{pbot}->{logger}->log("ActionTrigger create database failed: $@") if $@; } -sub update_database { - my $self = shift; - return if not $self->{dbh}; - - my %columns = (); - - eval { - foreach my $col (@{$self->{dbh}->selectall_arrayref("PRAGMA TABLE_INFO(Triggers)")}) { - $columns{$col->[1]} = 1; - } - - if (not exists $columns{cap_override}) { - $self->{dbh}->do("ALTER TABLE Triggers ADD COLUMN cap_override TEXT"); - $self->{dbh}->do("UPDATE Triggers SET cap_override='botowner', level=0 WHERE level >= 90"); - $self->{dbh}->do("UPDATE Triggers SET cap_override='admin', level=0 WHERE level >= 60"); - $self->{dbh}->do("UPDATE Triggers SET cap_override='chanop', level=0 WHERE level >= 10"); - } - }; - - $self->{pbot}->{logger}->log("ActionTrigger update database failed: $@") if $@; -} - sub dbi_begin { my ($self) = @_; + eval { $self->{dbh} = DBI->connect("dbi:SQLite:dbname=$self->{filename}", "", "", {RaiseError => 1, PrintError => 0, AutoInactiveDestroy => 1, sqlite_unicode => 1}) or die $DBI::errstr; @@ -135,19 +288,20 @@ sub dbi_end { } sub add_trigger { - my ($self, $channel, $trigger, $action, $owner, $cap_override, $repeatdelay) = @_; + my ($self, $channel, $trigger, $action, $owner, $cap_override, $ratelimit) = @_; return 0 if $self->get_trigger($channel, $trigger); eval { - my $sth = $self->{dbh}->prepare('INSERT INTO Triggers (channel, trigger, action, owner, cap_override, repeatdelay, lastused) VALUES (?, ?, ?, ?, ?, ?, 0)'); - $sth->execute(lc $channel, $trigger, $action, $owner, $cap_override, $repeatdelay); + my $sth = $self->{dbh}->prepare('INSERT INTO Triggers (channel, trigger, action, owner, cap_override, ratelimit, lastused) VALUES (?, ?, ?, ?, ?, ?, 0)'); + $sth->execute(lc $channel, $trigger, $action, $owner, $cap_override, $ratelimit); }; if ($@) { $self->{pbot}->{logger}->log("Add trigger failed: $@"); return 0; } + return 1; } @@ -166,11 +320,12 @@ sub list_triggers { my $sth; if ($channel eq '*') { - $sth = $self->{dbh}->prepare('SELECT * FROM Triggers WHERE channel != ?'); $channel = 'global'; + $sth = $self->{dbh}->prepare('SELECT * FROM Triggers WHERE channel != ?'); } else { $sth = $self->{dbh}->prepare('SELECT * FROM Triggers WHERE channel = ?'); } + $sth->execute(lc $channel); return $sth->fetchall_arrayref({}); }; @@ -187,20 +342,22 @@ sub update_trigger { eval { my $sql = 'UPDATE Triggers SET '; - my $comma = ''; + my @triggers; foreach my $key (keys %$data) { - $sql .= "$comma$key = ?"; - $comma = ", "; + push @triggers, "$key = ?"; } + $sql .= join ', ', @triggers; $sql .= "WHERE trigger = ? AND channel = ?"; - my $sth = $self->{dbh}->prepare($sql); + + my $sth = $self->{dbh}->prepare($sql); + my $param = 1; foreach my $key (keys %$data) { $sth->bind_param($param++, $data->{$key}); } $sth->bind_param($param++, $trigger); $sth->bind_param($param, $channel); - $sth->execute(); + $sth->execute; }; $self->{pbot}->{logger}->log("Update trigger $channel/$trigger failed: $@\n") if $@; @@ -212,7 +369,7 @@ sub get_trigger { my $row = eval { my $sth = $self->{dbh}->prepare('SELECT * FROM Triggers WHERE channel = ? AND trigger = ?'); $sth->execute(lc $channel, $trigger); - my $row = $sth->fetchrow_hashref(); + my $row = $sth->fetchrow_hashref; return $row; }; @@ -226,53 +383,99 @@ 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 ($victim, $reason) = ($event->{event}->to, $event->{event}->{args}[1]); - my $channel = $event->{event}->{args}[0]; + + # don't handle this event if it was caused by a bot command return 0 if $event->{interpreted}; + + 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]; + $self->check_trigger($nick, $user, $host, $channel, "KICK $victim $reason"); return 0; } sub on_action { my ($self, $event_type, $event) = @_; - my ($nick, $user, $host, $msg) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->args); + + my ($nick, $user, $host, $msg) = ( + $event->{event}->nick, + $event->{event}->user, + $event->{event}->host, + $event->{event}->args + ); + my $channel = $event->{event}->{to}[0]; - #return 0 if $event->{interpreted}; + $msg =~ s/^\/me\s+//; + $self->check_trigger($nick, $user, $host, $channel, "ACTION $msg"); return 0; } sub on_public { my ($self, $event_type, $event) = @_; - my ($nick, $user, $host, $msg) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->args); + + my ($nick, $user, $host, $msg) = ( + $event->{event}->nick, + $event->{event}->user, + $event->{event}->host, + $event->{event}->args); + my $channel = $event->{event}->{to}[0]; - #return 0 if $event->{interpreted}; + $self->check_trigger($nick, $user, $host, $channel, "PRIVMSG $msg"); return 0; } sub on_join { my ($self, $event_type, $event) = @_; - my ($nick, $user, $host, $channel, $args) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to, $event->{event}->args); - $channel = lc $channel; + + my ($nick, $user, $host, $channel, $args) = ( + $event->{event}->nick, + $event->{event}->user, + $event->{event}->host, + $event->{event}->to, + $event->{event}->args + ); + $self->check_trigger($nick, $user, $host, $channel, "JOIN"); return 0; } sub on_departure { my ($self, $event_type, $event) = @_; - my ($nick, $user, $host, $channel, $args) = ($event->{event}->nick, $event->{event}->user, $event->{event}->host, $event->{event}->to, $event->{event}->args); - $channel = lc $channel; + + my ($nick, $user, $host, $channel, $args) = ( + $event->{event}->nick, + $event->{event}->user, + $event->{event}->host, + $event->{event}->to, + $event->{event}->args + ); + $self->check_trigger($nick, $user, $host, $channel, (uc $event->{event}->type) . " $args"); return 0; } sub check_trigger { my ($self, $nick, $user, $host, $channel, $text) = @_; + + # database not available return 0 if not $self->{dbh}; + $channel = lc $channel; + + # TODO: cache these instead of loading them again every message my @triggers = $self->list_triggers($channel); my @globals = $self->list_triggers('global'); push @triggers, @globals; @@ -282,160 +485,46 @@ sub check_trigger { foreach my $trigger (@triggers) { eval { - $trigger->{lastused} = 0 if not defined $trigger->{lastused}; - $trigger->{repeatdelay} = 0 if not defined $trigger->{repeatdelay}; - if ($now - $trigger->{lastused} >= $trigger->{repeatdelay} and $text =~ m/$trigger->{trigger}/) { + $trigger->{lastused} //= 0; + $trigger->{ratelimit} //= 0; + + if ($now - $trigger->{lastused} >= $trigger->{ratelimit} and $text =~ m/$trigger->{trigger}/) { + my @stuff = ($1, $2, $3, $4, $5, $6, $7, $8, $9); + $trigger->{lastused} = $now; - my $data = {lastused => $now}; - $self->update_trigger($trigger->{channel}, $trigger->{trigger}, $data); + + $self->update_trigger($trigger->{channel}, $trigger->{trigger}, { lastused => $now }); my $action = $trigger->{action}; - my @stuff = ($1, $2, $3, $4, $5, $6, $7, $8, $9); my $i; map { ++$i; $action =~ s/\$$i/$_/g; } @stuff; - my $delay = 0; - my ($n, $u, $h) = $trigger->{owner} =~ /^([^!]+)!([^@]+)\@(.*)$/; + my $command = { - nick => $n, - user => $u, - host => $h, - command => $action, + nick => $n, + user => $u, + host => $h, + hostmask => "$n!$u\@$host", + command => $action, }; - if (length $trigger->{cap_override} and $trigger->{cap_override} ne 'none') { + if ($trigger->{cap_override} and $trigger->{cap_override} ne 'none') { $command->{'cap-override'} = $trigger->{cap_override}; } + my $cap = ''; $cap = " (capability=$command->{'cap-override'})" if exists $command->{'cap-override'}; $self->{pbot}->{logger}->log("ActionTrigger: ($channel) $trigger->{trigger} -> $action$cap\n"); - $self->{pbot}->{interpreter}->add_to_command_queue($channel, $command, $delay); + + $self->{pbot}->{interpreter}->add_to_command_queue($channel, $command); } }; if ($@) { $self->{pbot}->{logger}->log("Skipping bad trigger $trigger->{trigger}: $@"); } } + return 0; } -sub cmd_actiontrigger { - my ($self, $context) = @_; - return "Internal error." if not $self->{dbh}; - - my $command = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); - my $result; - given ($command) { - when ('list') { - my $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); - if (not defined $channel) { - 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]"; - } - - my @triggers = $self->list_triggers($channel); - - if (not @triggers) { $result = "No action triggers set for $channel."; } - else { - $result = "Triggers for $channel:\n"; - my $comma = ''; - foreach my $trigger (@triggers) { - $trigger->{cap_override} //= 'none'; - $trigger->{repeatdelay} //= 0; - $result .= "$comma$trigger->{trigger} -> $trigger->{action}"; - $result .= " (capability=$trigger->{cap_override})" if length $trigger->{cap_override} and $trigger->{cap_override} ne 'none'; - $result .= " (repeatdelay=$trigger->{repeatdelay})" if $trigger->{repeatdelay} != 0; - $comma = ",\n"; - } - } - } - - # TODO: use GetOpt flags instead of positional arguments - when ('add') { - my $channel; - if ($context->{from} =~ m/^#/) { $channel = $context->{from}; } - else { - $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); - - if (not defined $channel) { - return - "To use this command from private message the argument is required. Usage: actiontrigger add <#channel or global> "; - } elsif ($channel !~ m/^#/ and $channel ne 'global') { - return "Invalid channel $channel. Usage: actiontrigger add <#channel or global> "; - } - } - - 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 ($context->{from} !~ m/^#/) { - $result = - "To use this command from private message the argument is required. Usage: actiontrigger add <#channel or global> "; - } else { - $result = "Usage: actiontrigger add "; - } - return $result; - } - - my $exists = $self->get_trigger($channel, $trigger); - - if (defined $exists) { return "Trigger already exists."; } - - 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 "$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, $context->{hostmask}, $cap_override, $repeatdelay)) { $result = "Trigger added."; } - else { $result = "Failed to add trigger."; } - } - - when ('delete') { - my $channel; - if ($context->{from} =~ m/^#/) { $channel = $context->{from}; } - else { - $channel = $self->{pbot}->{interpreter}->shift_arg($context->{arglist}); - if ($channel !~ m/^#/ and $channel ne 'global') { - return "To use this command from private message the argument is required. Usage: actiontrigger delete <#channel or global> "; - } - } - - my ($trigger) = $self->{pbot}->{interpreter}->split_args($context->{arglist}, 1); - - if (not defined $trigger) { - if ($context->{from} !~ m/^#/) { - $result = "To use this command from private message the argument is required. Usage: from private message: actiontrigger delete "; - } else { - $result = "Usage: actiontrigger delete "; - } - return $result; - } - - my $exists = $self->get_trigger($channel, $trigger); - - if (not defined $exists) { $result = "No such trigger."; } - else { - $self->delete_trigger($channel, $trigger); - $result = "Trigger deleted."; - } - } - - default { - if ($context->{from} !~ m/^#/) { - $result = - "Usage from private message: actiontrigger list [#channel or global] | actiontrigger add <#channel or global> | actiontrigger delete <#channel or global> "; - } else { - $result = - "Usage: actiontrigger list [#channel or global] | actiontrigger add | actiontrigger delete "; - } - } - } - return $result; -} - 1; diff --git a/Plugins/Battleship.pm b/Plugins/Battleship.pm index 92774c5b..b44f1b66 100644 --- a/Plugins/Battleship.pm +++ b/Plugins/Battleship.pm @@ -375,8 +375,13 @@ sub send_message { $delay = 0 if not defined $delay; my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick'); my $message = { - nick => $botnick, user => 'battleship', host => 'localhost', command => 'battleship text', checkflood => 1, - message => $text + nick => $botnick, + user => 'battleship', + host => 'localhost', + hostmask => "$botnick!battleship\@localhost", + command => 'battleship', + checkflood => 1, + message => $text }; $self->{pbot}->{interpreter}->add_message_to_output_queue($to, $message, $delay); } diff --git a/Plugins/Connect4.pm b/Plugins/Connect4.pm index d584bae8..42be925e 100644 --- a/Plugins/Connect4.pm +++ b/Plugins/Connect4.pm @@ -364,8 +364,13 @@ sub send_message { $delay = 0 if not defined $delay; my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick'); my $message = { - nick => $botnick, user => 'connect4', host => 'localhost', command => 'connect4 text', checkflood => 1, - message => $text + nick => $botnick, + user => 'connect4', + host => 'localhost', + hostmask => "$botnick!connect4\@localhost", + command => 'connect4', + checkflood => 1, + message => $text }; $self->{pbot}->{interpreter}->add_message_to_output_queue($to, $message, $delay); } diff --git a/Plugins/Spinach.pm b/Plugins/Spinach.pm index f5f23aee..c641a2e9 100644 --- a/Plugins/Spinach.pm +++ b/Plugins/Spinach.pm @@ -871,8 +871,13 @@ sub send_message { $delay = 0 if not defined $delay; my $botnick = $self->{pbot}->{registry}->get_value('irc', 'botnick'); my $message = { - nick => $botnick, user => 'spinach', host => 'localhost', command => 'spinach text', checkflood => 1, - message => $text + nick => $botnick, + user => 'spinach', + host => 'localhost', + hostmask => "$botnick!spinach\@localhost", + command => 'spinach', + checkflood => 1, + message => $text }; $self->{pbot}->{interpreter}->add_message_to_output_queue($to, $message, $delay); }