Stwórz prostego bota IRC.


10

Zadanie

Stwórz prostego bota IRC, który wykonuje proste zadanie, takie jak powitanie użytkownika.

Szczegół

(Możesz zobaczyć ten dokument RFC .)

Napisz kompletny program, który wykona następujące czynności:

  1. Dane wejściowe programu nicknamei realnameod użytkownika.

    • Wszystko nicknamei realnamektóra forma jest [A-Za-z0-9]+dozwolona, ​​ale nie jest ważne, czy dozwolone są inne formularze. Na przykład, jeśli użytkownik chce 1234qwertyjak nicknamei 5319009jak realname, program powinien używać tych nazw, ale nie jest ważne, czy program może używać ^^☆Rick Astley☆^^(w tym nie alfabetu i dziesiętnych) jako ( nicknamelub realname), czy nawet nie, nawet sądząc, że ta nazwa może zostać odrzucona przez serwer.
  2. Dane wejściowe programu serverAddressod użytkownika.

    • Formą serverAddressjest serverIP:serverPort, gdzie serverIPjest adres IP serwera i serverPortnumer portu serwera.
  3. Program łączy się z portem serverPortna serwerze IRC serverIPi powinien ustawić swój pseudonim jako nicknamei prawdziwą nazwę jako realnamewysyłając USER realname 0 * :realnamei NICK nickname.

  4. Program wprowadza singiel, channelNamektóry nie zawiera #i dołącza do kanału #channelName.

  5. Wyślij prywatną wiadomość Hello, world!do #channelNamekanału w ten sposób:PRIVMSG #channelName :Hello, world!

  6. Następnie program wykonuje następujące czynności:

    A. Jeśli ktoś dołączy, powitaj go, mówiąc Hello, @!do #channelName, gdzie @ to jego / jej pseudonim.

    B. Jeśli program zostanie uruchomiony, spróbuj ponownie dołączyć.

    C. Jeśli ktoś zostanie wyrzucony lub zbanowany, powiedzmy POW HAHA.

    D. Jeśli dana osoba opuszcza ( PARTlub QUIT), powiedzmy Goodbye, @!, gdzie @ jest jej pseudonimem.

    E. Jeśli ktoś powie jakiś tekst, w tym Turing testlub turing test, powiedzmy I'm a human!.

    F. Jeśli ktoś powie coś, w tym tekst 6*9, wyjdź, wysyłając QUIT :42na serwer.

    G. Jeśli ktoś powie jakiś tekst, w tym all your base are belong to us(bez rozróżniania wielkości liter), wyjdź, wysyłając QUIT :What you say!na serwer.

    H. Jeśli ktoś powie, że tekst poprzedzony spacją i powyższe akty nie są wykonywane przez tekst, powiedz sumę znaków kodowych wszystkich znaków (z wyjątkiem pierwszej spacji) w tekście.

Jeśli wystąpi błąd

Jeśli wystąpi błąd (taki jak błąd połączenia lub nieprawidłowy nickname), możesz zrobić to, co chcesz. Na przykład, jeśli program nicknamejest już w użyciu, program może zatrzymać się, pobrać nowy nicknameod użytkownika lub automatycznie zmienić nicknamei ponowić próbę.

Ograniczenie

Program

  • Nie powinien używać żadnych wewnętrznych funkcji ani bibliotek, które służą do tworzenia klienta / bota IRC. tj. coś w rodzaju bibliotek klienta IRC
  • Powinien zapytać, co wprowadzi, zanim otrzyma dane wejściowe . Na przykład, przed wejściami serverAddress, powinno skłonić Write the address of server:, serverIP:serverPort >, serverAddress >, lub jakiś tekst, że użytkownik może rozpoznać.
  • Powinien działać na kilku serwerach IRC korzystających z UTF-8. (tj. nie dla pojedynczego serwera)
  • Wiadomości wysyłane na serwer nie powinny NOTICE. (RFC 2812, 3.3.2 Uwaga: Różnica między NOTICEi PRIVMSGpolega na tym, że automatyczne odpowiedzi NIGDY nie powinny być wysyłane w odpowiedzi na NOTICEwiadomość.)
  • Powinien wysłać wiadomość, z której pochodzi żądanie ( #channelNamelub nickname).
  • Należy PONGprzy PINGed, oczywiście.

PS

Właśnie to zrobiłem, ponieważ nie było żadnej łamigłówki na temat bota IRC.

Edytować

Po przeczytaniu komentarza @ dmckee zmieniłem zasadę wyboru zwycięzcy.

  1. Domyślnie bonus= +0

  2. Jeśli w jakiś sposób program może połączyć się z kanałem (nawet jeśli nie jest #channelName), bonus= 1

  3. Jeśli program może wykonać kroki 1 ~ 5, bonus* = 2.

  4. Dla każdego zadania A ~ H w kroku 6, jeśli program implementuje, bonus* = 1.2.

  5. Dla każdego sześciu ograniczeń, jeśli program postępuje zgodnie z tym, bonus* = 1.05.

a score = int(codelength/bonus).

Program z najniższym wynikiem jest zwycięzcą. Jeśli dwie odpowiedzi mają ten sam wynik, wygrywa odpowiedź z największą liczbą głosów.

EDIT Edycja: Myślę, że 1.2i 1.05w kroku 4 i 5 powinny być dostosowane nieco większe .. Co sądzisz na ten temat?

Zwycięzca jest zdecydowany, jednak myślę, że było za mało zgłoszeń.

Nadal każdy może przesłać kod ..: P


4
Szczerze mówiąc, nie bardzo akceptujemy „Nie ma danych, wystarczy głosować”. . Jest kilka rzeczy, z którymi warto tu pracować, jeśli chodzi o konfigurację obiektywnych wskaźników dla tego zadania. Zobacz fałszywy komunikat o błędzie do ewentualnego przykładu.
dmckee --- były moderator kotek

@dmckee: Przepraszam, nie wiedziałem, że głosy były dość subiektywne .. :(
JiminP

@JiminP: Niezły zapis.
dmckee --- były moderator kociak

irc bot brzmi jak dłuższy golf - jestem w nim :)
lunixbochs,

wyjaśnienie: „Jeśli program zostanie uruchomiony, spróbuj ponownie dołączyć”. - czy to oznacza z serwera czy kanału?
lunixbochs

Odpowiedzi:


1

PHP - 121 punktów

  • 1396 znaków
  • Wykonuje wszystkie kroki (w tym dodatkowe) i ograniczenia

Wynik

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

Kod

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

Dygresja

Moja odpowiedź w rzeczywistości bardzo różni się od instrukcji; instrukcje mówią, aby użyć realnamejako pierwszy parametr USERpolecenia podczas rejestracji, ale zamiast tego użyłem pseudonimu. Wynika to z faktu, że realnamedozwolone są spacje, podczas gdy ten parametr nie jest. Jest to jednak kwestia sporna, ponieważ włączenie zmiennej dla realnamebędzie dokładnie taką samą liczbą znaków.


5

Python - 125 punktów

  • 304 znaki
  • postępuje zgodnie z krokami 1-5 (działa dla mnie na irc.freenode.net:6667. jeśli spróbujesz tam, pamiętaj, że IDENT może trochę potrwać, więc daj mu ponad 20 sekund na połączenie i rozmowę)
  • przestrzega 4 ograniczeń (zakładając, że ograniczenie NOTICE jest nieco niejasne. ograniczenie UTF się liczy, ponieważ python nie będzie się dusił, jeśli nie będzie musiał analizować żadnego UTF).

wynik matematyki (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

kod:

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 punktów

  • 666 znaków
  • wszystkie podetapy
  • połowa ograniczeń

Wynik

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

Kod

(nowe wiersze tylko do prezentacji, nie liczone, a tym bardziej dopuszczalne)

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

Dygresja

Podetap „WSZYSTKIE PODSTAWY SĄ NALEŻY DO NAS” najprawdopodobniej nie jest wart swojej liczby postaci, ale gdybym ją upuścił, nie miałbym dobrej liczby postaci. Facet.


+1 za 66 punktów i 666 znaków. Czy to celowe, czy dostałeś to przez przypadek?
nyuszika7h

@ nyuszika7h Szczerze nie pamiętam.
JB

2

Ruby, 28 punktów

Wynik

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

Kod

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 punktów

  • 574 znaki
  • Kroki 1-5, 6 (AG) i ograniczenia dotyczące bibliotek lib, UTF-8, brak UWAGA i PONG
  • Przyjmuje argumenty wiersza poleceń w postaci serwera: 6667 botuser kanał botuser

Wynik

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

Kod

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.