web-dev-qa-db-fra.com

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

Je m'amuse à créer un simple chatbot sur Facebook Messenger et je n'arrive pas à envoyer les messages en séquence.

 enter image description here

Dans l'exemple ci-dessus, il aurait dû afficher "Bonjour!", "1", "2", "3" dans l'ordre. Je suis actuellement les documents Facebook trouvés 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 file d'attente simple qui met les messages en file d'attente et n'envoie qu'un message à la fois après chaque rappel de réussite de 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!

EDIT

Comme j'ai implémenté une file d'attente simple mais que je rencontre toujours ce problème, j'inclus ici le code de mon système de file d'attente 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 */);

UPDATE

Ce "bogue" 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 qu'ils disent se passe. (Merci à Louise d'avoir attiré l'attention de Facebook à ce sujet)

11
Brian

J'ai soumis un rapport de bogue à Facebook à ce sujet parce que j'avais le même problème. Ils ont reconnu qu’il s’agissait bien d’un bogue et travaillaient à le résoudre: https://developers.facebook.com/bugs/565416400306038

9
Louise

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.'

{ 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.

4
younglion

Implémenter la demande d'envoi en tant que promesse et n'envoyer les messages conséquents qu'une fois le précédent 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);
            }
        );    
    });
};
1
ninjadave

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

1
Corn Doggo

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

0
K. Kuksin

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);
    });
}
0
Emiliano Gonzalez

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 ajouter des délais intentionnels avec un code comme messageDelay += 15

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

sendMessage extension:

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

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

0
pschang

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 la prochaine variable sendTextMessage lorsque le message doit être envoyé avant qu'il ait reçu une réponse.

0
Kayslay