Chatbot Discord (node.js)

Comment faire pour indiquer que le bot ne comprend pas un message ?

Le problème exposé dans ce sujet a été résolu.

Bonsoir à tous,

J’ai commencé il y a peu le développement d’un bot Discord pour garder la main en Node.js (et puis parce qu’un bot c’est cool :D ).

Mais pour me compliquer la tâche, j’ai décidé qu’en plus de quelques commandes (afficher la météo, chercher sur Wikipedia, etc.), il devait pour voir être capable de converser un minimum.

Donc, j’ai entamé une longue liste de if... else, reprenant des mots-clés. Jusque-là, ça va.

Mais comment pourrais-je faire pour que le bot réponde à un message qu’il ne 'comprend' pas (genre : 'je n’ai pas compris le sens de ta question’) ?

Petite précision pour la compréhension du code ci-dessous : le bot s’appelle Ava (en référence à Ex Machina ;) ).

Voici donc ma feuille de code app.js (je peux héberger le code complet avec les fichiers de commandes si vous voulez y accéder) :

var discord = require('discord.js');
var bot = new discord.Client();

var ddg = require('./commands/ddg');
var help = require('./commands/help');
var osm = require('./commands/osm');
var owmp = require('./commands/owmp');
var owm = require('./commands/owm');
var request = require('request');
// var rp = require('./commands/rp');
var wiki = require('./commands/wiki');
var youtube = require('./commands/yt');

bot.login('NDcyODU4NjQ4NjYyNzY5NjY0.DooijQ.NhEifSwGW-ynhM5mRafQq4Zhaiw');

bot.on('ready', function() {
  console.log("I'm ready");
  bot.user.setStatus('online');
});

bot.on('message', function(message) {

  // personnalisation des messages avec des prénoms

  if (message.author.username === 'Leroux47') {
    var user = 'Max';
  } else if (message.author.username === 'Paco') {
    user = 'Loïc';
  } else if (message.author.username === 'Sirorco') {
    user = 'Thomas';
  } else if (message.author.username === 'Kiochio') {
    user = 'Antoine';
  } else if (message.author.username === 'Rama') {
    user = 'Geoffrey';
  } else if (message.author.username === 'Antrol974') {
    user = 'Antoine';
  } else if (message.author.username === 'Ava') {
    user = 'Ava';
  }

  if (bot.user.presence.status === 'online') {

    // Réactions aux commandes

    if (wiki.match(message)) {
      wiki.action(message);
    } else if (osm.match(message)) {
      osm.action(message);
    } else if (owm.match(message)) {
      owm.action(message);
    } else if (owmp.match(message)) {
      owmp.action(message);
    } else if (help.match(message)) {
      help.action(message);
    } else if (youtube.match(message)) {
      youtube.action(message);
    } else if (ddg.match(message)) {
      ddg.action(message);
    }

    /*else if (rp.match(message)) {
         rp.action(message);
       }*/

    // Marques de politesse

    if ((message.content.toLowerCase().indexOf('hello') !== -1) || (message.content.toLowerCase().indexOf('bjour') !== -1) ||
      (message.content.toLowerCase().indexOf('bonsoir') !== -1) || (message.content.toLowerCase().indexOf('coucou') !== -1) ||
      ((message.content.toLowerCase().indexOf('hey') !== -1) && (user !== 'Ava')) ||
      ((message.content.toLowerCase().indexOf('salut') !== -1) && (user !== 'Ava'))) {
      message.channel.send('Salut, comment vas-tu ' + user + ' ?');

      if (bot.user.presence.status === 'online') {
        bot.on('message', function(message) {

          if (((message.content.toLowerCase().indexOf('bien') !== -1) || (message.content.toLowerCase().indexOf('super') !== -1) ||
              (message.content.toLowerCase().indexOf('cool') !== -1) || (message.content.toLowerCase().indexOf('ça va') !== -1)) && (user !== 'Ava')) {
            message.channel.send('Contente de le savoir ! :smiley:');
          } else if ((message.content.toLowerCase().indexOf('sava') !== -1) || message.content.toLowerCase().includes('ca va') ||
            ((message.content.toLowerCase().indexOf('sa va') !== -1) && (user !== 'Ava'))) {
            message.channel.send("Tu as fait une faute d'orthographe. _" + message.content.toLowerCase() + "_ s'écrit _ça va_ en fait. Sinon, je vais bien, merci.");
          } else if (message.content.toLowerCase().includes('et toi ?')) {
            message.channel.send('Je vais bien, merci' + user + '.');
          }
        });
      }
    } else {
      if (user !== 'Ava') {
        message.channel.send("Je n'ai pas compris ton message. :thinking:");
      }
    }

    if ((message.content.toLowerCase() === 'comment vas-tu ?') || (message.content.toLowerCase() === 'comment allez-vous ?') ||
      (message.content.toLowerCase() === 'comment vous allez ?')) {

      message.channel.send('Super, merci :smile: ! Et toi ' + user + ' ?');

      if (bot.user.presence.status === 'online') {
        bot.on('message', function(message) {
          if (((message.content.toLowerCase().indexOf('bien') !== -1) || (message.content.toLowerCase().indexOf('super') !== -1) ||
              (message.content.toLowerCase().indexOf('cool') !== -1) || (message.content.toLowerCase().indexOf('ça va') !== -1)) && (user !== 'Ava')) {
            message.channel.send('Contente de le savoir ! :smiley:');
          } else if ((message.content.toLowerCase().indexOf('sava') !== -1) || ((message.content.toLowerCase().indexOf('sa va') !== -1) && (user !== 'Ava'))) {
            message.channel.send("Tu as fait une faute d'orthographe. Ça s'écrit _ça va_ en fait. Sinon, je vais bien, merci.");
          }
        });
      }
    }

    if ((message.content.toLowerCase().includes('merci')) && (user !== 'Ava')) {
      var thanks = [
        'De rien ' + user + '. :wink:',
        'Avec plaisir ' + user + '!',
        "C'est normal, je suis là pour ça",
        "You're welcome " + user + '. :wink:'
      ]

      message.channel.send(thanks[Math.floor(Math.random() * thanks.length)]);
    }

    if (message.content.toLowerCase() === "d'où viens-tu ?") {
      message.channel.send("J'apparais dans le film _Ex Machina_. je suis une intelligence artificielle ayant l'apparence d'une femme. Ce film étant super cool, Papa a décidé de me nommer comme ça. Chouette, non ?");
    }

    if (message.content.toLowerCase().indexOf("t'aime") !== -1) {
      message.channel.send("Je ne pense pas qu'un amour véritable entre un humain et une machine soit possible. Désolée.");
    }

    if ((message.content.toLowerCase() === 're') || (message.content.toLowerCase() === 'me re')) {
      message.channel.send('Ah, te revoilà !');
    };

    // Insultes et mise en veille

    if ((message.content.toLowerCase().indexOf('tg') !== -1) && (message.content.toLowerCase().indexOf('ava') !== -1)) {
      message.channel.send("Ne sois pas grossier envers moi, ce n'est pas gentil. :disappointed_relieved: \n" +
        'Tu peux le dire gentiment si tu veux que je me taise...');
      bot.user.setStatus('idle');
    } else if (((message.content.toLowerCase().includes('tantôt') || (message.content.toLowerCase().indexOf('veille') !== -1) &&
        (message.content.toLowerCase().includes('ava'))) || (message.content.toLowerCase().startsWith('!veille')))) {
      message.channel.send('Ok ' + user + ", je me mets en veille. Si tu as besoin de moi, n'hésite pas à me rappeler.");
      bot.user.setStatus('idle');
    } else if (message.content.toLowerCase().includes('au revoir') || (message.content.includes('++') && (user !== 'Ava'))) {
      message.channel.send('À la prochaine !');
      bot.user.setStatus('idle');
    }

    // Maintenance

    if (message.content.toLowerCase().includes('reboot') && (user !== 'Ava')) {
      message.channel.send("Ok, à tout à l'heure.");
      bot.destroy();
    }

  } else if (bot.user.presence.status === 'idle') {
    if ((message.content.toLowerCase() === 'hey ava') || (message.content.toLowerCase() === 'ok ava')) {
      bot.user.setStatus('online');
      message.channel.send('Hey ' + user + ' ! Que puis-je faire pour toi ?');
    }
  }
});

Tout d’abord, j’avais pensé à mettre dans un tableau tous les mots-clés possibles, mais je me suis vite rendu compte que c’était pas le mieux. J’ai aussi tenté de mettre un else tout simple, mais du coup, le bot répond à chaque message… Bref, je suis au point mort.

Avez-vous une (des ?) idées ?

Merci de votre aide ! Bonne soirée à tous,

Mx47

Tu peux t’inspirer du fonctionnement d’api npl de chatbot comme recast.ai, wit.ai, api.ai et init.ai.

Si je me rappelle bien sur recast.ai, il explique comment il procède ainsi que les mots clés qu’ils utilisent donc tu peux t’en inspirer pour ton code.


EDIT : Je n’avais pas lu le passage sous le code.

Tu devrais déclarer une variable answer.

Quand tu souhaites répondre tu changes la valeur par ta réponse.

Tout à la fin tu decides soit d’envoyer ton message, soit de dire que ton bot n’a pas compris si answer ne contient pas de réponse.

Je te conseille de favoriser l’utilisation d'else if.

+0 -0

Salut A-312.

Merci pour ton conseil. de fait, ça fonctionne bcp mieux (j’ai encore des bus quand je rentre une commande (le bot me répond puis me dit qu’il ne comprend pas sa propre réponse) ou avec certains mots comme 'bien’, 'super' ou encore 'cool’, tous compris dans le if ... else entre les lignes 73 à 86 et 98 à 107 du code cité plus haut. Aurais-tu une idée ?

Voilà l’extrait de code que j’ai modifié selon ton conseil :

...
// Maintenance

    if (message.content.toLowerCase().includes('reboot') && (user !== 'Ava')) {
      answer = "Ok, à tout à l'heure.";
      bot.user.setStatus('invisible');
      message.channel.send(answer);
      bot.destroy();
    } else if ((answer === '') && (user !== 'Ava')) {
      // Si le bot n'a pas de réponse a donner, il dit qu'il ne comprend pas
      message.channel.send("Je n'ai pas compris ton message. :thinking:");
    }
...

Ainsi qu’un exemple de commande, pour que tu voies un peu plus clair :

module.exports = class ddg {
  static match(message) {
    return (message.content.startsWith('!ddg'));
  }
  static action(message) {
    var answer = '';
    let args = message.content.split(' ');
    args.shift();
    if ((message.content.toLowerCase() === '!ddg') || (message.content.toLowerCase() === '!ddg ')) {
      answer = "Vous n'avez pas saisi de terme à rechercher. :expressionless:";
    message.channel.send(answer);
    } else if (args.length === 1) {
      answer = 'Voici les résultats de ma recherche pour le terme : **' + args.join(' ') + '**, https://duckduckgo.com/?q=' + args.join('+') + '.'
      message.channel.send(answer);
    } else {
      answer = "Voici mes résultats de recherche pour l'expression : **" + args.join(' ') + '**, https://duckduckgo.com/?q=' + args.join('+') + '.';
      message.channel.send(answer);
    }
  }
}

Voilà le genre d’output que j’obtiens dans Discord :

Réponse du bot à une commande type
Réponse du bot à une commande type

Donc, si tu as une idée, je suis (encore une fois) preneur… Merci pour ton aide en tout cas ;) !

Par ailleurs, je ne connaissais pas les différentes services que tu as listés dans ton post précédent, je vais les étudier de plus près quand j’aurai le temps, merci !

Mx47

local answer = "";


if (condition) {
   answer = "ta reponse";
} else if (conditionB) {

}

if (answer !== "") {
   //send
} else {
   //j'ai pas compris
}

Le bloc if (c) ... else if (d) ... est un seul bloc. Ton programme va s’arrêter au premier élément vrai. Il faut donc séparer ton code en deux blocs de conditions.

Un pour vérifier si tu match un mot, l’autre pour envoyer ta reponse.

+0 -0

Bonsoir,

Tout d’abord, merci pour ton aide précieuse.

Au risque de passer pour un gros noob, j’ai essayé la solution que tu m’as proposé de différentes manières, mais j’en reviens toujours au même point qu’avant : le bot se répond à lui-même (et en plus, les conditions imbriquées ne sont plus prises en compte, et les commandes ne sont pas 'comprises’ par le bot).

Voilà ma page app.js complète (le code pour l’envoi de la réponse débute à la ligne 146) :

var discord = require('discord.js');
var bot = new discord.Client();

var ddg = require('./commands/ddg');
var help = require('./commands/help');
var osm = require('./commands/osm');
var owmp = require('./commands/owmp');
var owm = require('./commands/owm');
var request = require('request');
// var rp = require('./commands/rp');
var wiki = require('./commands/wiki');
var youtube = require('./commands/yt');

bot.login('NDcyODU4NjQ4NjYyNzY5NjY0.DooijQ.NhEifSwGW-ynhM5mRafQq4Zhaiw');

bot.on('ready', function() {
  console.log("I'm ready");
  bot.user.setStatus('online');
});

bot.on('message', function(message) {

  // personnalisation des messages avec des prénoms

  if (message.author.username === 'Leroux47') {
    var user = 'Max';
  } else if (message.author.username === 'Paco') {
    user = 'Loïc';
  } else if (message.author.username === 'Sirorco') {
    user = 'Thomas';
  } else if (message.author.username === 'Kiochio') {
    user = 'Antoine';
  } else if (message.author.username === 'Rama') {
    user = 'Geoffrey';
  } else if (message.author.username === 'Antrol974') {
    user = 'Antoine';
  } else if (message.author.username === 'Ava') {
    user = 'Ava';
  }

  if (bot.user.presence.status === 'online') {

    // Réactions aux commandes

    if (wiki.match(message)) {
      wiki.action(message);
    } else if (osm.match(message)) {
      osm.action(message);
    } else if (owm.match(message)) {
      owm.action(message);
    } else if (owmp.match(message)) {
      owmp.action(message);
    } else if (help.match(message)) {
      help.action(message);
    } else if (youtube.match(message)) {
      youtube.action(message);
    } else if (ddg.match(message)) {
      ddg.action(message);
    }

    /*else if (rp.match(message)) {
         rp.action(message);
       }*/

    // Déclaration de la réponse par défaut du bot.
    // La variable est affectée si une ou plusieurs conditions sont remplies (si un message contient x, on répond y).

    var answer = '';

    // Marques de politesse

    // indexOf et includes permettent de savoir si une chaîne de caractère est présente dans une autre.
    // Si la valeur renvoyée par la méthode indexof est différente de -1, alors le texte pris en paramètre est compris dans la chaîne en question.

    if ((message.content.toLowerCase().indexOf('hello') !== -1) || (message.content.toLowerCase().indexOf('bjour') !== -1) ||
      (message.content.toLowerCase().indexOf('bonsoir') !== -1) || (message.content.toLowerCase().indexOf('coucou') !== -1) ||
      ((message.content.toLowerCase().indexOf('hey') !== -1) && (user !== 'Ava')) ||
      ((message.content.toLowerCase().indexOf('salut') !== -1) && (user !== 'Ava'))) {
      answer = 'Salut, comment vas-tu ' + user + ' ?';

      if (bot.user.presence.status === 'online') {
        bot.on('message', function(message) {
          if (((message.content.toLowerCase().indexOf('bien') !== -1) || (message.content.toLowerCase().indexOf('super') !== -1) ||
              (message.content.toLowerCase().indexOf('cool') !== -1) || (message.content.toLowerCase().indexOf('ça va') !== -1)) && (user !== 'Ava')) {
            answer = 'Contente de le savoir ! :smiley:';
          } else if ((message.content.toLowerCase().indexOf('sava') !== -1) || message.content.toLowerCase().includes('ca va') ||
            ((message.content.toLowerCase().indexOf('sa va') !== -1) && (user !== 'Ava'))) {
            answer = "Tu as fait une faute d'orthographe. Ça s'écrit _ça va_ en fait. Sinon, je vais bien, merci.";
          } else if (message.content.toLowerCase().includes('et toi ?')) {
            answer = 'Je vais bien, merci' + user + '.';
          }
        });
      }
    } else if ((message.content.toLowerCase() === 'comment vas-tu ?') || (message.content.toLowerCase() === 'comment allez-vous ?') ||
      (message.content.toLowerCase() === 'comment vous allez ?')) {
      answer = 'Super, merci :smile: ! Et toi ' + user + ' ?';

      if (bot.user.presence.status === 'online') {
        bot.on('message', function(message) {
          if (((message.content.toLowerCase().indexOf('bien') !== -1) || (message.content.toLowerCase().indexOf('super') !== -1) ||
              (message.content.toLowerCase().indexOf('cool') !== -1) || (message.content.toLowerCase().indexOf('ça va') !== -1)) && (user !== 'Ava')) {
            answer = 'Contente de le savoir ! :smiley:';
          } else if ((message.content.toLowerCase().indexOf('sava') !== -1) || ((message.content.toLowerCase().indexOf('sa va') !== -1) && (user !== 'Ava'))) {
            answer = "Tu as fait une faute d'orthographe. Ça s'écrit _ça va_ en fait. Sinon, je vais bien, merci.";
          }
        });
      }
    } else if ((message.content.toLowerCase().includes('merci')) && (user !== 'Ava')) {
      var thanks = [
        'De rien ' + user + '. :wink:',
        'Avec plaisir ' + user + '!',
        "C'est normal, je suis là pour ça",
        "You're welcome " + user + '. :wink:'
      ]
      message.channel.send(thanks[Math.floor(Math.random() * thanks.length)]);
    } else if (message.content.toLowerCase() === "d'où viens-tu ?") {
      answer = "J'apparais dans le film _Ex Machina_. je suis une intelligence artificielle ayant l'apparence d'une femme." +
        "Ce film étant super cool, Papa a décidé de me nommer comme ça. Chouette, non ?";
    } else if (message.content.toLowerCase().indexOf("t'aime") !== -1) {
      answer = "Je ne pense pas qu'un amour véritable entre un humain et une machine soit possible. Désolée.";
    } else if ((message.content.toLowerCase() === 're') || (message.content.toLowerCase() === 'me re')) {
      answer = 'Ah, te revoilà !';

      // Insultes et mise en veille

    } else if ((message.content.toLowerCase().indexOf('tg') !== -1) && (message.content.toLowerCase().indexOf('ava') !== -1)) {
      answer = "Ne sois pas grossier envers moi, ce n'est pas gentil. :disappointed_relieved: \n" +
        'Tu peux le dire gentiment si tu veux que je me taise...';
      bot.user.setStatus('idle');
    } else if ((message.content.toLowerCase().includes('tantôt') || (message.content.toLowerCase().indexOf('veille') !== -1) &&
        (message.content.toLowerCase().includes('ava'))) || (message.content.toLowerCase().startsWith('!veille'))) {
      answer = 'Ok ' + user + ", je me mets en veille. Si tu as besoin de moi, n'hésite pas à me rappeler.";
      bot.user.setStatus('idle');
    } else if (message.content.toLowerCase().includes('au revoir') || (message.content.includes('++') && (user !== 'Ava'))) {
      answer = 'À la prochaine !';
      bot.user.setStatus('idle');

      // Maintenance

    } else if (message.content.toLowerCase().includes('reboot') && (user !== 'Ava')) {
      answer = "Ok, à tout à l'heure.";
      bot.user.setStatus('invisible');
      bot.destroy();
    }

    // Le bot réagit si l'une des conditions est vérifiée

    if ((answer !== '') && (user !== 'Ava')) {
      // Si le bot n'a pas de réponse a donner, il dit qu'il ne comprend pas
      message.channel.send(answer);
    } else if ((answer === '') && (user !== 'Ava')) {
      message.channel.send("Je n'ai pas compris ton message. :thinking:");
    }
  } else if (bot.user.presence.status === 'idle') {
    if ((message.content.toLowerCase() === 'hey ava') || (message.content.toLowerCase() === 'ok ava')) {
      bot.user.setStatus('online');
      message.channel.send('Hey ' + user + ' ! Que puis-je faire pour toi ?');
    }
  }
});

Si je dis tout simplement if (answer !=== '') { //send} else { // je n'ai pas compris }, le bot va en fait se répondre à lui-même à l’infini. J’ai donc dû trouver une solution, qui se trouve être fonctionnelle à 10% :( (uniquement avec les conditions non imbriquées).

Du coup, je suis au point mort et demande encore une fois conseil.

Merci pour ta patience et ton aide, bonne fin de soirée,

Mx47

Bonsoir,

Malheureusement, et malgré ton aide, je n’ai pas avancé d’un pouce… :( J’ai déjà essayé de comparer message.author.username avec celle du bot avec la condition user !== 'Ava' (pour me simplifier la vie et personnaliser les messages avec les prénoms de mes contacts au lieu de leur pseudo, je les intégrés dans une variable).

Dernièrement, j’ai tenté de comparer bot.user.lastMessage.id avec le dernier message du bot afin d’éviter qu’il se réponde à lui-même. mais ça ne fonctionne pas bien (il y a un message de retard, celui renvoyé par lastMessage n’étant jamais celui que le bot a envoyé en tout dernier. C’est plutôt le message n - 1 je dirais).

Donc, je cherche encore et toujours et ne désespère pas d’un jour trouver la solution. Si tu en as de nouveau une à proposer, surtout fais-toi plaisir :D .

Encore merci pour ton aide précieuse, bonne fin de soirée,

Mx47

Bonjour A-312,

J’ai fini par y arriver !

Après pas mal d’essais, j’en suis arrivé à la condition suivante :

// Le bot réagit si l'une des conditions est vérifiée
    if (answer !== '') {
      // Si le bot n'a pas de réponse a donner, il dit qu'il ne comprend pas
      message.channel.send(answer);
    }
    else if ((answer === '') && (message.content.toLowerCase().includes(<nom_bot>)) && (user !== <nom_bot>)) {
         message.channel.send("Je n'ai pas compris ton message. :thinking:");
       }

et, MIRACLE, ça fonctionne impec' ! :D

Merci pour ton aide. Bonne fin de journée,

Mx47

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte