간단한 IRC 봇을 만드십시오.


10

직무

인사말 사용자와 같은 간단한 작업을 수행하는 간단한 IRC 봇을 만듭니다.

세부 묘사

( 이 RFC 문서를 볼 수 있습니다 .)

다음을 수행하는 완전한 프로그램을 작성하십시오.

  1. 프로그램 입력 nicknamerealname사용자.

    • 모두 nicknamerealname어떤 형식이 [A-Za-z0-9]+허용되어야하지만 다른 형식이 허용되는지는 중요하지 않습니다. 예를 들어, 사용자가 1234qwertyas nickname5319009as를 원하면 realname프로그램에서 해당 이름을 사용해야하지만 프로그램 ^^☆Rick Astley☆^^에서 알파벳이 아닌 (소수자가 아닌) 포함 ( nickname또는 realname)을 사용할 수 있는지 여부는 중요 하지 않습니다. 서버에 의해.
  2. serverAddress사용자가 프로그램을 입력 합니다.

    • 형식은 serverAddress입니다 serverIP:serverPort. 여기서 serverIP서버의 IP 주소는 서버 serverPort의 포트 번호입니다.
  3. 포트에이 프로그램은 커넥트 serverPortIRC 서버에서 serverIP, 그리고 그것의 별명으로 설정해야합니다 nickname같이 realname을 realname보내 USER realname 0 * :realnameNICK nickname.

  4. 프로그램은를 channelName포함하지 않는 싱글 을 입력 #하고 채널에 참여합니다 #channelName.

  5. 다음 과 같이 채널에 비공개 메시지 Hello, world!를 보내십시오 #channelName.PRIVMSG #channelName :Hello, world!

  6. 그런 다음 프로그램은 다음을 수행합니다.

    A. 누군가가 참여하는 경우 @에게 그 사람의 닉네임 이라고 말 Hello, @!하여 인사합니다 #channelName.

    B. 프로그램이 시작되면 다시 참여하십시오.

    C. 사람이 쫓겨나거나 금지당하는 경우이라고 말합니다 POW HAHA.

    D. 사람이 ( PART또는 QUIT) 떠날 경우 Goodbye, @!, @는 그 사람의 별명입니다.

    E. 만약 누군가가 일부 텍스트가 포함 말한다 Turing test거나 turing test, 말을 I'm a human!.

    F. 누군가가을 포함한 일부 텍스트를 말하면 서버 6*9로 전송 QUIT :42하여 종료 하십시오.

    G. 누군가가 all your base are belong to us(대소 문자를 구분하지 않음)을 포함한 텍스트를 말하면 QUIT :What you say!서버 로 전송 하여 종료 하십시오.

    H. 누군가 앞에 공백이 있고 위의 동작이 텍스트에 의해 수행되지 않는다고 말하면 텍스트의 모든 문자 (첫 번째 공백 제외)의 문자 코드 합계를 말합니다.

에러가 발생한 경우

연결 오류 또는 invalid와 같은 오류 nickname가 발생하면 원하는 작업을 수행 할 수 있습니다. 예를 들어, nickname프로그램이 이미 사용중인 경우 프로그램이 중지 nickname되거나 사용자로부터 새로운 정보 를 얻 거나 자동으로 nickname및 재 시도를 할 수 있습니다.

제한

프로그램

  • IRC 클라이언트 / 봇 제작을위한 내부 기능 또는 라이브러리를 사용하지 않아야합니다. 즉, IRC 클라이언트 라이브러리와 같은 것
  • 해야 그것이 입력을 취득하기 전에 무엇을 입력거야, 프롬프트 . 예를 들어, 입력하기 전에 serverAddress,이 메시지를 표시한다 Write the address of server:, serverIP:serverPort >, serverAddress >, 텍스트 또는 사용자가 인식 할 수있다.
  • UTF-8을 사용하는 여러 IRC 서버에서 작동해야합니다. (즉, 단일 서버가 아닌)
  • 서버로 전송되는 메시지는 없어야합니다 NOTICE. (RFC 2812 3.3.2주의 : 차이 NOTICEPRIVMSG자동 응답에 대한 응답으로 전송되지 않을해야한다는 NOTICE메시지).
  • ( #channelName또는 nickname) 에서 요청을 보낸 메시지를 보내야합니다 .
  • 해야 PONG할 때 PING물론, 에드.

추신

글쎄, IRC 봇에 대한 퍼즐이 없었기 때문에 방금 이것을 만들었습니다.

편집하다

@dmckee의 의견을 읽은 후 우승자를 선택하는 규칙을 변경했습니다.

  1. 기본값 bonus= +0

  2. 프로그램이 어떻게 든 채널에 연결할 수 있다면 ( 1이 아닌 경우에도 #channelName), bonus= 1

  3. 프로그램이 1 ~ 5 단계를 수행 할 수 있으면 bonus* = 2입니다.

  4. 6 단계의 각 태스크 A ~ H에 대해 프로그램이 구현하는 경우 bonus* = 1.2.

  5. 6 가지 제한 사항마다 프로그램이 다음을 준수하면 bonus* = 1.05.

그리고 score = int(codelength/bonus).

가장 낮은 점수를받은 프로그램이 승자입니다. 두 답변의 점수가 같으면 가장 높은 표를 얻은 답변이 승리합니다.

편집 편집 : 나는 생각 1.2하고 1.054 단계와 5 단계에서 약간 더 크게 조정해야합니다. 이것에 대해 어떻게 생각하십니까?

우승자가 결정되었지만 출품작이 너무 적다고 생각합니다.

누구든지 여전히 코드를 제출할 수 있습니다 .. : P


4
솔직히 우리는 "메트릭이없고 투표 만한다"는 것을 받아들이지 않았습니다 . . 이 작업에 대한 객관적인 메트릭 설정과 관련하여 여기에서 작업 할 사항이 있습니다 . 가능한 예는 가짜 오류 메시지 를 참조하십시오 .
dmckee --- 전 변조 고양이 새끼

@dmckee : 죄송합니다, 투표가 매우 주관적인지 몰랐습니다 .. :(
JiminP

@JiminP : 멋진 저장.
dmckee --- 전

IRC 봇 소리는 더 이상 골프처럼 - 나는 :) 생각에서 해요
lunixbochs

설명 : "프로그램이 시작되면 다시 참여하십시오." -이것은 서버 또는 채널에서 의미합니까?
lunixbochs 2012 년

답변:


1

PHP-121 포인트

  • 1396 자
  • 모든 단계 (추가 포함) 및 제한 사항 준수

점수

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

암호

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

사이드 노트

내 대답은 실제로 지침과 약간 다릅니다. 지시 사항은 등록 할 때 명령 realname의 첫 번째 매개 변수로 를 사용한다고 말하지만 USER별명을 대신 사용했습니다. 이는 realname공백이 허용되는 반면이 매개 변수는 허용되지 않기 때문입니다. 그러나 변수를 바꾸는 realname것이 정확히 동일한 문자 수 이기 때문에 문제의 여지 가 있습니다.


5

파이썬-125 포인트

  • 304 자
  • 1-5 단계를 따릅니다 (irc.freenode.net:6667에서 작동합니다). 시도하면 IDENT에 시간이 걸릴 수 있으므로 연결하고 말하기에 20 초 이상이 걸립니다.
  • 4 가지 제한 사항을 따릅니다 (조금 명확하지 않은 NOTICE 제한을 가정합니다. UTF 제한 사항은 파이썬이 UTF를 구문 분석 할 필요가없는 경우 질식하지 않기 때문에 계산됩니다).

수학 점수 (파이썬) :

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

암호:

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

펄, 66 포인트

  • 666 자
  • 모든 하위 단계
  • 제한의 절반

점수

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

암호

(프레젠테이션 전용 줄만, 허용 할 수있는 것은 아닙니다)

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

사이드 노트

"모든 당신의 기지는 우리에게 속합니다"하위 단계는 아마도 그 문자 수의 가치가 없을 것입니다. 도청 전문가.


66 포인트와 666 자에 +1 의도적입니까, 우연히 얻었습니까?
nyuszika7 시간

@ nyuszika7h 나는 솔직히 기억 나지 않는다.
JB

2

루비, 28 포인트

  • 249 문자
  • 다른 솔루션과 같은 봇이지만 압축을 적용하여 약간의 부정 행위가 있습니다.
  • http://coolfire.insomnia247.nl/golfbot-inflate.rb (이 코드를 붙여 넣으면 너무 잘 작동하지 않을 수 있습니다.)

점수

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

암호

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

루비, 65 포인트

  • 574 문자
  • 1-5, 6 단계 (AG) 및 libs에 대한 제한 사항, UTF-8, NOTICE & PONG
  • server : 6667 botnick botuser 채널 형식으로 명령 행 인수를 사용합니다.

점수

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

암호

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
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.