Tạo một bot IRC đơn giản.


10

Bài tập

Tạo một bot IRC đơn giản thực hiện nhiệm vụ đơn giản như chào người dùng.

Chi tiết

(Bạn có thể xem tài liệu RFC này .)

Viết một chương trình hoàn chỉnh thực hiện những điều sau:

  1. Các chương trình đầu vào nicknamerealnametừ người dùng.

    • Tất cả nicknamerealnamehình thức nào [A-Za-z0-9]+nên được cho phép, nhưng điều đó không quan trọng cho dù các hình thức khác được cho phép. Ví dụ, nếu người dùng muốn 1234qwertynhư nickname5319009như realname, chương trình nên sử dụng những cái tên đó, nhưng nó không phải là quan trọng cho dù chương trình có thể sử dụng ^^☆Rick Astley☆^^(bao gồm phi bảng chữ cái & số thập phân) như ( nicknamehoặc realname) hay không, thậm chí còn nghĩ tên này có thể bị từ chối bởi máy chủ.
  2. Các chương trình đầu vào serverAddresstừ người dùng.

    • Hình thức serverAddressserverIP:serverPort, serverIPđịa chỉ IP của máy chủ và serverPortlà số cổng của máy chủ.
  3. Chương trình kết nối với cổng serverPorttại máy chủ IRC serverIPvà chương trình sẽ đặt biệt hiệu là tên thật nicknamevà tên thật realnamebằng cách gửi USER realname 0 * :realnameNICK nickname.

  4. Chương trình nhập một đơn vị channelNamekhông bao gồm #và tham gia vào kênh #channelName.

  5. Gửi một tin nhắn riêng tư Hello, world!đến #channelNamekênh như thế này:PRIVMSG #channelName :Hello, world!

  6. Sau đó, chương trình thực hiện những điều này:

    A. Nếu ai đó tham gia, hãy chào hỏi anh ấy bằng cách nói Hello, @!với #channelName, trong đó @ là biệt danh của anh ấy / cô ấy.

    B. Nếu chương trình được khởi động, hãy thử tham gia lại.

    C. Nếu một người bị đá hoặc bị cấm, hãy nói POW HAHA.

    D. Nếu một người rời khỏi ( PARThoặc QUIT), giả sử Goodbye, @!, trong đó @ là biệt danh của anh ấy / cô ấy.

    E. Nếu ai đó nói một số văn bản bao gồm Turing testhoặc turing test, nói I'm a human!.

    F. Nếu ai đó nói một số văn bản bao gồm 6*9, thoát bằng cách gửi QUIT :42đến máy chủ.

    G. Nếu ai đó nói một số văn bản bao gồm all your base are belong to us(không phân biệt chữ hoa chữ thường), hãy thoát bằng cách gửi QUIT :What you say!đến máy chủ.

    H. Nếu ai đó nói rằng một số văn bản có trước một khoảng trắng và các hành vi trên không được thực hiện bởi văn bản, hãy nói tổng số ký tự của tất cả (ngoại trừ khoảng trắng đầu tiên) trong văn bản.

Nếu xảy ra lỗi

Nếu xảy ra lỗi (như lỗi kết nối hoặc không hợp lệ nickname), bạn có thể làm những gì bạn muốn làm. Ví dụ: nếu nicknamechương trình đã được sử dụng, chương trình có thể dừng, nhận thông tin mới nicknametừ người dùng hoặc tự động thay đổi nicknamevà thử lại.

Sự hạn chế

Chương trình

  • Không nên sử dụng bất kỳ chức năng hoặc thư viện nội bộ nào dành cho việc tạo / máy khách IRC. tức là một cái gì đó giống như các thư viện máy khách IRC
  • Nên nhắc những gì nó sẽ nhập, trước khi nó nhận được một đầu vào . Ví dụ, trước khi đầu vào serverAddress, nó sẽ nhắc Write the address of server:, serverIP:serverPort >, serverAddress >, hoặc một số văn bản mà người dùng có thể nhận ra.
  • Nên hoạt động trên một số máy chủ IRC sử dụng UTF-8. (tức là không dành cho máy chủ đơn lẻ)
  • Không nên gửi tin nhắn đến máy chủ NOTICE. (RFC 2812, 3.3.2 Lưu ý: Sự khác biệt giữa NOTICEPRIVMSGlà trả lời tự động PHẢI KHÔNG BAO GIỜ được gửi để trả lời NOTICEtin nhắn.)
  • Nên gửi một tin nhắn trong đó yêu cầu đến từ ( #channelNamehoặc nickname).
  • Nên PONGkhi PINGed, tất nhiên.

PS

Vâng, tôi chỉ làm điều này, bởi vì không có câu đố nào về IRC bot.

Biên tập

Sau khi đọc bình luận của @ dmckee, tôi đã thay đổi quy tắc chọn người chiến thắng.

  1. Mặc định bonus= +0

  2. Nếu bằng cách nào đó, chương trình có thể kết nối với một kênh (ngay cả khi không phải vậy #channelName), bonus= 1

  3. Nếu chương trình có thể thực hiện bước 1 ~ 5, bonus* = 2.

  4. Đối với mỗi tác vụ A ~ H trong bước 6, nếu chương trình thực hiện, bonus* = 1.2.

  5. Đối với mỗi sáu hạn chế, nếu chương trình tuân theo điều đó, bonus* = 1.05.

score = int(codelength/bonus).

Chương trình có số điểm thấp nhất là người chiến thắng. Nếu hai câu trả lời có cùng số điểm, thì câu trả lời có số phiếu cao nhất sẽ thắng.

EDIT Chỉnh sửa: Tôi nghĩ 1.21.05trong bước 4 và 5 nên điều chỉnh lớn hơn một chút .. Bạn nghĩ gì về điều này?

Người chiến thắng được quyết định, tuy nhiên, tôi nghĩ có quá ít mục.

Bất cứ ai vẫn có thể gửi mã ..: P


4
Thành thật mà nói, chúng tôi đã không chấp nhận "Không có số liệu, chỉ cần bỏ phiếu." . Có nhiều thứ để bạn làm việc ở đây về mặt thiết lập một số liệu khách quan cho nhiệm vụ này. Xem thông báo lỗi giả cho một ví dụ có thể.
dmckee --- ex-moderator mèo con

@dmckee: Xin lỗi, tôi không biết rằng phiếu bầu khá chủ quan .. :(
JiminP

@JiminP: Đẹp tiết kiệm.
dmckee --- ex-moderator mèo con

irc bot có vẻ như là một sân golf dài hơn - mặc dù vậy :)
lunixbochs

làm rõ: "Nếu chương trình được khởi động, hãy thử tham gia lại." - điều này có nghĩa là từ máy chủ hoặc kênh?
lunixbochs

Câu trả lời:


1

PHP - 121 điểm

  • 1396 ký tự
  • Theo tất cả các bước (bao gồm thêm) và các hạn chế

Ghi bàn

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

Lưu ý bên

Câu trả lời của tôi thực sự khác với hướng dẫn rất nhẹ; các hướng dẫn nói sử dụng realnamelàm tham số đầu tiên cho USERlệnh khi đăng ký, nhưng tôi đã sử dụng tên hiệu thay thế. Điều này là do realnameđược phép có khoảng trắng, trong khi tham số này thì không. Tuy nhiên, đó là một điểm của một điểm mô phỏng, vì chuyển đổi trong biến cho realnamesẽ có cùng số lượng ký tự.


5

Con trăn - 125 điểm

  • 304 ký tự
  • làm theo các bước 1-5 (hoạt động với tôi trên irc.freenode.net:6667. nếu bạn thử ở đó, hãy nhớ IDENT có thể mất một lúc, vì vậy hãy dành hơn 20 giây để kết nối và nói chuyện)
  • tuân theo 4 hạn chế (giả sử hạn chế THÔNG BÁO không rõ ràng. Hạn chế UTF được tính vì python sẽ không bị nghẹt nếu không cần phân tích bất kỳ UTF nào).

điểm toán (trăn):

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

mã:

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 điểm

  • 666 ký tự
  • tất cả các bước
  • một nửa hạn chế

Ghi bàn

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

(dòng mới chỉ để trình bày, không tính hãy để một mình chấp nhận)

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

Lưu ý bên

Mục phụ "TẤT CẢ CÁC CƠ SỞ CỦA BẠN LÀ DƯỚI ĐÂY" có lẽ không đáng để tính nhân vật của nó, nhưng nếu tôi bỏ nó, tôi sẽ không có số lượng nhân vật tốt. Bugger.


+1 cho 66 điểm và 666 ký tự. Đó là cố ý hay bạn đã có được điều đó một cách tình cờ?
nyuszika7h

@ nyuszika7h Thật lòng tôi không nhớ.
JB

2

Ruby, 28 điểm

Ghi bàn

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

Ruby, 65 điểm

  • 574 ký tự
  • Các bước 1-5, 6 (AG) và các hạn chế đối với libs, UTF-8, không có THÔNG BÁO & PONG
  • Đưa dòng lệnh lập luận dưới dạng máy chủ: 6667 kênh botuser botnick

Ghi bàn

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
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.