16

我正在尝试构建一个简单的 Facebook Messenger 聊天机器人,但无法按顺序发送消息。

在此处输入图像描述

在上面的示例中,它应该按顺序打印“Hello!”、“1”、“2”、“3”。我目前正在关注此处找到的 Facebook 文档来实现这个简单的短信功能。我在下面包含了我的 Express Node.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,该队列对消息进行排队,并且在每个成功回调之后一次只发送一条消息。这让我怀疑我没有正确地与 Messenger API 交互。

有没有人遇到过这个问题?如何让消息按顺序发送?谢谢!

编辑

因为我实现了一个简单的队列但仍然遇到这个问题,所以我在这里包含了我的简单队列系统的代码。

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 帖子上的票务线程,了解他们所说的情况的详细信息。(感谢 Louise 引起 Facebook 的关注)

4

11 回答 11

10

我向 Facebook 提交了一份关于此问题的错误报告,因为我遇到了同样的问题。他们承认这确实是一个错误并正在努力修复它:https ://developers.facebook.com/bugs/565416400306038

于 2016-06-22T20:57:07.363 回答
4

在您向 /me/messages 发送 POST 后,您将收到具有消息 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 } }

我认为送达回执是确保送达的最佳方式,然后发送下一条消息。

于 2016-05-27T18:56:36.110 回答
2

你可以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');
    })
  })
})

于 2019-12-20T09:27:35.257 回答
2

将发送请求实现为 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);
            }
        );    
    });
};
于 2017-04-10T12:24:54.517 回答
1

我将创建一个队列数据结构,而不是添加静态超时。当机器人想要发送消息时,将内容附加到队列的末尾。在消息发布回调中,检查队列中是否仍有消息,并使用递归再次调用该函数并相应地从队列中删除。

于 2016-05-14T01:47:29.350 回答
0

它们应该按照发送的顺序被接收。确保您实际上是按顺序发送它们而不是调用异步函数 4 次(并且不能保证发送顺序)。(我读到您对其进行了测试,但在我的所有测试中,如果保证发送顺序,我从未见过接收出现故障。)

于 2016-05-17T01:13:49.563 回答
0

我遇到了完全相同的问题,该解决方案对我有用:

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 进行顺序消息发送

于 2018-01-20T05:07:39.850 回答
0

基于@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);
    });
}
于 2017-09-21T04:07:10.013 回答
0

我向应用程序添加了一个 messageId 计数器,该计数器在每次消息处理开始时重置为 0。然后我用那个数字延迟 * 100 毫秒。这样,我也可以使用类似的代码添加故意延迟messageDelay += 15

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

sendMessage 扩展:

function sendTextMessage(recipientId, messageText) {
//...
  setTimeout(function() {
    callSendAPI(messageData);
  }, messageDelay++ * 100)    
}
于 2017-06-17T00:29:00.697 回答
0

消息没有按顺序发送,因为请求是异步发送到 facebook 的,并且可以按任何顺序发送。

要解决此问题,您必须在sendTextMessage收到响应之前应发送的消息时调用下一个。

于 2017-06-17T06:35:43.967 回答
-1

您可以尝试将它们放在 setTimeout 函数中,这样每个函数都会经过一段时间。

所以替换这个:

sendTextMessage(user, "Hello!");
sendTextMessage(user, "1");
sendTextMessage(user, "2");
sendTextMessage(user, "3");

有了这个:

sendTextMessage(user, "Hello!");              

// 1 second

setTimeout(function() {
    sendTextMessage(user, "1");
}, 1000)

// 2 seconds

setTimeout(function() {
    sendTextMessage(user, "2");
}, 2000)

// 3 seconds

setTimeout(function() {
    sendTextMessage(user, "3");
}, 3000)    

他们应该一个接一个。如果需要,您还可以将这些功能相互嵌入。

于 2016-05-14T01:39:22.837 回答