Определимся с задачей


Есть комната в 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 не разносил в отдельные функции не разносил, чтобы компактней всё выглядело и не мешалось.