web-dev-qa-db-ja.com

FacebookMes​​sengerボットがメッセージを順番に送信しない

簡単なFacebookMes​​sengerチャットボットを作成して遊んでいますが、メッセージを順番に送信するのに問題があります。

enter image description here

上記の例では、「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に感謝します)

13
Brian

同じ問題を抱えていたので、これについてFacebookにバグレポートを提出しました。彼らはそれが確かにバグであることを認め、それを修正するために取り組んでいます: https://developers.facebook.com/bugs/565416400306038

9
Louise

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 } }

確実に配達してから次のメッセージを送るには、配達領収書が一番いいと思います。

4
younglion

送信リクエストを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);
            }
        );    
    });
};
1
ninjadave

静的タイムアウトを追加する代わりに、キューデータ構造を作成します。ボットがメッセージを送信したい場合は、キューの最後にコンテンツを追加します。メッセージポストコールバックで、キューにまだメッセージがあるかどうかを確認し、再帰を使用して関数を再度呼び出し、それに応じてキューから削除します。

1
Corn Doggo

私はまったく同じ問題を抱えていました、その解決策は私のために働きました:

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を使用したシーケンシャルメッセージ送信

0
K. Kuksin

約束によって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');
    })
  })
})
0
Akshay Bande

@ 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

メッセージ処理を開始するたびに0にリセットされるmessageIdカウンターをアプリに追加しました。次に、その数* 100ミリ秒で遅延します。このようにして、messageDelay += 15のようなコードで意図的な遅延を追加することもできます

receivedMessage(event) {
  messageDelay = 0;
  //...

sendMessage拡張:

function sendTextMessage(recipientId, messageText) {
//...
  setTimeout(function() {
    callSendAPI(messageData);
  }, messageDelay++ * 100)    
}
0
csomakk

送信順に受信する必要があります。実際にそれらを順番に送信し、非同期関数を4回呼び出さないようにしてください(送信順序は保証されません)。 (あなたがそれをテストしたことを読みましたが、私のすべてのテストで、送信順序が保証されている場合、受信が故障するのを見たことがありません。)

0
pschang

リクエストはFacebookに非同期で送信され、任意の順序で送信できるため、メッセージは順番に送信されていません。

これを解決するには、応答を受信する前に送信する必要があるメッセージのときに、次のsendTextMessageを呼び出す必要があります。

0
Kayslay