Faça um bot simples de IRC.


10

Tarefa

Faça um bot simples de IRC, que executa tarefas simples como cumprimentar usuário.

Detalhe

(Você pode ver este documento RFC .)

Escreva um programa completo que execute estes:

  1. As entradas do programa nicknamee realnamedo usuário.

    • Todo nicknamee realnamequal formulário [A-Za-z0-9]+deve ser permitido, mas não é importante se outros são permitidos. Por exemplo, se o usuário quiser 1234qwertycomo nicknamee 5319009como realname, o programa deve usar esses nomes, mas não é importante se o programa pode usar ^^☆Rick Astley☆^^(que inclui caracteres não alfabéticos e decimais) como ( nicknameou realname) ou não, mesmo que esse nome possa ser rejeitado pelo servidor.
  2. As entradas serverAddressdo programa do usuário.

    • A forma de serverAddressé serverIP:serverPort, onde serverIPé o endereço IP do servidor e serverPorté o número da porta do servidor.
  3. O programa se conecta à porta serverPortno servidor IRC serverIPe deve definir seu apelido como nicknamee nome real como realnameenviando USER realname 0 * :realnamee NICK nickname.

  4. O programa insere um único channelNameque não inclui #e se junta ao canal #channelName.

  5. Envie uma mensagem privada Hello, world!para o #channelNamecanal assim:PRIVMSG #channelName :Hello, world!

  6. Então, o programa faz o seguinte:

    R. Se alguém entrar, cumprimente-o dizendo Hello, @!para #channelNameonde @ é o apelido dele.

    B. Se o programa for iniciado, tente entrar novamente.

    C. Se uma pessoa for chutada ou banida, diga POW HAHA.

    D. Se uma pessoa sai ( PARTou QUIT), digamos Goodbye, @!, onde @ é o apelido dela.

    E. Se alguém disser algum texto, incluindo Turing testou turing test, diga I'm a human!.

    F. Se alguém disser algum texto incluindo 6*9, saia enviando QUIT :42para o servidor.

    G. Se alguém disser algum texto, incluindo all your base are belong to us(sem distinção entre maiúsculas e minúsculas), saia enviando QUIT :What you say!para o servidor.

    H. Se alguém disser que algum texto anterior com espaço e atos acima não são executados pelo texto, diga a soma do código de todos os caracteres (exceto o primeiro espaço) no texto.

Se ocorrer um erro

Se ocorrer um erro (como erro de conexão ou inválido nickname), você poderá fazer o que deseja. Por exemplo, se ele nicknamejá estiver em uso, o programa poderá parar, obter uma novidade nicknamedo usuário ou alterar automaticamente nicknamee tentar novamente.

Restrição

O programa

  • Não deve usar nenhuma função ou biblioteca interna destinada à criação de clientes / bot de IRC. ou seja, algo como bibliotecas de clientes IRC
  • Deve solicitar o que será inserido, antes de receber uma entrada . Por exemplo, antes entradas serverAddress, deve solicitar Write the address of server:, serverIP:serverPort >, serverAddress >, ou algum texto que o usuário possa reconhecer.
  • Deve funcionar em vários servidores de IRC usando UTF-8. (ou seja, não para servidor único)
  • As mensagens enviadas ao servidor não devem ser NOTICE. (RFC 2812, 3.3.2. Aviso: A diferença entre NOTICEe PRIVMSGé que as respostas automáticas NUNCA DEVEM ser enviadas em resposta a uma NOTICEmensagem.)
  • Deve enviar uma mensagem de onde a solicitação veio ( #channelNameou nickname).
  • Deve PONGquando PINGed, é claro.

PS

Bem, acabei de fazer isso, porque não havia quebra-cabeças sobre o bot de IRC.

Editar

Depois de ler o comentário de @ dmckee, mudei a regra para escolher o vencedor.

  1. Padrão bonus= +0

  2. Se, de alguma forma, o programa puder se conectar a um canal (mesmo que não esteja #channelName), bonus= 1

  3. Se o programa puder executar as etapas 1 a 5, bonus* = 2.

  4. Para cada tarefa A ~ H na etapa 6, se o programa implementar, bonus* = 1.2.

  5. Para cada seis restrições, se o programa seguir isso, bonus* = 1.05.

e score = int(codelength/bonus).

Programa com pontuação mais baixa é vencedor. Se duas respostas tiverem a mesma pontuação, a resposta com mais votos vence.

Edição: Eu acho que 1.2e 1.05nas etapas 4 e 5 devem ser ajustadas um pouco maiores .. O que você acha disso?

O vencedor está decidido, no entanto, acho que houve poucas inscrições.

Qualquer pessoa ainda pode enviar o código ..: P


4
Francamente, não aceitamos muito "Não há métrica, apenas voto". . Você pode trabalhar aqui em termos de configuração de uma métrica objetiva para esta tarefa. Consulte Mensagem de erro falsa para um possível exemplo.
dmckee --- gatinho ex-moderador

@dmckee: Desculpe, eu não sabia que os votos eram bastante subjetivos. :(
JiminP 12/11/11

@JiminP: Nice save.
dmckee --- gatinho ex-moderador

sons irc bot como um golf mais - Estou em embora :)
lunixbochs

esclarecimento: "Se o programa for iniciado, tente entrar novamente." - isso significa do servidor ou do canal?
lunixbochs

Respostas:


1

PHP - 121 pontos

  • 1396 caracteres
  • Segue todas as etapas (incluindo extra) e restrições

Ponto

<?php
$bonus = 1;                             //connects to channel
$bonus *= 2;                            //completes steps 1-5
for ($x=0;$x < 8;$x++) $bonus *= 1.2;   //all 8 extra steps
for ($y=0;$y < 6;$y++) $bonus *= 1.05;  //all 6 restrictions
echo (int)(1396 / $bonus);

> 121

Código

<?php function w($t){global$s;echo$t."\n";socket_write($s,$t."\r\n");}function m($c,$t){w("PRIVMSG $c :$t");}@$y=fgets;$z=STDIN;echo"nickname>";$n=trim($y($z));echo"realname>";$r=trim($y($z));echo"serverIP:Port>";$a=explode(":",trim($y($z)));$s=socket_create(2,1,6);socket_connect($s,$a[0],$a[1]);w("NICK $n");w("USER $n 0 * :$r");while(1){if((!($l=trim(socket_read($s,512,1))))||(!preg_match("/^(?:\:(\S+)[ ]+)?([^: ][^ ]*)(?:[ ]+([^:].*?))?(?:[ ]+:(.+))?$/",$l,$m)))continue;echo$l."\n";if(preg_match("/(.+)!(.+)@(.+)/",$m[1],$o))$m[1]=$o;if(!empty($m[3]))$p=explode(" ",$m[3]);else$p=array();if(isset($m[4])) $p[]=$m[4];$p=array($m[1],$m[2],$p);$b=$p[2][0];@$e=$p[0][1];@$f=$p[2][1];if($p[1]=="PING")w("PONG :".$b);elseif($p[1]=="376"){echo"#channel>";$c=trim($y($z));$c=(!empty($c))?$c:"#rintaun";w("JOIN $c");}elseif($p[1]=="JOIN")if($e!=$n)m($b,"Hello, $e!");else m($b,"Hello, world!");elseif($p[1]=="KICK")if($f!=$n)m($b,"POW HAHA");else w("JOIN ".$b);elseif(($p[1]=="PART")&&($e!=$n))m($b,"Goodbye, $e!");elseif(($p[1]=="QUIT")&&($e!=$n))m($c,"Goodbye, $e!");elseif($p[1]=="PRIVMSG")if(preg_match("/[Tt]uring test/",$f))m(($b==$n)?$e:$b,"I'm a human!");elseif(strstr($f,"6*9")){w("QUIT :42");break;}elseif(stristr($f,"all your base are belong to us")){w("QUIT :What you say!");break;}elseif($f[0]==" "){$q=str_split(substr($f,1));$u=0;foreach($q AS $d)$u+=ord($d);m(($b==$n)?$e:$b,$u);}}

Nota

Minha resposta realmente difere das instruções muito ligeiramente; as instruções dizem para usar o realnamecomo o primeiro parâmetro do USERcomando ao registrar, mas usei o apelido. Isso ocorre porque realnameé permitido ter espaços, enquanto esse parâmetro não é. É um ponto discutível, no entanto, uma vez que mudar a variável para realnameseria exatamente a mesma contagem de caracteres.


5

Python - 125 pontos

  • 304 caracteres
  • segue as etapas de 1 a 5 (funciona para mim em irc.freenode.net:6667. se você tentar lá, lembre-se de que o IDENT pode demorar um pouco, portanto, aguarde mais de 20 segundos para conectar e falar)
  • segue 4 restrições (assumindo que a restrição NOTICE é um pouco incerta. a restrição UTF conta porque o python não engasga se não precisar analisar nenhum UTF).

pontuação matemática (python):

bonus = 1 # connects to channel
bonus *= 2 # steps 1-5
for i in xrange(4):
    bonus *= 1.05 # 4 restrictions

int(304.0/bonus)
> 125

código:

import socket
i=raw_input
u=i('user# ')
n=i('nick# ')
h,p=i('host:port# ').split(':',1)
p=int(p)
c='#'+i('chan# ')
z=0
while 1:
 try:
  def s(m): z.send(m+'\r\n')
  z.recv(9)
 except:
  z=socket.socket();z.connect((h,p));s('USER '+n+' 0 * :'+n);s('NICK '+n);s('JOIN '+c);s('PRIVMSG '+c+' :Hello, world!')

5

Perl, 66 pontos

  • 666 caracteres
  • todas as subetapas
  • metade das restrições

Ponto

use 5.010;
$bonus = 1;              # connects to channel
$bonus *= 2;             # steps 1 to 5
$bonus *= 1.2 for 1..8;  # substeps A to H
$bonus *= 1.05 for 1..3; # restrictions 3, 4, 6
say int(666 / $bonus);
> 66

Código

(novas linhas apenas para apresentação, não contadas e muito menos aceitáveis)

use POE"Component::IRC";$_='sub _start{Zregister,all);Z"connect")}subX001{
Zjoin=>$c);ZY"Hello, world!")}*Xquit=*Xpart=*Xjoin=sub{$g=$_[STATE]=~/t/?G
oodbye:Hello;$_=$_[ARG0];/\w+/;ZY"$g, $&!")};subXkick{$_=$_[ARG2];/\w+/;Z$
&eq$n?"join":Y"POW HAHA")}subXpublic{$_=$_[ARG2];if(/turing test/i){ZY"I\'
m a human!")}elsif(/6\*9/){Zquit,42)}elsif(/all your base are belong to us
/i){Zquit,"What you say!")}elsif(/^ /){$t=-32;$t+=ord for/./g;ZY$t)}}chop(
($n,$r,$s,$c)=<>);$c="#$c";$i=POE::Component::IRC->spawn(nick,$n,ircname,$
r,server,$s)';s/Z/\$i->yield(/g;s/Y/privmsg,\$c,/g;S/X/ irc_/g;eval;POE::S
ession->create(package_states,[main,[grep*$_{CODE},%::]]);POE::Kernel->run

Nota

A subetapa "TODA A SUA BASE ESTÁ PERTENCE A NÓS" provavelmente não vale sua contagem de caracteres, mas se eu a soltasse, não teria a boa contagem de caracteres. Bugger.


+1 para 66 pontos e 666 caracteres. Isso é intencional ou você conseguiu isso por acidente?
precisa saber é o seguinte

@ nyuszika7h Eu sinceramente não me lembro.
JB

2

Ruby, 28 pontos

Ponto

bonus = 0       # We've done nothing yet
bonus += 1      # Connects to channel
bonus *= 2      # Step 1 - 5

for n in 1..7
    bonus *= 1.2    # A - G
end

for n in 1..4
    bonus *= 1.05   # 4 constraints
end

puts (249/bonus).to_i
>  28

Código

require 'zlib'
b=<<'E'
x�]�_o�0���)��q�-KFBcdf��߃�P�S�B�����(N�Л��s~�� ��(�_$U6��5G�)�r�BB������J�{��� nNhlO�f)QQdJ�g��'�yP�!!����K�ɫ��[Ё�Ə{0�F]ѽ�m�2���GŐP��p`   ��I����E�+�* z�                                                                                                                                                           )jrmKR�ˮ�%�
#��nQaJ�H��<�ZT���虦T3.�$D('�hw��a�/'��&�_ei�}o��1���M$����H��J�$��������V"���"��'��|A�`<��3L)Y��Z|� e�� ���m�é��ǚ�ڎu��J�����Vq~(ح�
E
eval Zlib::Inflate.new.inflate b

2

Ruby, 65 pontos

  • 574 Chars
  • Etapas 1-5, 6 (AG) e restrições sobre libs, UTF-8, sem aviso e PONG
  • Recebe argumentos da linha de comando na forma de servidor: 6667 botnick botuser channel

Ponto

bonus = 0       # We've done nothing yet
bonus += 1      # Connects to channel
bonus *= 2      # Step 1 - 5

for n in 1..7
    bonus *= 1.2    # A - G
end

for n in 1..4
    bonus *= 1.05   # 4 constraints
end

puts (574/bonus).to_i
> 65

Código

require'socket'
a=ARGV
c="##{a[3]}"
h,p=a[0].split':'
s=TCPSocket.open(h,p)
m="PRIVMSG #{c} :"
s.puts"USER #{a[2]} 0 * :#{a[2]}\nNICK #{a[1]}\nJOIN #{c}\n#{m}Hello, world!"
while l=s.gets
case l
when/\:(.+?)!(.+)JOIN/
s.puts"#{m}Hello, #{$1}!"
when/KICK (.+?) (.+?) \:(.+)/
if $2==a[1]
s.puts"JOIN #{c}"
else
s.puts"#{m}POW HAHA"
end
when/\:(.+?)\!(.+)(PART|QUIT)/
s.puts"#{m}Goodbye, #{$1}!"
when/turing test/i
s.puts"#{m}I'm a human!"
when/6\*9/
s.puts"QUIT :42"
when/all your base are belong to us/i
s.puts"QUIT :What you say!"
when/PING \:(.+)/
puts"PONG #{$1}"
end
end
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.