ทำบอท IRC ง่าย ๆ


10

งาน

ทำบอท IRC อย่างง่ายซึ่งทำหน้าที่ง่าย ๆ เช่นผู้ใช้อวยพร

รายละเอียด

(คุณอาจเห็นเอกสาร RFCนี้)

เขียนโปรแกรมที่สมบูรณ์ซึ่งทำสิ่งเหล่านี้:

  1. โปรแกรมอินพุตnicknameและrealnameจากผู้ใช้

    • ควรอนุญาตให้ใช้แบบฟอร์มทั้งหมดnicknameและrealnameแบบฟอร์ม[A-Za-z0-9]+ใดก็ได้ แต่ไม่สำคัญว่าจะอนุญาตให้ใช้รูปแบบอื่นได้หรือไม่ ตัวอย่างเช่นหากผู้ใช้ต้องการ1234qwertyเป็นnicknameและ5319009เป็นrealnameโปรแกรมควรใช้ชื่อเหล่านั้น แต่มันไม่สำคัญว่าโปรแกรมสามารถใช้^^☆Rick Astley☆^^(ซึ่งรวมถึงที่ไม่ใช่ตัวอักษรและทศนิยม) เป็น ( nicknameหรือrealname) หรือแม้กระทั่งคิดว่าชื่อนี้อาจถูกปฏิเสธ โดยเซิร์ฟเวอร์
  2. โปรแกรมอินพุตserverAddressจากผู้ใช้

    • รูปแบบของserverAddressคือserverIP:serverPortที่ไหนserverIPคือที่อยู่ IP ของเซิร์ฟเวอร์และserverPortเป็นจำนวนพอร์ตของเซิร์ฟเวอร์
  3. โปรแกรมที่เชื่อมต่อกับพอร์ตserverPortที่เซิร์ฟเวอร์ IRC serverIPและควรตั้งค่าเป็นชื่อเล่นnicknameและ realname เป็นrealnameโดยการส่งและUSER realname 0 * :realnameNICK nickname

  4. โปรแกรมปัจจัยเดียวchannelNameซึ่งไม่รวมถึงและเข้าร่วมช่อง##channelName

  5. ส่งข้อความส่วนตัวHello, world!ถึง#channelNameช่องดังนี้:PRIVMSG #channelName :Hello, world!

  6. จากนั้นโปรแกรมทำสิ่งเหล่านี้:

    ตอบ: ถ้ามีคนเข้าร่วมทักทายเขาโดยกล่าวว่าHello, @!การ#channelNameที่ @ เป็นชื่อเล่นของเขา / เธอ

    B. หากโปรแกรมถูกเตะให้ลองเข้าร่วมอีกครั้ง

    C. POW HAHAถ้าคนที่ถูกเตะหรือห้ามพูด

    D. หากมีคนออก ( PARTหรือQUIT) ให้พูดGoodbye, @!โดยที่ @ เป็นชื่อเล่นของเขา / เธอ

    อีถ้ามีคนพูดข้อความบางส่วนรวมถึงTuring testหรือพูดturing testI'm a human!

    F. หากมีคนพูดถึงข้อความบางอย่างรวมถึง6*9ให้ออกจากการส่งQUIT :42ไปยังเซิร์ฟเวอร์

    G. ถ้ามีคนบอกว่ามีข้อความบางอย่างรวมถึงall your base are belong to us(ตัวพิมพ์เล็กและตัวพิมพ์ใหญ่) ให้เลิกโดยส่งQUIT :What you say!ไปที่เซิร์ฟเวอร์

    H. หากมีคนพูดว่าข้อความที่อยู่ข้างหน้าช่องว่างและการกระทำข้างต้นไม่ได้ถูกดำเนินการโดยข้อความให้พูดผลรวมของตัวอักษรทั้งหมด (ยกเว้นช่องว่างแรก) ในข้อความ

หากมีข้อผิดพลาดเกิดขึ้น

หากเกิดข้อผิดพลาด (เช่นข้อผิดพลาดการเชื่อมต่อหรือไม่ถูกต้องnickname) คุณสามารถทำสิ่งที่คุณต้องการ ตัวอย่างเช่นหากnicknameมีการใช้งานอยู่แล้วโปรแกรมอาจหยุดรับสิ่งใหม่nicknameจากผู้ใช้หรือเปลี่ยนnicknameและลองใหม่โดยอัตโนมัติ

การ จำกัด

โปรแกรม

  • ไม่ควรใช้ฟังก์ชั่นภายในหรือไลบรารีที่มีไว้สำหรับลูกค้า IRC / การทำบอท เช่นสิ่งที่ต้องการห้องสมุดลูกค้า IRC
  • ควรแจ้งให้สิ่งที่มันจะป้อนข้อมูลก่อนที่จะได้รับการป้อนข้อมูล ตัวอย่างเช่นก่อนปัจจัยการผลิตserverAddressก็ควรแจ้งให้Write the address of server:, serverIP:serverPort >, serverAddress >หรือข้อความบางอย่างที่ผู้ใช้สามารถรับรู้
  • ควรทำงานกับเซิร์ฟเวอร์ IRC หลายเครื่องโดยใช้ UTF-8 (เช่นไม่ใช่สำหรับเซิร์ฟเวอร์เดียว)
  • NOTICEข้อความของส่งไปยังเซิร์ฟเวอร์ไม่ควรจะเป็น (RFC 2812, 3.3.2 ข้อสังเกต: ความแตกต่างระหว่างNOTICEและPRIVMSGคือการตอบกลับอัตโนมัติจะต้องไม่ถูกส่งไปตอบกลับNOTICEข้อความ)
  • ควรส่งข้อความที่มาจากคำขอ ( #channelNameหรือnickname)
  • PONGเมื่อควรPINGเอ็ดแน่นอน

PS

ฉันเพิ่งทำสิ่งนี้เพราะไม่มีปริศนาเกี่ยวกับบอทของ IRC

แก้ไข

หลังจากอ่านความคิดเห็นของ @ dmckee ฉันเปลี่ยนกฎสำหรับการเลือกผู้ชนะ

  1. ค่าเริ่มต้นbonus= +0

  2. ถ้าอย่างใดโปรแกรมสามารถเชื่อมต่อกับช่องสัญญาณ (แม้ว่าจะไม่ใช่#channelName), bonus= 1

  3. หากโปรแกรมสามารถทำตามขั้นตอนที่ 1 ~ 5, bonus* = 2

  4. สำหรับแต่ละงาน ~ H ในขั้นตอนที่ 6 ถ้าการดำเนินการโปรแกรมbonus* 1.2=

  5. สำหรับแต่ละหกข้อ จำกัด หากโปรแกรมดังต่อไปนี้ที่bonus* 1.05=

score = int(codelength/bonus)และ

โปรแกรมที่มีคะแนนต่ำสุดเป็นผู้ชนะ หากคำตอบสองข้อมีคะแนนเท่ากันคำตอบที่มีคะแนนสูงสุดจะเป็นฝ่ายชนะ

แก้ไขแก้ไข: ฉันคิดว่า1.2และ1.05ในขั้นตอนที่ 4 และ 5 ควรปรับให้ใหญ่ขึ้นเล็กน้อย .. คุณคิดอย่างไรเกี่ยวกับเรื่องนี้?

ผู้ชนะได้รับการตัดสินอย่างไรก็ตามฉันคิดว่ามีรายการน้อยเกินไป

ทุกคนยังสามารถส่งรหัส .. : P


4
ตรงไปตรงมาเราไม่ได้ยอมรับอย่างมากว่า"ไม่มีการวัดเพียงลงคะแนน" . มีหลายสิ่งที่คุณจะต้องทำงานด้วยที่นี่ในแง่ของการตั้งค่าตัวชี้วัดที่เป็นกลางสำหรับงานนี้ ดูข้อความแสดงข้อผิดพลาดปลอมสำหรับตัวอย่างที่เป็นไปได้
dmckee --- ผู้ดูแลอดีตลูกแมว

@dmckee: ขออภัยฉันไม่ทราบว่าการลงคะแนนเป็นเรื่องส่วนตัว .. :(
JiminP

@JiminP: บันทึกที่ดี
dmckee --- ผู้ดูแลอดีตลูกแมว

บอท irc ฟังดูเหมือนกอล์ฟอีกต่อไป - ฉันคิดว่า :)
lunixbochs

clarification: "หากโปรแกรมถูกเตะให้ลองเข้าร่วมใหม่" - สิ่งนี้หมายความว่ามาจากเซิร์ฟเวอร์หรือช่อง?
lunixbochs

คำตอบ:


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

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

Perl, 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

หมายเหตุด้านข้าง

ขั้นตอนย่อย "ทั้งหมดที่คุณมีต่อเรา" อาจไม่คุ้มกับจำนวนตัวละคร แต่ถ้าฉันทิ้งมันไปฉันจะไม่มีตัวละครที่ดีเลย คนเสพเวจมรรค


+1 สำหรับ 66 คะแนนและ 666 ตัวอักษร คุณตั้งใจหรือได้รับสิ่งนั้นโดยบังเอิญ?
nyuszika7h

@ 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, ไม่มีประกาศ & PONG
  • รับ arline commandline ในรูปแบบของเซิร์ฟเวอร์: 6667 botnick botuser channel

คะแนน

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.