【问题标题】:Facebook Messenger bot not sending messages in orderFacebook Messenger bot 未按顺序发送消息
【发布时间】:2016-09-06 05:56:58
【问题描述】:

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

在上面的示例中,它应该按顺序打印“Hello!”、“1”、“2”、“3”。我目前正在关注找到here 的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 帖子 here 上的票务线程,了解他们所说的详细信息。 (感谢 Louise 引起 Facebook 的关注)

【问题讨论】:

  • @brain 你找到解决办法了吗?
  • @Raju 我还没有找到明确的解决方案,但如果你看下面,有人确实为它提交了错误报告,我相信它正在处理中。我能够通过在消息队列上递归使用setTimeout 在发送消息之间实现任意 1 秒的延迟来解决它。它有效,但它似乎是一个黑客。希望有帮助!
  • 我们用这个npmjs.com/package/fibers解决了它
  • 感谢队列代码!这是一个简单的小解决方案:)
  • 我刚刚实现了一个排队系统,似乎可以解决这个问题,我的做法与此类似。

标签: node.js facebook messenger chatbot facebook-chatbot


【解决方案1】:

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

【讨论】:

  • 感谢您向 Facebook 提交该错误,希望他们能解决这个问题!
【解决方案2】:

在您向 /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 } }

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

【讨论】:

  • 我的错误,根据较新的 Facebook 开发人员的说法,无法保证交货收据,尽管这可能适用于某些开发环境,但这种技术实际上并不是产品中的好方法。我们目前正在实施延迟,但必须有更好的方法来处理这个问题,即使是大规模的。
【解决方案3】:

将发送请求实现为 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);
            }
        );    
    });
};

【讨论】:

    【解决方案4】:

    你可以通过promise实现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');
        })
      })
    })

    【讨论】:

      【解决方案5】:

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

      【讨论】:

      • 正如我在帖子底部提到的,我尝试实现一个队列,在每次成功发送回调后,我将在队列中递归地发送消息。令人惊讶的是,这仍然不起作用。
      • @Brian 是同一网络上的机器人和接收端吗?也许检索是如此即时,以至于下载时消息顺序混乱。
      • 我使用 messenger.com 作为我与机器人交互的“客户端”。机器人本身在 Heroku 服务器上作为 Node.js 应用程序运行。
      • @Brian 我必须对其进行研究,但我最好的猜测是信使后端实际上也是异步的,并且不依赖于“发送”时间,而是依赖于后端的时间将它们分发到接收端,因此即使以队列格式发送它们也是不可靠的。也许您可以尝试队列系统并在处理队列中的下一个之前添加任意延迟?至少这会给它一个小的缓冲区供后端处理请求。您还可以根据交货时间确定发送下一个,但这无关紧要...
      • 谢谢大通,我很惊讶我找不到任何类似的帖子。我自己也在研究它,如果我发现了什么,我会保持更新。我确定我不能是唯一的!
      【解决方案6】:

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

      【讨论】:

      • 感谢您的意见。我刚刚编辑了我的帖子以包含我添加的简单排队功能的代码。你能看看让我知道我做的事情是否与你不同吗?再次感谢!
      【解决方案7】:

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

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

      sendMessage 扩展:

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

      【讨论】:

        【解决方案8】:

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

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

        【讨论】:

          【解决方案9】:

          基于@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);
              });
          }
          

          【讨论】:

            【解决方案10】:

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

            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);
            

            这是我的问题:Sequential Message Sending Using Facebook Send-API

            【讨论】:

              【解决方案11】:

              您可以尝试将它们放在 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)    
              

              他们应该一个接一个。如果需要,您还可以将函数相互嵌入。

              【讨论】:

              • 不幸的是,我需要一个更“可扩展”的解决方案。我希望 Messenger API 中有一些我没有正确使用的东西,但是除了上面显示的我使用的内容之外,文档在任何细节上似乎都很稀疏。
              • 我已经尝试过这样做,它并不是那么可靠,并且某些消息存在极端延迟,因此您仍然无法 100% 地连续获取它们。如果 FB 可以实现它,像回调这样的更高效和可扩展的解决方案会很棒。虽然,我注意到这个聊天机器人可以轻松做到:messenger.com/t/chatbotsmagazine 所以我想知道他们是如何实现它的。
              猜你喜欢
              • 1970-01-01
              • 2017-06-04
              • 1970-01-01
              • 2018-11-25
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多