IRC/Bot moderador
De Hackmeeting
Version 0.1 by meskio, queda aqui para el futuro.
#!/usr/bin/perl
# Este es un Bot de IRC preparado para hacer de moderador en asambleas
use warnings;
use strict;
use POE;
use POE::Component::IRC;
use Getopt::Long;
# información de conexion
my $nickname = 'moderador';
my $username = 'moderador';
my $ircname = 'El sumo moderador';
my $server = 'irc.freenode.net';
my $port = '6667';
my $channel = '#hackmeeting';
# textos
my $welcome = "<</me pide la palabra>> para esperar turno para hablar
<</me pide frase>> para pedir frase
tu turno de palabra termina cuando escribes un mensaje con <<.>>
tu turno de frase te permite enviar un solo mensage, pero tienes prioridad.";
my $msg = '';
my $help;
# orden de palabras y frases pedidas
my @palabras = ();
my @frases = ();
my $fue_frase = 2; # bool indica si la última peticion era frase, 2 indica que nadie esta hablando
# regexp de los comandos
my $palabra = '.*palabr.';
my $fin_escritura = '^\.$';
my $frase = '.*frase.*';
# parsear los parametros
usage() if ( ! GetOptions('help|h' => \$help,
'nick|n=s' => \$nickname,
'user|u=s' => \$username,
'irc|i=s' => \$ircname,
'server|s=s' => \$server,
'port|p=s' => \$port,
'channel|c=s' => \$channel,
'msg|m=s' => \$msg)
or defined $help );
sub usage {
print "usage: moderador [--nick|-n nickname] [--user|-u username] [--irc|-i ircname] [--server|-s server] [--port|-p port] [--channel|-c channel] [--msg|-m mensage] [--help|-h]\n";
exit;
}
print "Iniciando conexión......\n";
# Crea el componente de IRC
my ($irc) = POE::Component::IRC->spawn();
# Crea la sesión, indicandole los eventos que queremos que atienda
POE::Session->create(
inline_states => {
_start => \&bot_start,
irc_001 => \&on_connect,
irc_public => \&on_public,
irc_join => \&on_join,
irc_nick => \&on_nick,
irc_part => \&on_part,
irc_quit => \&on_part,
irc_ctcp_action => \&on_me,
},
);
# Al iniciar la sesion, conectarse al servidor
sub bot_start {
$irc->yield(register => "all");
$irc->yield(
connect => {
Nick => $nickname,
Username => $username,
Ircname => $ircname,
Server => $server,
Port => $port,
}
);
print "Conectado a: $server\n";
}
# Una vez este conectado al servidor conectarse al canal y enviar mensaje
sub on_connect {
$irc->yield(join => $channel);
envia_texto($channel, $welcome);
if ($msg)
{
envia_texto($channel, $msg);
}
print "Conectado a: $channel\n";
}
# Interpretar los mensajes de los usuarios
sub on_public {
my ($kernel, $who, $where, $msg) = @_[KERNEL, ARG0, ARG1, ARG2];
my $nick = (split /!/, $who)[0];
if ($fue_frase == 1) {
if ($nick eq $frases[0]) {
shift(@frases);
asignar_voz();
}
} elsif ($fue_frase == 0) {
if (($msg =~ /$fin_escritura/) and ($nick eq $palabras[0])) {
shift(@palabras);
asignar_voz();
}
}
}
# Enviar mensage de info cuando se conecte alguien nuevo
sub on_join {
my ($kernel, $who, $where) = @_[KERNEL, ARG0, ARG1];
my $nick = (split /!/, $who)[0];
envia_texto($nick, $welcome);
if ($msg)
{
envia_texto($nick, $msg);
}
}
# Cuando alguien cambia de nick hay que actualizar
sub on_nick {
my ($kernel, $prev, $now) = @_[KERNEL, ARG0, ARG1];
my $prev_nick = (split /!/, $prev)[0];
my $now_nick = (split /!/, $now)[0];
for (my $i = 0; $i < @palabras; $i++) {
if ($palabras[$i] eq $prev_nick) {
$palabras[$i] = $now_nick;
}
}
for (my $i = 0; $i < @frases; $i++) {
if ($frases[$i] eq $prev_nick) {
$frases[$i] = $now_nick;
}
}
}
# Si se va pierde sus palabras
# FIXME: si me caigo y me reconecto también las pierdo
sub on_part {
my ($kernel, $who) = @_[KERNEL, ARG0];
my $nick = (split /!/, $who)[0];
my $tengo_que_asignar = 0;
if (@frases > 0) {
if ($frases[0] eq $nick) {
$tengo_que_asignar = 1;
}
} elsif ((@palabras > 0) and ($palabras[0] eq $nick)) {
$tengo_que_asignar = 1;
}
my $j = 0;
for (my $i = 0; $i < @palabras; $i++) {
# Deslizar para eliminar el nick
if ($j != $i) {
$palabras[$j] = $palabras[$i];
}
if ($palabras[$i] ne $nick) {
$j++;
}
}
while ($#palabras >= $j) {
pop(@palabras);
}
$j = 0;
for (my $i = 0; $i < @frases; $i++) {
# Deslizar para eliminar el nick
if ($j != $i) {
$frases[$j] = $frases[$i];
}
if ($frases[$i] ne $nick) {
$j++;
}
}
while ($#frases >= $j) {
pop(@frases);
}
if ($tengo_que_asignar) {
asignar_voz();
}
}
# /me para pedir palabra
sub on_me {
my ($kernel, $who, $where, $msg) = @_[KERNEL, ARG0, ARG1, ARG2];
my $nick = (split /!/, $who)[0];
if ($msg =~ /$palabra/)
{
push(@palabras, $nick);
print "$nick ha pedido palabra\n";
}
if ($msg =~ /$frase/)
{
push(@frases, $nick);
print "$nick ha pedido frase\n";
}
print "frases: " . join(", ", @frases) . ".\n";
print "palabras: " . join(", ", @palabras) . ".\n";
if ($fue_frase == 2)
{
asignar_voz();
}
}
sub asignar_voz {
my $str = "";
if (@frases > 0) {
$str = "da frase a $frases[0]";
if (@frases > 1) {
$str .= " otras frases pedidas: " .
join(', ', @frases[1..$#frases]) . ".";
}
$fue_frase = 1;
} elsif (@palabras > 0) {
$str = "da la palabra a $palabras[0].";
if (@palabras > 1) {
$str .= " otras palabras pedidas: " .
join(', ', @palabras[1..$#palabras]) . ".";
}
$fue_frase = 0;
} else {
$fue_frase = 2;
}
if ($str ne "") {
$irc->yield(ctcp => $channel => "ACTION $str");
}
}
sub envia_texto {
my ($who, $txt) = @_[0, 1];
foreach (split("\n", $txt)) {
$irc->yield(privmsg => $who, $_);
}
}
# Ejecutar el bot hasta que termine
$poe_kernel->run();
exit 0;

