Определимся с задачей
Есть комната в irc, есть комната в xmpp. соответственно нужно, чтобы всё, что пишут в xmpp оказалось в irc, и наоборот.
xmpp и irc в данном случае имеют кодировку utf-8, поэтому перекодировать ничего не нужно будет.
Начнём
Для всего этого будем использовать Anyevent.
Пояснения буду сразу в коде писать — думаю, так будет удобней.
#!/usr/bin/perl use strict; use warnings; use utf8; use Encode qw(decode encode); use locale; use open qw( :utf8 :std ); use AnyEvent::IRC::Client; use AnyEvent::XMPP::Client; use AnyEvent::Socket; use AnyEvent::Handle; use AnyEvent::XMPP::Ext::Disco; use AnyEvent::XMPP::Client; use AnyEvent::XMPP::Ext::MUC; # xmpp коннектится дольше, поэтому плясать будем от него my $xmpp_connected=0; my $c = AE::cv; my $xmpp=AnyEvent::XMPP::Client->new(debug=>0); my $disco=AnyEvent::XMPP::Ext::Disco->new; my $muc=AnyEvent::XMPP::Ext::MUC->new (disco => $disco); # оставим глобальную переменную, из которой в последующем будем отправлять сообщения в xmpp my $croom; $xmpp->add_extension($disco); $xmpp->add_extension($muc); $xmpp->add_account('bot@server/res','password'); # callback's для xmpp $xmpp->reg_cb( session_ready => sub{ my($xmpp,$acc)=@_; my $con=$acc->connection; # Как только установили надёжную связь с xmpp - входим в комнату. $muc->join_room ($acc->connection, "habr2014\@conference.jabber.ru", "ibot435"); }, disconnect => sub {die "disconnected\n";}, error => sub { my ($xmpp,$acc,$err)=@_; die "error: ".$err->string."\n"}, ); # callback's для xmpp muc (multi user conference) $muc->reg_cb( message=>sub{ my ($muc,$room,$msg,$echo)=@_; # мы получили сообщение в xmpp-комнату. и если это сообщение отправили не мы - пересылаем его в irc if ($msg->from_nick ne "ibot435"){ $irc->send_srv(PRIVMSG => '#habr2014ny', "(xmpp) ". encode("utf8",$msg->from_nick).": ".encode("utf8",$msg->body)); } }, enter=>sub{ my ($muc,$room,$user)=@_; #вошли в канал успешно - задаём значение глобальной переменной. $croom=$room; $xmpp_connected=1; } ); $xmpp->start; # с xmpp закончили, теперь irc my($server, $port, $nick, $channel) = ("irc.p2pchat.net",6667,"jbot435","#habr2014ny"); my $irc = AnyEvent::IRC::Client->new; $irc->reg_cb ( connect => sub { my ($irc, $err) = @_; if (defined $err) { die "connect error: $err\n"; } }, irc_privmsg=>sub { my($irc,$msg)=@_; # получили сообщение из irc - пересылаем в xmpp my $nick=(split /!/,$msg->{'prefix'})[0]; my $to=$msg->{'params'}[0]; my $text=$msg->{'params'}[1]; $text=decode('utf8',$text); if ($to eq "#habr2014ny" && $xmpp_connected==1) { my $new_msg=$croom->make_message(); $new_msg->add_body("(irc) ".$nick.': '.$text); $new_msg->send(); } } ); $irc->connect ($server, $port, { nick => $nick }); $irc->send_srv( JOIN => $channel); # запускаем loop $c->recv;
Выглядеть это всё будет примерно так:
(в xmpp)
<ibot435> (irc) user1: текст
<ibot435> (irc) user2: текст(в irc)
<jbot435> (xmpp) user3: текст
<jbot435> (xmpp) user4: текстПодводные камни
Единственное, что оказалось нетривиальным — модуль AnyEvent::XMPP и AnyEvent::IRC по-разному работают с юникодом. Поэтому пришлось устанавливать флаг юникода при отправке в irc (encode(«utf8»,$msg->body), а при получении из irc снимать этот флаг ($text=decode('utf8',$text);)
Выводы
С виду громоздкая задача на перл может оказаться совсем тривиальной. главное найти хороший модуль.
PS: callback's не разносил в отдельные функции не разносил, чтобы компактней всё выглядело и не мешалось.
