Créez un bot IRC simple.


10

Tâche

Créez un bot IRC simple qui fait une tâche simple comme saluer l'utilisateur.

Détail

(Vous pouvez voir ce document RFC .)

Écrivez un programme complet qui les exécute:

  1. Les entrées du programme nicknameet realnamede l'utilisateur.

    • Tout nicknameet realnamequel formulaire [A-Za-z0-9]+doit être autorisé, mais il n'est pas important que d'autres formulaires soient autorisés. Par exemple, si l'utilisateur veut au 1234qwertyfur nicknameet à 5319009mesure realname, le programme doit utiliser ces noms, mais il n'est pas important que le programme puisse utiliser ^^☆Rick Astley☆^^(qui inclut les caractères non alphabétiques et décimaux) comme ( nicknameou realname) ou non, même si ce nom peut être rejeté par le serveur.
  2. Le programme serverAddressentre de l'utilisateur.

    • La forme de serverAddressest serverIP:serverPort, où serverIPest l'adresse IP du serveur et serverPortle numéro de port du serveur.
  3. Le programme se connecte au port serverPortsur le serveur IRC serverIP, et il doit définir son pseudo as nicknameet realname as realnameen envoyant USER realname 0 * :realnameet NICK nickname.

  4. Le programme entre un single channelNamequi n'inclut pas #et rejoint le canal #channelName.

  5. Envoyez un message privé Hello, world!à la #channelNamechaîne comme ceci:PRIVMSG #channelName :Hello, world!

  6. Ensuite, le programme procède comme suit:

    A. Si quelqu'un se joint, le saluer en disant Hello, @!à #channelName, où @ est le surnom de lui / elle.

    B. Si le programme est lancé, essayez de vous réinscrire.

    C. Si une personne est expulsée ou bannie, dites POW HAHA.

    D. Si une personne quitte ( PARTou QUIT), disons Goodbye, @!, où @ est son surnom.

    E. Si quelqu'un dit du texte, y compris Turing testou turing test, disons I'm a human!.

    F. Si quelqu'un dit du texte 6*9, quittez en envoyant QUIT :42au serveur.

    G. Si quelqu'un dit du texte, y compris all your base are belong to us(insensible à la casse), quittez en envoyant QUIT :What you say!au serveur.

    H. Si quelqu'un dit qu'un texte précédé d'un espace et au-dessus des actes n'est pas exécuté par le texte, dites la somme du code de tous les caractères (sauf le premier espace) dans le texte.

En cas d'erreur

Si une erreur (telle qu'une erreur de connexion ou non valide nickname) s'est produite, vous pouvez faire ce que vous voulez faire. Par exemple, si le nicknameest déjà utilisé, le programme peut s'arrêter, en obtenir un nouveau nicknamede l'utilisateur ou modifier automatiquement le nicknameet réessayer.

Restriction

Le programme

  • Ne doit pas utiliser de fonctions ou de bibliothèques internes destinées à la création de clients / bots IRC. c'est-à-dire quelque chose comme les bibliothèques clientes IRC
  • Devrait demander ce qu'il entrera avant qu'il ne reçoive une entrée . Par exemple, avant les entrées serverAddress, il doit inviter Write the address of server:, serverIP:serverPort >, serverAddress >ou un texte que l'utilisateur peut reconnaître.
  • Devrait fonctionner sur plusieurs serveurs IRC utilisant UTF-8. (c'est-à-dire pas pour un seul serveur)
  • Les messages envoyés au serveur ne devraient pas l'être NOTICE. (RFC 2812, 3.3.2 Remarque: la différence entre NOTICEet PRIVMSGest que les réponses automatiques NE DOIVENT JAMAIS être envoyées en réponse à un NOTICEmessage.)
  • Devrait envoyer un message d'où provenait la demande ( #channelNameou nickname).
  • Devrait PONGquand PINGed, bien sûr.

PS

Eh bien, je viens de le faire, car il n'y avait pas de puzzle sur le bot IRC.

Éditer

Après avoir lu le commentaire de @ dmckee, j'ai changé la règle pour choisir le gagnant.

  1. Par défaut bonus= +0

  2. Si le programme peut se connecter à une chaîne (même si ce n'est pas le cas #channelName), bonus= 1

  3. Si le programme peut exécuter les étapes 1 à 5, bonus* = 2.

  4. Pour chaque tâche A ~ H à l'étape 6, si le programme implémente, bonus* = 1.2.

  5. Pour chaque six restrictions, si le programme suit cela, bonus* = 1.05.

et score = int(codelength/bonus).

Le programme avec le score le plus bas est gagnant. Si deux réponses ont le même score, alors la réponse avec les votes les plus élevés l'emporte.

EDIT Edit: Je pense 1.2et 1.05aux étapes 4 et 5 devrait être ajusté légèrement plus grand .. Que pensez-vous de cela?

Le gagnant est décidé, cependant, je pense qu'il y avait trop peu d'inscriptions.

N'importe qui peut toujours soumettre le code ..: P


4
Franchement, nous n’avons pas été très enthousiastes à l’égard de «Il n’ya pas de mesure, votez simplement». . Il y a des choses avec lesquelles vous pouvez travailler ici en termes de configuration d' une mesure objective pour cette tâche. Voir Faux message d'erreur pour un exemple possible.
dmckee --- chaton ex-modérateur

@dmckee: Désolé, je ne savais pas que les votes étaient assez subjectifs .. :(
JiminP

@JiminP: Belle sauvegarde.
dmckee --- chaton ex-modérateur

irc bot sonne comme un golf plus long - je suis quand même :)
lunixbochs

clarification: "Si le programme est lancé, essayez de vous réinscrire." - cela signifie-t-il depuis le serveur ou le canal?
lunixbochs

Réponses:


1

PHP - 121 points

  • 1396 caractères
  • Suit toutes les étapes (y compris les extras) et les restrictions

But

<?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

Code

<?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);}}

Note latérale

Ma réponse diffère en fait très légèrement des instructions; les instructions indiquent d'utiliser le realnamecomme premier paramètre de la USERcommande lors de l'inscription, mais j'ai utilisé le surnom à la place. C'est parce que le realnameest autorisé à avoir des espaces, alors que ce paramètre ne l'est pas. C'est quelque chose d'un point discutable, car le fait de basculer dans la variable pour realnameaurait le même nombre de caractères.


5

Python - 125 points

  • 304 caractères
  • suit les étapes 1 à 5 (fonctionne pour moi sur irc.freenode.net:6667. si vous essayez là-bas, rappelez-vous que IDENT peut prendre un certain temps, alors donnez-lui plus de 20 secondes pour vous connecter et parler)
  • suit 4 restrictions (en supposant la restriction NOTICE qui est un peu floue. la restriction UTF compte parce que python ne s'étouffera pas s'il n'a pas besoin d'analyser un UTF).

mathématiques des scores (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

code:

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 points

  • 666 caractères
  • toutes les sous-étapes
  • la moitié des restrictions

But

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

Code

(nouvelles lignes pour présentation seulement, non comptées et encore moins acceptables)

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

Note latérale

La sous-étape "TOUTE VOTRE BASE NOUS APPARTIENT" ne vaut probablement pas son nombre de caractères, mais si je le laissais tomber, je n'aurais pas le bon nombre de caractères. Bugger.


+1 pour 66 points et 666 caractères. Est-ce intentionnel ou avez-vous obtenu cela par accident?
nyuszika7h

@ nyuszika7h Honnêtement, je ne me souviens pas.
JB

2

Rubis, 28 points

But

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

Code

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

Rubis, 65 points

  • 574 caractères
  • Étapes 1 à 5, 6 (AG) et restrictions sur les bibliothèques, UTF-8, aucun AVIS ET PONG
  • Prend des arguments de ligne de commande sous la forme d'un serveur: 6667 botnick botuser channel

But

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

Code

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
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.