블로그 이미지
JEEN

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

Rss feed Tistory
IT/Perl 2008.05.23 12:20

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

하루에 한 번씩 쓸려고 했는데.. 역시 계획대로 쉽게 되지는 않는군요.

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

 - #2 에서는...

   - PoCo::IRC 를 이용해서 실제 IRC서버에 접속하고, 채널입장을 할 수 있었습니다.
   - IRC에서의 여러 이벤트들이 있다는 것을 알았습니다.

 - #3 에서는...

   - IRC에서 벌어지는 여러가지 이벤트 처리를 어떻게 하는 지에 대해서 알아보겠습니다.
   - IRC 에서 쓰이는 커맨드의 종류에 대해서도 함께 알아보겠습니다.

 - IRC Events

  자주 쓰이는 Event 를 우선으로 하겠습니다. 그리고 이벤트에서 받을 수 있는 인수에 대해서도 함께 알아보겠습니다.

  - irc_public (ARG0 - "닉!호스트", ARG1 - "채널이름", ARG2 - "메시지")
 채널 상에서 일반적인 대화시에 발생하는 이벤트 입니다.
sub irc_public {
my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];
my ($nick, $host) = split /!/, $who; # nick 과 호스트를 분리
my $channel = $where->[0]; # $where는 배열 참조
$irc->yield( privmsg => $channel => $nick . " : WTF?" );
# 건방진 봇이 되는 Lifehack
}
  - irc_join ( ARG0 - "닉!호스트", ARG1 - "채널이름" )
 누군가 채널에 입장했을 때 발생하는 이벤트 입니다.
sub irc_join {
     my ($sender, $who, $where) = @_[SENDER, ARG0, ARG1];
my ($nick, $host) = split /!/, $who; # nick 과 호스트를 분리
my $channel = $where->[0]; # $where는 배열 참조
$irc->yield( privmsg => $channel => $nick . " : Hello" );
# 언어에서 Hello World 가 기본이듯, Bot 에서도 Hello Bot 만들기는 가장 기본적인 예제입니다.
}

  - irc_msg ( ARG0 - "닉!호스트", ARG1 - "MSG 받은 당사자", ARG2 - "메시지" )
 귓속말 이벤트(1:1 대화)가 발생했을 때 입니다. 물론 여기서 메시지를 받는 대상은 "봇"이 됩니다.
sub irc_msg {
     my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2 ];
my ($nick, $host) = split /!/, $who; # nick 과 호스트를 분리
my $me = $where->[0]; # $where는 배열 참조
$irc->yield( privmsg => $nick => "What's wrong?" );
# 이번에는 privmsg 의 대상은 채널이 아니라, 닉네임이 됩니다.
# 귓속말 했는데 채널에 대고 떠들면 안되겠죠? 물론 인수에는 채널 정보를 얻을 수 없기도 하지만요.
}
  - irc_connected, irc_disconnected (ARG0 - "서버 이름" )
 
 IRC 서버에 접속하거나 나갔을 때의 이벤트 처리입니다.  강제종료가 아니라 정상적인 disconnect 가 되었다면, irc_disconnected 도 호출됩니다. 서버의 문제로 튕기거나 하는 상황이 적절한 예가 될 것입니다. irc_disconneted 에 다시 IRC 접속하게 해두면... 강제종료 하지 않는 이상은 계속해서 접속하려고 하겠죠. (물론 서버에서 부정한 접속이라고 튕겨낼 가능성이 있습니다)

  - irc_kick, irc_mode, irc_notice, irc_nick.... 
 채널 내에서 누구를 쫓아낼 때의 이벤트라든지, 누구에게 옵을 줬는지, 누군가 notice로 알릴 때나, 누군가 자신의 닉네임을 바꿀 때의 이벤트도 처리할 수 있습니다. 이에 대해서는 POE::Component::IRC 페이지에서 자세하게 확인하실 수 있으실 겁니다. 전부 다 쓰는 것은 역시나 힘들군요.

 - IRC Commands

 IRC에서 사용하는 기본적인 커맨드에 관한 이야기입니다. 이런 커맨드로 인해 이벤트가 발생하고, 그렇게 발생한 이벤트를 위에서 기술한 이벤트 처리에서 다루게 됩니다. 내용은 자주 사용하는 일부의 커맨드만을 다루도록 하겠습니다. 그리고 역시 마찬가지로 POE::Component::IRC 페이지에서 보다 더 자세한 내용을 알 수 있습니다.

  - privmsg
  주로 대부분의 IRC 클라이언트에서 이 명령어를 생략해도 됩니다. 일반적인 말하기 커맨드입니다.

  - join
  IRC 서버 접속 이후, 채널에 입장할 시에 쓰이는 커맨드 입니다.

  - kick
  맘에 안드는 대상을 쫓아냅니다. kick을 사용하는 당사자는 옵을 가지고 있어야 합니다.

  - mode
  채널 내의 어떤 사용자에 대해 권한을 설정할 수 있습니다. 엄격한 정책을 가지고 있는 채널에서는 여러가지 권한을 설정할 수 있습니다.

  - nick
  자신의 닉네임을 변경할 수 있습니다.

  - notice
  통보 메시지를 채널이나 유저에게 알립니다.

  - topic
  방의 주제를 설정할 수 있습니다.


 - Tutorial

 자신이 처리할 이벤트는 미리 POE::Session을 만들 때 등록해 둘 필요가 있습니다.
POE::Session->create(
                     package_states => [
                                        main => [ qw(_default _start irc_001 irc_public irc_msg ) ],
                                        ],
                     heap => { irc => $irc },
                     );

 이렇게 해두면 irc_public 과 irc_msg 를 처리할 수 있게 됩니다.
sub irc_public {
my ($sender, $who, $where, $what) = @_[SENDER, ARG0 .. ARG2];
my ($nick, $host) = split /!/, $who; # nick 과 호스트를 분리
my $channel = $where->[0]; # $where는 배열 참조
$irc->yield( privmsg => $channel => $nick . " : WTF?" );
# 건방진 봇이 되는 Lifehack
}

 그리고 irc_public 에서 이벤트를 위와 같이 기술합니다.

  $irc->yield ( <blahblah> => <target> => <do something> );

 이와 같이 IRC에 이벤트를 날릴 수 있습니다.
 <blahblah> 에는 위에서 말한 IRC Command 를,
 <target> 에는 채널이름이나 유저를,
 <do something> 에는 말하고 싶은 무언가를...

 물론 커맨드마다 필요한 인수는 다를 수 있으니, 그에 맞게 사용하시면 됩니다.
 실제 사용예제에 대해서는 차후에 다룰 예정이지만, 맘이 급하신 분들은 아래의 -PR 을 따라오시면 됩니다.

  - Summary

  - IRC 의 이벤트 처리에는 여러가지가 있고, 대부분을 처리할 수 있습니다.
  - IRC 커맨드에는 여러종류가 있고, 상황에 맞춰서 사용할 수 있습니다.

  - #4 에서는...

  - POE::Component::IRC::Plugin::(.*) 모듈을 사용해서 이미 만들어져 있는 Plugin 들을 붙여보겠습니다.

  - 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에게 연락하시면 됩니다.

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에게 연락하시면 됩니다.
IT/Perl 2008.05.20 21:56

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


 YAPC::ASIA 2008 의 광풍이 불고난 다음, Perl 을 사용하는 사람에게 남은 숙제는, Perl에 대해 제대로 알리는 것입니다. 그리고 어떻게 하면 그것이 가능하느냐에 대해 수없이 고민을 해보았습니다. 어떻게 하면 좋을까 해서 나온 게 일단 use strict 가 무엇이고 문법이 어떻고를 떠나, 어떻게 하면 Perl에 재미를 느낄 수 있을 까 하는 것입니다.
 그래서 생각한 것이 현재 irc.hanirc.org, #perl 에서 움직이고 있는 Perl_^^ BOT에 대한 내용을 한번 올려보면 어떨까 하는 것에서 시작합니다.
 
사용자 삽입 이미지

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

 - Warning!!

 - 우선 이 내용에 대해서 불건전한 사용에 대한 책임은 지지 않습니다.
 - 본 내용은 "난 Perl 을 들어봤다. Linux 커맨드는 기본적인 것은 알고 있다." 의 조건에 부합하신 분들에게 최적화 되어 있습니다.
 - IRC Port가 열려 있어야 합니다.
 - 여기에서는 제 시스템 환경인 CentOS 5, Perl 5.8 이상의 환경을 기반으로 합니다.
 - 특히 Windows 의 경우에는 사용해 본 적이 없기에 장담할 수 없습니다.

 - Intro...


 IRC BOT 을 만들 기 위해, IRC Protocol 을 미리 다 알 필요는 없습니다(물론 저도 전부 모릅니다).
 미리 IRC 프로토콜에 맞춰서 만들어진 모듈이 이미 존재하고, 이에 대한 내용이 구성되어 있기 때문이죠.

  Perl CPAN 모듈에서 대표적인 IRC 클라이언트 모듈은

  Net::IRCPOE::Component::IRC 가 있습니다.

  이중에서 Net::IRC는 2004년 이후로는 관리되지 않고 있으며,
  POE::Component::IRC 는 2008년 4월까지 꾸준히 계속해서 관리되어 오고 있고, 이 모듈을 위한 여러가지 플러그인들이 존재하고 있습니다.

  그리고 이제부터 다루고자 할 모듈도 POE::Component::IRC(이하 PoCo::IRC) 입니다.

  - Tutorial

  우선적으로 해야할 것은 CPAN Module 의 인스톨입니다.

  대부분의 리눅스계열의 OS는 Perl은 기본적으로 들어가 있고, cpan 역시 기본적으로 지원하고 있습니다.
  만약, root 계정을 사용할 수 없으시거나, 웹 호스팅을 이용하고 계신다면, CPAN Module을 로컬 계정에 설치할 수 있습니다.
  이에 대해서는 펄매니아 위키에 자세히 적혀져 있으므로 참고하세요.

$ cpan
cpan shell -- CPAN exploration and modules installation (v1.9205)
ReadLine support enabled
                                                                                                                                              cpan[1]>

  cpan 을 실행하면 cpan용 터미널이 뜹니다. 이때 인스톨 하실 모듈을 넣어주시면 됩니다.

cpan[1]> install POE::Component::IRC

  그러면 모듈을 설치합니다. 중간에 어떤 것을 물어보신다면 그냥 엔터만 믿고 눌러주시면 됩니다.

cpan[2]> quit

  설치가 종료하면 "quit"으로 나옵니다.

  이상으로 POE::Component::IRC 모듈의 설치가 끝났습니다.

 - Summary

  - IRC 를 이용하기 위한 CPAN Module에는 대표적으로 Net::IRC, POE::Component::IRC 가 있습니다.
  - 웹 호스팅을 이용하시거나, root 계정을 사용할 수 없으실 때에는 이곳을 참조하세요.
  - CPAN Module 을 인스톨 하기 위해서는 "cpan 터미널에서 install [모듈이름]을 입력합니다."
    (혹은 cpan [모듈이름])

 - #2에서는

  - PoCo::IRC를 이용해서 BOT의 Nick 을 설정합니다.
  - IRC 서버에 접속합니다.
  - PoCo::IRC를 이용해서 어떤 처리를 할 수 있는지 알아봅니다.

※ 현재 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에게 연락하시면 됩니다.

'IT > Perl' 카테고리의 다른 글

[ Perl ] IRC BOT을 만들어봅시다 :-) #2  (4) 2008.05.21
[ Perl ] IRC BOT을 만들어봅시다 :-) #1  (6) 2008.05.20
YAPC::Asia 2008 이야기 #3  (2) 2008.05.18
YAPC::Asia 2008 이야기 #2  (0) 2008.05.18
Project 2008.04.01 21:41

[PERL] 급조 #5 IRC Channel Log를 수집...해서 웹에다가 뿌리자!

출근시간이 플렉시블한 관계로 인해서...

출근시간이면 제 귀가 가렵기 그지 없습니다.

제가 irc.hanirc.org #perl 에 들어갔을 때는 귀가 괜찮아 졌습니다.

이유는 제가 #perl 에 들어갔을 때는 험담이 끝났기 때문이라고 생각합니다.

라는 것은 훼이크이고...

예~전부터 생각했지만... 중간에 들어가면 대화의 맥을 못잡을 때도 있고,

중요한 정보나 Tip등을 본채로 그냥 넘겨버리기도 하고는 하거든요.

이미 회사에서는 사내 IRC의 로그를 남겨서 수시로 확인할 수 있게 만들어 뒀습니다.

회사의 주요 커뮤니케이션이 IRC를 통해서 이기도 하거든요. MSN같은 경우도 사용은 하는데...

1:1은 아무래도 무거운 분위기이며, 업무적으로도 증인이 없으니(프로젝트 중에서 수시로 말이 바뀌니...)

증인이 될 수 있고, 증거가 남게 되는 IRC를 사용하게 되는 것이죠.

어떻게 되면 공개처형같이 보일 수도 있겠지만 말이죠...

우선 서두는 이정도로 하겠습니다. 물론 사용언어는 Perl 입니다.

Ruby나 Python, Java등의 이미 만들어진 것들도 있고... Perl 도 물론 있는 것으로 압니다.

IRC BOT말이죠. 걔중에는 다양한 기능을 지원하기도 하니... 좋기도 하죠.

뭐... 그리 필요한 것도 아니고 해서.. 일단은 그냥 만들기로 했습니다.

처음은 Net::IRC를 사용해봤는데... 접속이 불규칙하고... 기본적인 뼈대만 만들어져 있는 상태라서...

POE::Component::IRC 로 하기로 했습니다. CPAN Rating 도 만점이니까... :-)

POE::Component::IRC 자체는 플러그 인으로 Log를 남기는 기능이 있습니다.

POE::Component::IRC::Plugin::Logger 였었나... 근데 안쓰고 그냥 저질러 버리고는

현재 #perl 방에서 가동중입니다.

걸 웹에서 보게 하는 건... 이미 만들어 놓은 게 있기 때문에... 공개만 하면 되는데...

이상하게 외부에서 제 섭으로 80이 답이 없네요.. 흠... 초허접 뉴비인 저로써는 어케할 도리가 없이

일단 머리잡고 공부하면.. 답이 나오겠죠.

 http://www.myemy.com:13000/

 여기에서 #perl 의 히스토리 로그를 볼 수 있습니다.

 너무 이것저것 남으면 아니되니까... 로그에 담지 않게 필터링하는 것 붙이느라

 (aero++) 간단한 건데... Encode 때문에 너무 고생을 했네요.
 
SpringNote 연계라든가... Me2Day 연계라든가... MSN으로 간다던가... 네이트온으로 간다던가...

FaceBook으로 자동 포스트 하든가... RSS 를 발행하든가... 다양한(=잡다한) 것들을 생각중입니다.

뭐, 어케 되겠죠 뭐...


IRC, Log, perl
TOTAL 525,176 TODAY 3