【问题标题】:How to create a jabber/XMPP proxy/logging service?如何创建 jabber/XMPP 代理/日志服务?
【发布时间】:2011-09-20 06:26:07
【问题描述】:

我在一家公司工作,该公司使用 Google Chatback(与我公司的支持员工进行匿名聊天)作为主要聊天服务提供商。此服务使用 XMPP(以前称为 Jabber)协议来发送和接收消息。

我们公司有十个支持员工帐户,可以通过我们在网站上使用的聊天服务访问它们。员工同时使用 Mac OSX 和 Windows,以及不同操作系统上的不同客户端。聊天也可以通过 Android 和 iOS 上的本机应用程序进行。

我们需要一项记录聊天会话的服务,并且我们一直在寻找专有解决方案,但移动平台不支持这些解决方案,这基本上是破坏交易的因素。

我决定的解决方案是在消息链中引入另一个链接,记录所有消息。这个想法是服务器通过这个代理发送,根据它是哪个聊天会话记录消息,然后以适当的方式保存这些日志。目前他们将所有日志存储在 Dropbox 文件夹中,这是一个容易出错的活动。

理论上,这将允许我们的支持者使用他们选择的任何操作系统/客户端,并且日志最终会放在同一个地方。

在使用 Smack API 进行了一些测试后,我得出的结论是,我的 XMPP 客户端(Android 和 Windows 上的 Trillian)响应了它最后收到消息的资源。这实际上意味着我实现的非常简单的聊天记录器会被忽略。

测试是使用下面的代码和另一个并行运行的客户端进行的。只有一个客户端收到消息。

ConnectionConfiguration config = new ConnectionConfiguration("talk.google.com", 5222, "googlemail.com");
config.setSecurityMode(ConnectionConfiguration.SecurityMode.required);
config.setSASLAuthenticationEnabled(true);
XMPPConnection connection = new XMPPConnection(config);
connection.connect();

Presence presence = new Presence(Presence.Type.unavailable);
connection.login("android_client_username", "android_client_pass");
Message message = new Message("my_test_email@gmail.com");
message.setBody("Hello World!");
connection.sendPacket(message);
connection.sendPacket(presence);
connection.addPacketListener(new PacketListener() {
          public void processPacket(Packet packet) {
             if (packet instanceof Message) {
                Message message = (Message) packet;
                System.out.println(message.getBody()); 
             }
           }
        }, new MessageTypeFilter(Message.Type.chat));
  • 是否可以使用 Google Talk 服务创建这样的代理,即无需托管我们自己的 XMPP 服务器?
  • 是否可以远程监听服务器上的所有数据包?
  • 如果不是,对于使用 XMPP 等开放协议的基于 Web 的匿名聊天客户端,还有哪些替代方案?

感谢您的宝贵时间。

【问题讨论】:

    标签: java xml-rpc xmpp smack


    【解决方案1】:

    如果你设法配置它,你可以试试 gozerbot

    【讨论】:

      【解决方案2】:

      我不太确定它是否会影响您和您的服务,但仅供参考,我过去曾体验过 407 代理身份验证。尝试发出跨域文本/xml ajax 请求时的响应代码。大多数情况下,如果您位于防火墙/http-proxy(squid) 类型的环境后面。解决方案主要是在代理后面使用 jsonp 的回退模式。

      测试验证: 1)设置本地鱿鱼 2)使用strophejs的基本例子 3) 设置跨域 ajax 即 BOSH_SERVICE_URL 域与请求者域不同 4)配置浏览器使用本地squid 5)您会发现所有 POST api 调用,即 /http-bind text/xml 调用将失败,并出现 407 代理身份验证响应代码 6)从浏览器中删除代理使用 7) 再试一次,在启用 CORS 的情况下一切正常

      【讨论】:

        【解决方案3】:

        如果您不使用 Google Chatback 服务,那么设置您需要的环境相对容易。为了记录 XMPP 消息,必须通过 MUC(多用户聊天)进行聊天。您需要以下组件:

        • 书:http://professionalxmpp.com/
        • HTTP 服务器
        • Jabber/XMPP 服务器(例如 ejabberd)
        • 每个支持座位的聊天室
        • 使用 perl 和 Net::Jabber(不是 Net::XMPP,因为它不支持 MUC)创建脚本/进程/守护程序,它将登录到 XMPP 服务器并加入适当的聊天室。聊天室中的其他参与者将是您的支持者之一,以及寻求支持的人。必须以这样一种方式设置脚本,即它在收到 MUC 消息时可以做任何你想做的事情(例如,存储在数据库中)。自从安装 Net::Jabber 后,这项工作就不那么重要了,有一些示例脚本,您只需要在其中添加/修改部分代码。
        • 如果您想通过网络浏览器聊天,必须使用 Strophe.js 以通过 HTTP 服务器通过适当的代理配置建立与 XMPP 服务器的 BOSH 连接。

        除了使用 Net::Jabber 的 Perl 脚本之外,所有这些东西都可以在书中找到。

        我可能帮不上什么忙,但如果你决定走这条路,我会帮忙的。如果 Google Chatback 支持 MUC,那么您只需要 Perl/Net::Jabber 部分。

        编辑:perl XMPP 守护进程

        #!/usr/bin/perl -w
        
        use strict;
        use Net::Jabber;
        use threads;
        use DBI;
        
        my $server = shift @ARGV;
        my $port = shift @ARGV;
        my $username = shift @ARGV;
        my $password = shift @ARGV;
        my $resource = shift @ARGV;
        my $chatroom = shift @ARGV;
        
        my %img = ('URGENT' => 'urgent.png',
                    'HIGH' => 'high.png',
                    'MEDIUM' => 'medium.png',
                    'LOW' => 'low.png');
        
        my $dbname_status= 'db';
        my $dbuser_status= 'user';
        my $dbpass_status= 'pass';
        my $dbhost_status = 'localhost';
        my $dbport_status = 5432;
        
        my $dbh_status = DBI->connect("dbi:Pg:dbname=$dbname_status;host=$dbhost_status;port=$dbport_status", $dbuser_status, $dbpass_status, {AutoCommit => 0, RaiseError => 1});
        my $sth_status = $dbh_status->prepare(qq{SELECT * FROM sosrhs_ticketstatus});
        $sth_status->execute;
        my %status = ();
        while (my $res = $sth_status->fetchrow_hashref)
        {
            $status{$res->{status}} = $res->{id};
        }
        $sth_status->finish;
        $dbh_status->disconnect;
        
        print "\nSERVER: ", $server, "\n";
        print 'PORT: ', $port, "\n";
        print 'USERNAME: ', $username, "\n";
        print 'RESOURCE: ', $resource, "\n";
        
        
        $SIG{HUP} = \&Stop;
        $SIG{KILL} = \&Stop;
        $SIG{TERM} = \&Stop;
        $SIG{INT} = \&Stop;
        
        my $Connection = new Net::Jabber::Client();
        
        $Connection->SetCallBacks(message => sub {threads->create('InMessage', (@_))->join()},
                                  presence => sub {threads->create('InPresence', (@_))->join()},
                                  iq => sub {threads->create('InIQ', (@_))->join()}
                                  );
        
        my $status = $Connection->Connect(hostname=>$server,
                                          port=>$port,
                                         );
        
        if (!(defined($status)))
        {
            print "ERROR:  Jabber server is down or connection was not allowed.\n";
            print "        ($!)\n";
            exit(0);
        }
        
        my @result = $Connection->AuthSend(username=>$username,
                                           password=>$password,
                                           resource=>$resource);
        
        if ($result[0] ne "ok")
        {
            print "ERROR: Authorization failed: $result[0] - $result[1]\n";
            exit(0);
        }
        
        print "Logged in to $server:$port...\n";
        
        $Connection->RosterGet();
        
        print "Getting Roster to tell server to send presence info...\n";
        
        $Connection->PresenceSend();
        
        print "Sending presence to tell world that we are logged in...\n";
        
        $Connection->MUCJoin(room => $chatroom,
                            server => 'conference.' . $server,
                            nick => $username);
        
        print 'Join ' . $chatroom . '@conference.sosrhs MUC room...';
        print "\n";
        
        while(defined($Connection->Process())) { }
        
        print "ERROR: The connection was killed...\n";
        
        exit(0);
        
        
        sub Stop
        {
            print "Exiting...\n";
            $Connection->Disconnect();
            exit(0);
        }
        
        
        sub InMessage
        {
            my $sid = shift;
            my $message = shift;
        
            my $type = $message->GetType();
            my $fromJID = $message->GetFrom("jid");
        
            my $from = $fromJID->GetUserID();
            my $resource = $fromJID->GetResource();
            my $subject = $message->GetSubject();
            my $body = $message->GetBody();
            #print "===\n";
            #print "Message ($type)\n";
            #print "  From: $from ($resource)\n";
            #print "  Subject: $subject\n";
            #print "  Body: $body\n";
            #print "===\n";
            #print $message->GetXML(),"\n";
            #print "===\n";
        
            if ($from eq 'ticket_distributor')
            {
                if ($body =~ /^ticketrelay /)
                {
                    &to_group($body);
                }
                elsif ($body =~ /^ackrelay /)
                {
                    &to_group_ack($body);
                }
                elsif ($body =~ /^ticketupdaterelay /)
                {
                    &to_group_update($body);
                }
                elsif ($body =~ /^ticketwithdrawrelay /)
                {
                    &to_group_withdraw($body);
                }
                elsif ($body =~ /^ticketclearrelay /)
                {
                    &to_group_clear($body);
                }
                elsif ($body =~ /^ticketcloserelay /)
                {
                    &to_group_close($body);
                }
                elsif ($body =~ /^ticketfwdrelay /)
                {
                    &to_group_fwd($body);
                }
            }
            else
            {
                if ($body =~ /^ticketnew /)
                {
                    &to_group($body);
                    &to_ticket_distributor($body);
                }
                elsif ($body =~ /^ack /)
                {
                    &to_ticket_distributor_ack($body);
                }
                elsif ($body =~ /^ticketupdate /)
                {
                    &to_ticket_distributor_update($body);
                }
                elsif ($body =~ /^ticketwithdraw /)
                {
                    &to_ticket_distributor_withdraw($body);
                }
                elsif ($body =~ /^ticketclear /)
                {
                    &to_ticket_distributor_clear($body);
                }
                elsif ($body =~ /^ticketclose /)
                {
                    &to_ticket_distributor_close($body);
                }
                elsif ($body =~ /^ticketfwd /)
                {
                    &to_ticket_distributor_fwd($body);
                }
            }
        }
        
        
        sub InIQ
        {
            my $sid = shift;
            my $iq = shift;
        
            my $from = $iq->GetFrom();
            my $type = $iq->GetType();
            my $query = $iq->GetQuery();
            my $xmlns = $query->GetXMLNS();
            #print "===\n";
            #print "IQ\n";
            #print "  From $from\n";
            #print "  Type: $type\n";
            #print "  XMLNS: $xmlns";
            #print "===\n";
            #print $iq->GetXML(),"\n";
            #print "===\n";
        }
        
        sub InPresence
        {
            my $sid = shift;
            my $presence = shift;
        
            my $from = $presence->GetFrom();
            my $type = $presence->GetType();
            my $status = $presence->GetStatus();
            #print "===\n";
            #print "Presence\n";
            #print "  From $from\n";
            #print "  Type: $type\n";
            #print "  Status: $status\n";
            #print "===\n";
            #print $presence->GetXML(),"\n";
            #print "===\n";
        
            if ($type eq 'subscribe')
            {
                my @usrreq = split('@', $from);
                my $usrreq = $usrreq[0] . '@' . $server;
                $Connection->Subscription(type => 'subscribed',
                                            to => $usrreq
                                            );
            }
        }
        
        # Functions for actions taken upon ticket
        sub to_ticket_distributor
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($msg[1]);
            my $group_assigned_groupnamechat = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $group_assigned_groupnamechat = $res->{group_assigned_groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => $msg[1] . ' ' . $group_assigned_groupnamechat);
        }
        
        sub to_ticket_distributor_ack
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1] $msg[2]\n";
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->do(qq{UPDATE sosrhs_tickets SET ticketstatus = $status{'WORK IN PROGRESS'}, user_accepted = '$msg[2]', tmstmp_accepted = now() WHERE ticket_id = $msg[1]});
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($msg[1]);
            my $user_creator_groups_id = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groups_id = $res->{user_creator_groups_id};
            }
            $sth->finish;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = ?});
            $sth->execute($user_creator_groups_id);
            my $user_creator_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ackrelay ' . $msg[1] . ' ' . $user_creator_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ackfinish ' . $msg[1]);
        }
        
        sub to_ticket_distributor_update
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1] $msg[2]\n";
            my $ticket_action = shift @msg;
            my $ticket_id = shift @msg;
            my $user_id_update = shift @msg;
            my $ticket_comment = join(' ', @msg);
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->prepare(qq{INSERT INTO sosrhs_tickets_comments (ticket_id, users_id, comment) VALUES (?, ?, ?)});
            $sth->execute($ticket_id, $user_id_update, $ticket_comment);
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($ticket_id);
            my $user_creator_groups_id = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groups_id = $res->{user_creator_groups_id};
            }
            $sth->finish;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = ?});
            $sth->execute($user_creator_groups_id);
            my $user_creator_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketupdaterelay ' . $ticket_id . ' ' . $user_creator_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketupdatefinish ' . $ticket_id);
        }
        
        sub to_ticket_distributor_withdraw
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
            my $ticket_action = shift @msg;
            my $ticket_id = shift @msg;
            my $user_id_withdraw = shift @msg;
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->do(qq{UPDATE sosrhs_tickets SET ticketstatus = $status{'WITHDRAWN'}, user_withdrawn = $user_id_withdraw, tmstmp_withdrawn = now() WHERE ticket_id = $ticket_id});
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($ticket_id);
            my $user_creator_groups_id = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groups_id = $res->{user_creator_groups_id};
            }
            $sth->finish;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = ?});
            $sth->execute($user_creator_groups_id);
            my $user_creator_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketwithdrawrelay ' . $ticket_id . ' ' . $user_creator_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketwithdrawfinish ' . $ticket_id);
        }
        
        sub to_ticket_distributor_clear
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
            my $ticket_action = shift @msg;
            my $ticket_id = shift @msg;
            my $user_id_clear = shift @msg;
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->do(qq{UPDATE sosrhs_tickets SET ticketstatus = $status{'CLEARED'}, user_cleared = $user_id_clear, tmstmp_cleared = now() WHERE ticket_id = $ticket_id});
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($ticket_id);
            my $user_creator_groups_id = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groups_id = $res->{user_creator_groups_id};
            }
            $sth->finish;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = ?});
            $sth->execute($user_creator_groups_id);
            my $user_creator_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketclearrelay ' . $ticket_id . ' ' . $user_creator_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketclearfinish ' . $ticket_id);
        }
        
        sub to_ticket_distributor_close
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
            my $ticket_action = shift @msg;
            my $ticket_id = shift @msg;
            my $user_id_close = shift @msg;
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->do(qq{UPDATE sosrhs_tickets SET ticketstatus = $status{'CLOSED'}, user_closed = $user_id_close, tmstmp_closed = now() WHERE ticket_id = $ticket_id});
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_users_v WHERE groups_id = (SELECT group_assigned_id FROM sosrhs_tickets_v WHERE ticket_id = ?)});
            $sth->execute($ticket_id);
            my $user_accepted_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_accepted_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketcloserelay ' . $ticket_id . ' ' . $user_accepted_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketclosefinish ' . $ticket_id);
        }
        
        sub to_ticket_distributor_fwd
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1] $msg[2]\n";
            my $ticket_action = shift @msg;
            my $ticket_id = shift @msg;
            my $user_id_fwd = shift @msg;
            my $group_id_fwd_to = shift @msg;
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->do(qq{UPDATE sosrhs_tickets SET ticketstatus = $status{'ASSIGNED'}, user_accepted = NULL, tmstmp_accepted = NULL, group_assigned = $group_id_fwd_to WHERE ticket_id = $ticket_id});
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{INSERT INTO sosrhs_tickets_comments (ticket_id, users_id, groups_id_fwd_to) VALUES (?, ?, ?)});
            $sth->execute($ticket_id, $user_id_fwd, $group_id_fwd_to);
            $dbh->commit;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = (SELECT group_assigned_id FROM sosrhs_tickets_v WHERE ticket_id = ?)});
            $sth->execute($ticket_id);
            my $user_fwd_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_fwd_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $sth = $dbh->prepare(qq{SELECT groupnamechat FROM sosrhs_groups WHERE id = (SELECT user_creator_groups_id FROM sosrhs_tickets_v WHERE ticket_id = ?)});
            $sth->execute($ticket_id);
            my $user_creator_groupchatname = '';
            while (my $res = $sth->fetchrow_hashref)
            {
                $user_creator_groupchatname = $res->{groupnamechat};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketfwdrelay ' . $ticket_id . ' ' . $user_fwd_groupchatname);
        
            $Connection->MessageSend(to => 'ticket_distributor@' . $server,
                                    type => 'chat',
                                    body => 'ticketfwdrelay ' . $ticket_id . ' ' . $user_creator_groupchatname);
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketfwdfinish ' . $ticket_id);
        }
        
        # Functions for relayed actions from ticket_distributor
        sub to_group
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => &build_new_ticket_message($msg[1]));
        }
        
        sub to_group_ack
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ackrelay ' . $msg[1]);
        }
        
        sub to_group_update
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketupdaterelay ' . $msg[1]);
        }
        
        sub to_group_withdraw
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketwithdrawrelay ' . $msg[1]);
        }
        
        sub to_group_clear
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketclearrelay ' . $msg[1]);
        }
        
        sub to_group_close
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketcloserelay ' . $msg[1]);
        }
        
        sub to_group_fwd
        {
            my $msg = shift;
            my @msg = split(' ', $msg);
            print "\n$username : $msg[0] $msg[1]\n";
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => 'ticketfwdrelay ' . $msg[1]);
        
            sleep 2;
        
            $Connection->MessageSend(to => $chatroom . '@conference.' . $server,
                                    type => 'groupchat',
                                    body => &build_new_ticket_message($msg[1]));
        }
        
        sub build_new_ticket_message
        {
            my $ticket_id = shift;
        
            my $dbname= 'db';
            my $dbuser= 'user';
            my $dbpass= 'pass';
            my $dbhost = 'localhost';
            my $dbport = 5432;
        
            my $dbh = DBI->connect("dbi:Pg:dbname=$dbname;host=$dbhost;port=$dbport", $dbuser, $dbpass, {AutoCommit => 0, RaiseError => 1});
            my $sth = $dbh->prepare(qq{SELECT * FROM sosrhs_tickets_v where ticket_id = ?});
            $sth->execute($ticket_id);
            my %ticket = ();
            while (my $res = $sth->fetchrow_hashref)
            {
                $ticket{ticket_id} = $res->{ticket_id};
                $ticket{ticketcategory_category} = $res->{ticketcategory_category};
                $ticket{ticketstatus_status} = $res->{ticketstatus_status};
                $ticket{ticketpriority_severityname} = $res->{ticketpriority_severityname};
                $ticket{tmstmp_assigned} = $res->{tmstmp_assigned};
                $ticket{user_creator_firstname} = $res->{user_creator_firstname};
                $ticket{user_creator_secondname} = $res->{user_creator_secondname};
                $ticket{group_assigned_groupname} = $res->{group_assigned_groupname};
                $ticket{ticket_text} = $res->{ticket_text};
                $ticket{ticket_file} = $res->{ticket_file};
                $ticket{subject} = $res->{subject};
                $ticket{user_creator_groups_id} = $res->{user_creator_groups_id};
            }
            $sth->finish;
        
            $dbh->disconnect;
        
            my $html_msg = q!<p id="p! . $ticket{ticket_id} . q!">
                                <img src="/sosrhs/images/! . $img{$ticket{ticketpriority_severityname}} . q!"/>&nbsp;<text id="t! . $ticket{ticket_id} . q!" class="textmainleft">! . substr($ticket{tmstmp_assigned}, 0, 16) . '&nbsp;|&nbsp;' . $ticket{ticketstatus_status} . '&nbsp;|&nbsp;' . $ticket{ticketcategory_category} . '&nbsp;|&nbsp;' . $ticket{subject} . '<br>From:&nbsp;' . $ticket{user_creator_firstname} . '&nbsp;' . $ticket{user_creator_secondname} . '&nbsp;|&nbsp;To:&nbsp;' . $ticket{group_assigned_groupname} . q!</text>&nbsp;|&nbsp;<a href="#" onClick="$('#explanation').fadeOut('fast'); $('div.divmainleft > p').css('background-color', 'white'); $('#p! . $ticket{ticket_id} . q!').css('background-color', '#E0E0F8'); $('#tdexplanation').load('/cgi-bin/sosrhs/ticket_details.pl?ticket_id=! . $ticket{ticket_id} . q!&my_groupchatname=! . $chatroom . q!');">Details</a>
                            </p>!;
        
                            #<hr id="h! . $ticket{ticket_id} . q!" style="height: 1px; border-width: 0; color: gray; background-color: gray;"/>!;
        
            return $html_msg;
        }
        

        【讨论】:

        • 这个设置的成本远低于我开发一些充当中间人的广泛日志守护程序的成本。非常感谢您的回答!
        • “Google Chatback 支持 MUC 吗?”这个问题还有待回答。也许那时一切都会变得不那么复杂。
        • 我不认为他们这样做,但托管我们自己的服务器将不得不这样做。
        【解决方案4】:

        为什么不使用 XMPP over HTTP,然后使用 HTTP 代理记录消息(将所有 XMPP 客户端设置为与 HTTP 代理而不是直接与端点通信)?

        【讨论】:

        • 我没想到,好主意!尽管 google talk 内置加密,代理能否读取数据?
        • 嗯,我猜不是 :-( 除非你想用伪造的证书来 MITM HTTPS,这不太可能是一个好主意。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-08-13
        • 2011-05-11
        • 2011-08-29
        • 1970-01-01
        • 2012-02-26
        • 1970-01-01
        相关资源
        最近更新 更多