簡単なFacebookMessengerチャットボットを作成して遊んでいますが、メッセージを順番に送信するのに問題があります。
上記の例では、「Hello!」、「1」、「2」、「3」の順に印刷されているはずです。私は現在、この単純なテキストメッセージ機能を実装するために見つかったFacebookのドキュメントをフォローしています ここ 。 ExpressNode.JSサーバーコードを以下に含めました。
sendTextMessage()
関数の定義:
var request = require("request");
function sendTextMessage(user, text) {
messageData = {
text: text
};
request({
url: "https://graph.facebook.com/v2.6/me/messages",
qs: {access_token: PAGE_ACCESS_TOKEN},
method: "POST",
json: {
recipient: {id: user},
message: messageData
}
}, function(error, response, body) {
if (error) {
console.log("Error sending message: ", error);
} else if (response.body.error) {
console.log("Error: ", response.body.error);
} else {
console.log("Message successfully send.")
}
});
}
それを使用して応答を送信します。
sendTextMessage(user, "Hello!");
sendTextMessage(user, "1");
sendTextMessage(user, "2");
sendTextMessage(user, "3");
メッセージをキューに入れ、各request
の成功コールバックの後に一度に1つのメッセージのみを送信する単純なキューを実装しようとしました。これにより、MessengerAPIを正しく操作していないことが疑われます。
誰かがこの問題に遭遇しましたか?メッセージを順番に送信するにはどうすればよいですか?ありがとう!
単純なキューを実装しましたが、それでもこの問題が発生するため、単純なキューシステムのコードをここに含めます。
var queue = [];
var queueProcessing = false;
function queueRequest(request) {
queue.Push(request);
if (queueProcessing) {
return;
}
queueProcessing = true;
processQueue();
}
function processQueue() {
if (queue.length == 0) {
queueProcessing = false;
return;
}
var currentRequest = queue.shift();
request(currentRequest, function(error, response, body) {
if (error || response.body.error) {
console.log("Error sending messages!");
}
processQueue();
});
}
queueRequest(/* Message 1 */);
queueRequest(/* Message 2 */);
queueRequest(/* Message 3 */);
この「バグ」はFacebookに報告されましたが、修正されていないようです。 Facebookの投稿のチケットスレッドを読んでください ここ 彼らが言っていることの詳細については。 (これについてFacebookの注目を集めてくれたLouiseに感謝します)
同じ問題を抱えていたので、これについてFacebookにバグレポートを提出しました。彼らはそれが確かにバグであることを認め、それを修正するために取り組んでいます: https://developers.facebook.com/bugs/565416400306038
POSTを/ me/messagesに送信すると、メッセージIDを持つ応答が返されます(私の場合は「mid。」で始まります。これはおそらくメッセージIDを表しますか?):
{ recipient_id: '1015411228555555',
message_id: 'mid.1464375085492:b9606c00ca33c12345' }
FB Messenger APIによって完全に受信された後、受信を確認するWebhookへの呼び出し(メッセージイベントなし)を受け取ります。
{ sender: { id: '1015411228555555' },
recipient: { id: '566031806XXXXXX' },
delivery:
{ mids: [ 'mid.1464375085492:b9606c00ca33c12345' ],
watermark: 1464375085604,
seq: 176 } }
確実に配達してから次のメッセージを送るには、配達領収書が一番いいと思います。
送信リクエストをPromiseとして実装し、前のメッセージが解決された後にのみ結果のメッセージを送信します
const send = (userId, messageData) => {
return new Promise((resolve, reject) => {
request
(
{
url : BASE_URL + "me/messages",
qs : { access_token : PAGE_ACCESS_TOKEN },
method : "POST",
json :
{
recipient: { id : userId },
message: messageData,
}
}, (error, response, body) =>
{
if (error) { console.log("Error sending message: " + response.error); return reject(response.error); }
else if (response.body.error) { console.log('Response body Error: ' + response.body.error); return reject(response.body.error); }
console.log("Message sent successfully to " + userId);
return resolve(response);
}
);
});
};
静的タイムアウトを追加する代わりに、キューデータ構造を作成します。ボットがメッセージを送信したい場合は、キューの最後にコンテンツを追加します。メッセージポストコールバックで、キューにまだメッセージがあるかどうかを確認し、再帰を使用して関数を再度呼び出し、それに応じてキューから削除します。
私はまったく同じ問題を抱えていました、その解決策は私のために働きました:
function sendMessage(recipient, messages, accessToken, i) {
axios.post(baseURL + 'v2.11/me/messages/?access_token=' + accessToken,
Object.assign({}, {
messaging_type: "RESPONSE",
recipient: {
id: recipient
}
}, messages[i]['payload']) )
.then(response => {
if(i < messages.length) sendMessage( recipient, messages, accessToken, i+1 );
},
error => {})
.catch(error => {});
}
sendMessage(recipient, flow['messages'], flow['page']['accessToken'], 0);
それが私の質問です: Facebook Send-APIを使用したシーケンシャルメッセージ送信
約束によってQUEUING
を達成することができます。
function delay(time) {
return new Promise(function(resolve, reject) {
setTimeout(resolve, time);
});
}
delay(2000).then(() => {
console.log('hi');
delay(2000).then(() => {
console.log('hello');
delay(2000).then(() => {
console.log('welcome');
})
})
})
@ user3884594によって提案された再帰的ソリューションに基づいて、私はこれを使用してそれを機能させるようにしています(単純化するためにエラー処理を削除しました):
send_messages (["message 01", "message 02", "message 03"]);
function send_messages (which, i = 0)
{
request({
url: 'https://graph.facebook.com/v2.10/me/messages',
qs: { access_token: FACEBOOK_ACCESS_TOKEN },
method: 'POST',
json: { recipient: { id: senderId }, message: { text: which [i] }
}, (error, response, body) =>
{
// You need to put your error handling logic here
if (i++ < which.length - 1)
send_messages (which, i);
});
}
メッセージ処理を開始するたびに0にリセットされるmessageIdカウンターをアプリに追加しました。次に、その数* 100ミリ秒で遅延します。このようにして、messageDelay += 15
のようなコードで意図的な遅延を追加することもできます
receivedMessage(event) {
messageDelay = 0;
//...
sendMessage拡張:
function sendTextMessage(recipientId, messageText) {
//...
setTimeout(function() {
callSendAPI(messageData);
}, messageDelay++ * 100)
}
送信順に受信する必要があります。実際にそれらを順番に送信し、非同期関数を4回呼び出さないようにしてください(送信順序は保証されません)。 (あなたがそれをテストしたことを読みましたが、私のすべてのテストで、送信順序が保証されている場合、受信が故障するのを見たことがありません。)
リクエストはFacebookに非同期で送信され、任意の順序で送信できるため、メッセージは順番に送信されていません。
これを解決するには、応答を受信する前に送信する必要があるメッセージのときに、次のsendTextMessage
を呼び出す必要があります。