블로그 이미지
JEEN

서울에 사는 꽃청년의 IT찌질모험기

Rss feed Tistory
IT/Perl 2008.05.21 13:23

[ Perl ] IRC BOT을 만들어봅시다 :-) #2

 어제 저녁 엔트리에 이어서, 계속해서 써나갑니다.

  IRC BOT을 만들어봅시다 :-) #2

  - #1 에서는... ( 2008/05/20 - [IT/Perl] - IRC BOT을 만들어봅시다 :-) #1 )

   - IRC 를 구현한 모듈은 Net::IRC, PoCo::IRC 가 있다는 것을 알았습니다.
   - PoCo::IRC 모듈을 설치하는 법을 알았습니다.

  - #2 에서는

   - PoCo::IRC를 이용해서 실제로 IRC 서버 접속을 해봅니다.

  - Tutorial

   PoCo::IRC 의 CPAN Module 페이지로 들어가보면 자세한 예제가 나옵니다. 여기서는 이 예제를 바탕으로 시작해보고자 합니다.
 
use strict;
use warnings;
use POE qw(Component::IRC);

my $nickname = 'I_Like_Perl';
my $ircname = 'Bot-Likes-Perl';
my $server = 'irc.blahblahblah.irc';

my @channels = ('#perlbot_test', '#perlbot', '#perl');

my $irc = POE::Component::IRC->spawn(
nick => $nickname,
ircname => $ircname,
server => $server,
) or die "Oh noooo! $!";

POE::Session->create(
package_states => [
main => [ qw(_default _start irc_001 irc_public) ],
],
heap => { irc => $irc },
);

$poe_kernel->run();

sub _start {
my $heap = $_[HEAP];

my $irc = $heap->{irc};

$irc->yield( register => 'all' );
$irc->yield( connect => { } );
return;
}

sub irc_001 {
my $sender = $_[SENDER];

my $irc = $sender->get_heap();

print "Connected to ", $irc->server_name(), "\n";

$irc->yield( join => $_ ) for @channels;
return;
}

sub irc_public {
my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];

return;
}

sub _default {
my ($event, $args) = @_[ARG0 .. $#_];
my @output = ( "$event: " );

for my $arg (@$args) {
if ( ref $arg eq 'ARRAY' ) {
push( @output, '[' . join(' ,', @$arg ) . ']' );
}
else {
push ( @output, "'$arg'" );
}
}
print join ' ', @output, "\n";
return 0;
}
이와같은 코드를 뽑아왔습니다. 위의 코드를 "bot.pl"로 저장합니다.

그리고 한 부분씩 조심조심 설명 들어가겠습니다.
my $nickname = 'I_Like_Perl'; # 당연히 IRC 상에서의 닉입니다.
my $ircname = 'Bot-Likes-Perl'; # IRC 상에서의 이름입니다. 적당하게 대충쓰시면 됩니다 :-)
my $server = 'irc.hanirc.org'; # 접속할 IRC 서버입니다.
 - 국내의 대표적인 IRC 서버는 hanIRC(irc.hanirc.org)와 단군넷(irc.dankun.net) 이 있습니다.
 - 해외의 대표적인 IRC 서버는 Freenode(irc.freenode.net) 와 Perl IRC(irc.perl.org) 이외에 여럿 있습니다. :-)

 각자 자신이 사용하실 IRC 서버를 넣으시면 되겠습니다.
my @channels = ('#perlbot_test', '#perlbot', '#perl'); # 입장하실 채널을 정해주세요.
 @channels 라는 배열에 처음에 입장하실 IRC 채널을 넣으시면 됩니다. 이렇게 하시면 #perlbot_test, #perlbot, #perl 방에 입장하시게 되는 겁니다. (그 채널에 아무도 없다면 IRC 프로토콜의 정책 상 채널이 생기는 것이 됩니다)
my $irc = POE::Component::IRC->spawn(
nick => $nickname, # 위에서 설정한 닉
ircname => $ircname, # 위에서 설정한 이름
server => $server, # 위에서 설정한 IRC서버
) or die "Oh noooo! $!";
  PoCo::IRC 모듈에 적절한 인수를 맞춰서 호출합니다. 만약 여기서 문제가 생긴다면 "Oh noooo!" 를 외치면서 스크립트는 종료됩니다.

 POE::Session->create(
  package_states => [
  main => [ qw(_default _start irc_001 irc_public) ], # POE 상에서 어떤 상태별로 호출될 서브루틴입니다.
 ],
 heap => { irc => $irc },
 );
 $poe_kernel->run(); # POE Kernel 을 실행합니다.

 위의 _default, _start_ irc_001, irc_public 은 해당되는 상태정보에 따라 호출이 됩니다.
 이에 대해 하나하나 알아볼까요?
sub _start {
my $heap = $_[HEAP];

my $irc = $heap->{irc};

$irc->yield( register => 'all' );
$irc->yield( connect => { } );
return;
}
 _start 메소드의 구성입니다. 여기서는 시작할 때에 IRC 접속을 위한 초기화 작업을 수행합니다. IRC 접속 이전에 각종 플러그인을 여기에서 추가할 수 있습니다.
sub irc_001 {
my $sender = $_[SENDER];

my $irc = $sender->get_heap();

print "Connected to ", $irc->server_name(), "\n";

$irc->yield( join => $_ ) for @channels; # 위에서 정의한 @channels 변수에 담긴 채널에 입장합니다.
return;
}
  irc_001 의 구성입니다. 서버에 접속한 뒤에 한번 호출이 됩니다. IRC 서버에 접속하고서 가장 먼저 해야할 일들을 여기에서 정의해 줄 수 있습니다. 가장 기본적으로 해야할 것은 역시 채널에 접속하는 것입니다.
sub irc_public {
my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];

return;
}

irc_public 은 유난히도 받아들이는 인수가 많습니다. 이것은 일반적인 대화시에 호출이 됩니다. 대화시에 발생되는
어떤 이벤트들을 여기에서 구현해 줄 수 있습니다. (누가, 어디서, 무슨 말을 했는가)에 대한 인수를 얻게 됩니다.

sub _default {
my ($event, $args) = @_[ARG0 .. $#_];
my @output = ( "$event: " );

for my $arg (@$args) {
if ( ref $arg eq 'ARRAY' ) {
push( @output, '[' . join(' ,', @$arg ) . ']' );
}
else {
push ( @output, "'$arg'" );
}
}
print join ' ', @output, "\n";
return 0;
}

_default 는 어떤 이벤트 발생시의 기록을 남깁니다. 서버로 부터 ping을 받았을 때는 irc_ping, 서버접속시의
상태정보에 대한 것이거나, irc_353 등의 정보로 현재 채널에 입장한 사람이 누구인지 여부를 알 수 있습니다.
irc_join, irc_quit 등의 정보로 지금 막 입장한 사람에 대한 정보도 얻을 수 있구요.

모든 처리는 이런 정보를 기본으로 합니다.
누가 어떤 말을 했을 때, BOT에게 어떻게 하게 한다거나...
어떤 사람이 입장했을 때 그 사람에게 "안녕"이라고 말한다거나 말이죠.

이 부분의 처리에 대해서는 다음 포스트에 계속하겠습니다.

  - Summary

- PoCo::IRC를 이용해서 IRC 서버 접속할 수 있다.
- 해당 변수의 내용을 바꿔서 Bot의 Nick을 바꿀 수 있다.
- irc 상태에 따라 여러 메소드들을 호출 할 수 있다.
- _start, _default, irc_001, irc_public 등의 메소드에서 해당 이벤트들을 처리한다.

  - #3 에서는...

- IRC의 상태에 따른 이벤트 처리를 알아보겠습니다.
- euc-kr, UTF-8 등의 언어코드에 대한 내용을 알아보겠습니다.

  - PR
※ 현재 POE::Component::IRC를 사용한 Perl Bot 만들기 프로젝트가 진행중입니다.
- http://code.google.com/p/perl-irc-bot
※ 더불어 perldoc을 한글로 번역하기 위한 프로젝트도 진행중입니다.
- http://code.google.com/p/perldoc-kr
※ 거기에 덧붙여 me2day Perl API를 만드는 프로젝트도 진행중입니다.
- http://code.google.com/p/me2day-perl-api

 참여를 원하시면 댓글을 달아주시거나, email: aiatejin@gmail.com
 혹은 IRC(irc.hanirc.org, #perl)에서 JEEN에게 연락하시면 됩니다.
신고
TOTAL 466,751 TODAY 70

티스토리 툴바