なぜ私はそれがログアウトする前に私のJabberボットに複数のメッセージを送信することがありますか?
-
22-09-2019 - |
質問
私は自分のJabberボットを作成しようとしていますが、私は少しトラブルに遭遇してきました。私は、ボットの存在を変更しようとする場合は、遅れが出るボットに送信するメッセージのすべてかのようにしかし、それはそうと、メッセージに応答する私のボットを頂いております。
私、私は、私はそれがオンラインであることを見ることができますので、私は存在を変更するスクリプトを実行するときの平均です。その後、私はそれを私がメッセージを設定したコールバックサブルーチンが呼び出される前に、それは3を取るメッセージを送信するとき。 thirrdメッセージが送信されると、チャットサブルーチンが呼び出された後、それはまだ私が送られた最初のメッセージを処理します。
これは本当に私はそれが私がメッセージ「ログアウト」を送信するときにログアウトするように設定していると、それはログアウトするために2件の以上のメッセージが続く必要があることを除いてあまり問題になりません。私はそれが私がこの問題を解決するためにしなければならないが、私は、私は、IQのコールバックを設定しているだけでなく、それが存在することを設定した後に2回呼び出されるので、それが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; }
あなたの助けをありがとう!
解決
あなたはあなたのためkeepItGoingルーチンのリソース不足を持っています。一般的には、同期これは仕事に行くされていないようにXMPPを使用しようとしています。私はあなたのコールバックが設定取得提案、そしてちょうどの 1 のループで処理を()を呼び出します。
プロセス用ドキュメント()と言うます:
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.
あなたがプロセス(呼び出すたびに)、あなたのコールバックの0以上が発生します。それは、サーバーのタイミングに依存するため、あなたは、どの知っていることはありません。あなたが何かを送信する前に戻すために)(プロセスのために必要がある場合は、ほとんど常にXMPPであなたを殺す、というよりもasych、同期考えている。
あなたがチャット()からkeepItGoingへの呼び出しを削除する場合はあなたのケースでは、私は物事はより多くのあなたが期待するように動作します賭けます。
他のヒント
の行を置き換えます:
$jabberBot->Process(1);
これらと
while (defined($jabberBot->Process(1))) {
# Do stuff here
}