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 2.393 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )