Adam
view release on metacpan or search on metacpan
ex/ai-bot.pl view on Meta::CPAN
);
}
sub recall {
my ($self, $query, $limit) = @_;
$limit //= 5;
my $rows = $self->_dbh->selectall_arrayref(
'SELECT nick, message, response FROM conversations WHERE message LIKE ? OR response LIKE ? ORDER BY id DESC LIMIT ?',
{ Slice => {} }, "%$query%", "%$query%", $limit,
);
return join("\n---\n", map { "<$_->{nick}> $_->{message}\n$_->{response}" } @$rows);
}
sub save_note {
my ($self, $nick, $content) = @_;
$self->_dbh->do('INSERT INTO notes (nick, content) VALUES (?,?)', undef, $nick, $content);
}
sub recall_notes {
my ($self, $nick, $query, $limit) = @_;
$limit //= 10;
ex/ai-bot.pl view on Meta::CPAN
$rows = $self->_dbh->selectall_arrayref(
'SELECT id, nick, content FROM notes WHERE nick = ? AND content LIKE ? ORDER BY id DESC LIMIT ?',
{ Slice => {} }, $nick, "%$query%", $limit,
);
} else {
$rows = $self->_dbh->selectall_arrayref(
'SELECT id, nick, content FROM notes WHERE content LIKE ? ORDER BY id DESC LIMIT ?',
{ Slice => {} }, "%$query%", $limit,
);
}
return join("\n", map { "#$_->{id} [$_->{nick}] $_->{content}" } @$rows);
}
sub update_note {
my ($self, $id, $content) = @_;
my $rows = $self->_dbh->do('UPDATE notes SET content = ? WHERE id = ?', undef, $content, $id);
return $rows > 0;
}
sub delete_note {
my ($self, $id) = @_;
ex/ai-bot.pl view on Meta::CPAN
if ($m->{msg} =~ /^(\S+)\s+\(/) {
$seen_nicks{$1} = 1;
}
if ($m->{msg} =~ /PRIVATE MESSAGE from (\S+)/) {
$seen_nicks{$1} = 1;
}
}
# Scan message text for nicks mentioned by name (check against channel members)
my @channel_nicks = eval { $self->irc->nicks($channel) } || ();
if (@channel_nicks) {
my %chan_nicks = map { lc($_) => $_ } @channel_nicks;
for my $m (@messages) {
for my $word (split /\W+/, $m->{msg}) {
if (my $real = $chan_nicks{lc $word}) {
$seen_nicks{$real} = 1;
}
}
}
}
my $context = '';
for my $nick (sort keys %seen_nicks) {
my $notes = $self->memory->recall_notes($nick, '', 5);
if ($notes) {
$context .= "[Your notes about $nick: $notes]\n";
}
}
my $input = '';
$input .= $context if $context;
$input .= join("\n", map {
my $prefix = $_->{nick};
if ($prefix ne 'system' && $self->irc->is_channel_operator($channel, $prefix)) {
$prefix = '@' . $prefix;
}
"<$prefix> $_->{msg}";
} @messages);
$self->info("Processing buffer for $channel:\n$input");
$self->_pending_raid({ input => $input, channel => $channel, messages => \@messages });
ex/ai-bot.pl view on Meta::CPAN
}
# Clean up AI output
$answer =~ s/^<\s*\@?\s*(\w+)\s*>:?\s*/$1: /mg; # line start <@nick> â Nick:
$answer =~ s/<\s*\@?\s*(\w+)\s*>/$1/g; # mid-text <nick> â Nick
$answer =~ s/<\/?\w+>//g; # strip remaining XML tags
# Strip lines where the AI narrates its tool usage
$answer =~ s/^\*?\s*(save_note|recall_notes|update_note|delete_note|recall_history|stay_silent|set_alarm|whois|send_private_message)\b[^\n]*\n?//mg;
# Check for lines too long
my @lines = grep { length } map { s/^\s+//r =~ s/\s+$//r } split(/\n/, $answer);
my $too_long = grep { length($_) > $MAX_LINE } @lines;
if ($too_long) {
$self->info("Response too long, asking to shorten");
$answer = eval {
my $retry = $self->_raider->raid(
"Your last response had lines over $MAX_LINE characters. "
. "Rewrite it shorter. Every line must be under $MAX_LINE chars."
);
"$retry";
} || $answer;
ex/declare.pl view on Meta::CPAN
is => 'ro',
default => 'Mutant Detected!',
);
on irc_bot_addressed( Str $nickstr, ArrayRef $channels, Str $message) {
my ($nick) = split /!/, $nickstr;
$self->privmsg( $channels => "$nick: ${ \$self->message }" );
};
}
my @bots = map { MasterMold->new( nickname => "Sentinel_${_}" ) } ( 1 .. 2 );
POE::Kernel->run;
ex/ncbot.pl view on Meta::CPAN
name => [qw(COMMAND echo -keep)],
create => q[^(?k:[@#][^\s]+)?\s*(?k:.*)$];
method handle_nc_command( Str $cmd) {
my ($owner) = split /!/, $self->get_owner;
given ($cmd) {
when (/$RE{COMMAND}{echo}{-keep}/) {
if ($1) {
my @targets = split ',', $1;
$self->privmsg( $_ => $2 ) for map { s/^@//; warn $_; $_ } @targets;
}
else {
$self->privmsg( $self->get_channels->[0] => $2 );
}
}
default {
$self->privmsg( $owner, "unknown command $cmd" );
}
}
lib/Adam.pm view on Meta::CPAN
has_plugins => 'count'
}
);
sub core_plugins {
return {
'Core_Connector' => 'POE::Component::IRC::Plugin::Connector',
'Core_BotAddressed' => 'POE::Component::IRC::Plugin::BotAddressed',
'Core_AutoJoin' => POE::Component::IRC::Plugin::AutoJoin->new(
Channels => { map { $_ => '' } @{ $_[0]->get_channels } },
),
'Core_NickReclaim' =>
POE::Component::IRC::Plugin::NickReclaim->new( poll => 30 ),
};
}
sub custom_plugins { {} }
lib/Adam/Plugin.pm view on Meta::CPAN
);
sub default_events {
[ grep { /^[SU]_\w+/ } shift->meta->get_all_method_names ];
}
sub PCI_register {
my ( $self, $irc ) = splice @_, 0, 2;
my @events = $self->_list_events;
my @s_events = map { s/^S_//; $_ } grep { /^S_/ } @events;
my @u_events = map { s/^U_//; $_ } grep { /^U_/ } @events;
$irc->plugin_register($self, 'SERVER', @s_events) if @s_events;
$irc->plugin_register($self, 'USER', @u_events) if @u_events;
return 1;
}
sub PCI_unregister {
my ( $self, $irc ) = @_;
return 1;
}
lib/Moses/Declare.pm view on Meta::CPAN
is => 'ro',
default => 'Mutant Detected!',
);
on irc_bot_addressed( Str $nickstr, ArrayRef $channels, Str $message) {
my ($nick) = split /!/, $nickstr;
$self->privmsg( $channels => "$nick: ${ \$self->message }" );
};
}
my @bots = map { MasterMold->new( nickname => "Sentinel_${_}" ) } ( 1 .. 2 );
POE::Kernel->run;
=head1 SUPPORT
=head2 Issues
Please report bugs and feature requests on GitHub at
L<https://github.com/perigrin/adam-bot-framework/issues>.
( run in 0.546 second using v1.01-cache-2.11-cpan-39bf76dae61 )