Facebook Messenger bot n’envoie pas de messages dans l’ordre

Je m’amuse à créer un simple chatbot sur Facebook Messenger et je ne parviens pas à envoyer des messages en séquence.

entrez la description de l'image ici

Dans l’exemple ci-dessus, il aurait dû afficher “Bonjour!”, “1”, “2”, “3” dans l’ordre. Je suis actuellement en train de suivre la documentation Facebook trouvée ici pour mettre en œuvre cette fonction de messagerie texte simple. J’ai inclus le code de mon serveur Express Node.JS ci-dessous:

Définir la fonction 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.") } }); } 

En l’utilisant pour envoyer une réponse:

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

J’ai même essayé d’implémenter une queue simple qui met en file d’ attente les messages et n’envoie qu’un message à la fois après le rappel réussi de chaque request . Cela me fait penser que je n’interagis pas correctement avec l’API Messenger.

Quelqu’un at-il rencontré ce problème? Comment puis-je obtenir des messages à envoyer en séquence? Merci!

MODIFIER

Comme j’ai implémenté une queue simple mais que je rencontre toujours ce problème, j’inclus ici le code de mon système de queue simple.

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

METTRE À JOUR

Ce “bug” a été signalé à Facebook, mais il semble qu’ils ne vont pas le réparer . Veuillez lire le fil de discussion sur le billet de Facebook ici pour plus de détails sur ce qui se passe. (Merci à Louise d’avoir attiré l’attention de Facebook à ce sujet)

J’ai soumis un rapport de bogue à Facebook à ce sujet car j’avais le même problème. Ils ont reconnu qu’il s’agissait bien d’un bogue et s’efforçaient de le corriger: https://developers.facebook.com/bugs/565416400306038

Après avoir envoyé un POST à ​​/ moi / messages, vous recevrez une réponse avec un identifiant de message (le début de ma lettre est ‘mid.’, Ce qui peut signifier identifiant de message?):

 { recipient_id: '1015411228555555', message_id: 'mid.1464375085492:b9606c00ca33c12345' } 

Après avoir été complètement reçu par l’API FB Messenger, vous recevez un appel à votre compte Webhook (sans événement de message) qui confirme la réception:

 { sender: { id: '1015411228555555' }, recipient: { id: '566031806XXXXXX' }, delivery: { mids: [ 'mid.1464375085492:b9606c00ca33c12345' ], watermark: 1464375085604, seq: 176 } } 

Je pense que le bon de livraison est le meilleur moyen d’en assurer la livraison, puis envoyez le message suivant.

Au lieu d’append des délais d’attente statiques, je créerais une structure de données de queue. Lorsque le bot veut envoyer un message, ajoutez le contenu à la fin de la queue. Sur le message après le rappel, vérifiez s’il rest des messages dans la queue, appelez à nouveau la fonction à l’aide de la récursivité et supprimez-la de la queue en conséquence.

Implémenter la demande d’envoi comme une promesse et envoyer les messages conséquents uniquement lorsque le précédent est résolu

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

Ils doivent être reçus dans l’ordre d’envoi. Assurez-vous de les envoyer dans l’ordre et de ne pas appeler une fonction asynchrone 4 fois (l’ordre d’envoi n’est pas garanti). (J’ai lu que vous l’aviez testée, mais lors de tous mes tests, je n’ai jamais vu une réception tomber en panne si la commande était garantie.)

J’ai ajouté un compteur messageId à l’application qui réinitialise à 0 à chaque début de traitement du message. Ensuite, je retarde avec ce nombre * 100 ms. De cette façon, je peux aussi append des délais intentionnels avec du code tel que messageDelay += 15

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

sendMessage extension:

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

Le message n’est pas envoyé dans l’ordre car la demande est envoyée de manière asynchrone à Facebook et peut être envoyée dans n’importe quel ordre.

Pour résoudre ce problème, vous devez appeler le prochain sendTextMessage lorsque le message doit être envoyé avant d’avoir reçu une réponse.

Sur la base de la solution récursive proposée par @ user3884594, je fais en sorte que cela fonctionne avec ceci (j’ai supprimé le traitement des erreurs afin de simplifier):

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

J’ai eu exactement le même problème, cette solution a fonctionné pour moi:

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

Voilà ma question: Envoi séquentiel de messages à l’aide de Facebook Send-API

Vous pouvez essayer de les insérer dans une fonction setTimeout afin que chacun d’eux aille après un certain temps.

Alors remplacez ceci:

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

Avec ça:

 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) 

Et ils devraient y aller les uns après les autres. Vous pouvez également intégrer les fonctions les unes dans les autres si besoin est.