Почему я должен отправить несколько сообщений своему боту Jabber, прежде чем он выйдет из системы? - PullRequest
0 голосов
/ 29 марта 2010

Я пытаюсь создать своего собственного бота Jabber, но у меня возникли небольшие проблемы. Я заставил своего бота отвечать на сообщения, однако, если я пытаюсь изменить присутствие бота, то кажется, что все сообщения, которые вы отправляете боту, задерживаются.

Я имею в виду, что когда я запускаю скрипт, я меняю присутствие, чтобы видеть, что он в сети. Затем, когда я отправляю ему сообщение, требуется три, прежде чем вызывается функция обратного вызова, которую я настроил для сообщений. После отправки третьего сообщения и вызова подпрограммы чата он по-прежнему обрабатывает первое отправленное мной сообщение.

Это действительно не создает особых проблем, за исключением того, что у меня настроен выход из системы при отправке сообщения «выход из системы», и для выхода из него должны быть добавлены еще два сообщения. Я не уверен, что мне нужно сделать, чтобы это исправить, но я думаю, что это как-то связано с пакетами iq, потому что у меня также установлен обратный вызов iq, и он вызывается два раза после установки присутствия.

Вот мой исходный код:

#!/usr/bin/perl

use strict;
use warnings;

#Libraries
use Net::Jabber;
use DBI;
use DBD::mysql;

#--------------- Config Vars -----------------
# Jabber Client
my $jbrHostname = "DOMAINNAME"; 
my $jbrUserName = "USERNAME";
my $jbrPassword = "PASSWORD";
my $jbrResource = "RESOURCE";
my $jbrBoss = new Net::Jabber::JID();
$jbrBoss->SetJID(userid=>"USERNAME",server=>$jbrHostname);

# MySQL
my $dbHostname = "DOMAINNAME";
my $dbName = "DATABASENAME";
my $dbUserName = "USERNAME";
my $dbPassword = "PASSWORD";
#--------------- End Config -----------------

# connect to the db
my $dbh = DBI->connect("DBI:mysql:database=$dbName;host=$dbHostname",$dbUserName, $dbPassword, {RaiseError => 1}) or die "Couldn't connect to the database: $!\n";

# create a new jabber client and connect to server
my $jabberBot = Net::Jabber::Client->new();
my $status = $jabberBot->Connect(hostname=>$jbrHostname) or die "Cannot connect ($!)\n";
my @results = $jabberBot->AuthSend(username=>$jbrUserName,password=>$jbrPassword,resource=>$jbrResource);

if($results[0] ne "ok")
{
    die "Jabber auth error @results\n";
}

# set jabber bot callbacks
$jabberBot->SetMessageCallBacks(chat=>\&chat);
$jabberBot->SetPresenceCallBacks(available=>\&welcome);
$jabberBot->SetCallBacks(iq=>\&gotIQ);

$jabberBot->PresenceSend(type=>"available");
$jabberBot->Process(1);

sub welcome
{
    $jabberBot->MessageSend(to=>$jbrBoss->GetJID(),subject=>"",body=>"Hello There!",type=>"chat",priority=>10);
    &keepItGoing;
}

$jabberBot->MessageSend(to=>$jbrBoss->GetJID(),subject=>"",body=>"Hello There! Global...",type=>"chat",priority=>10);
#$jabberBot->Process(5);
&keepItGoing;

sub chat
{
    print "Chat Called!\n";
    my ($sessionID,$msg) = @_;
    $jabberBot->MessageSend(to=>$msg->GetFrom(),subject=>"",body=>"Chatting!",type=>"chat",priority=>10);
    if($msg->GetBody() ne 'logout')
    {
        print $msg->GetBody()."\n";
        &keepItGoing;
    }
    else
    {
        &killBot($msg);
    }

}

sub gotIQ
{
    print $_[1]->GetID()."\n";
    &chat;
}

sub keepItGoing
{
    print "Movin' the chains!\n";
    my $proc = $jabberBot->Process(1);
    while(defined($proc) && $proc != 1)
    {
        $proc = $jabberBot->Process(1);
    }
}

sub killBot
{
    $jabberBot->MessageSend(to=>$_[0]->GetFrom(),subject=>"",body=>"Logging Out!",type=>"chat",priority=>10);
    $jabberBot->Process(1);
    $jabberBot->Disconnect();
    exit;
}

Спасибо за вашу помощь!

Ответы [ 2 ]

0 голосов
/ 11 мая 2010

Заменить строку:

$jabberBot->Process(1);

с этими:

while (defined($jabberBot->Process(1))) {
    # Do stuff here
}
0 голосов
/ 30 марта 2010

У вас истощение ресурсов из-за вашей рутины keepItGoing. В общем, попытка использовать XMPP синхронно, как это, не сработает. Я предлагаю настроить ваши обратные вызовы, а затем просто вызвать Process () в one loop.

Документы для Process () говорят:

Process(integer) - takes the timeout period as an argument.  If no
                   timeout is listed then the function blocks until
                   a packet is received.  Otherwise it waits that
                   number of seconds and then exits so your program
                   can continue doing useful things.  NOTE: This is
                   important for GUIs.  You need to leave time to
                   process GUI commands even if you are waiting for
                   packets.  The following are the possible return
                   values, and what they mean:

                       1   - Status ok, data received.
                       0   - Status ok, no data received.
                     undef - Status not ok, stop processing.

                   IMPORTANT: You need to check the output of every
                   Process.  If you get an undef then the connection
                   died and you should behave accordingly.

Каждый раз, когда вы вызываете Process (), срабатывает 0 или более ваших обратных вызовов. Вы никогда не знаете, какой, так как это зависит от времени сервера. Если вы хотите, чтобы Process () возвращался перед отправкой чего-либо, вы почти всегда думаете синхронно, а не asych, что убивает вас в XMPP.

В вашем случае, если вы удалите вызов keepItGoing из чата (), держу пари, что все будет работать так, как вы ожидаете.

...