Chatbot für Facebook Messenger mit dialog flow und node.js: Teil 1.

Überblick

Hier erstellen wir einen einfachen Facebook Messenger Chatbot mit dialogflow und Node.js. Wir werden nicht weiter darauf eingehen, aber wir werden alle Arten von Antworten behandeln, die die Messenger-Plattform unterstützt, wie z. B. eine generische Vorlage, Quittung, Schaltfläche, Medien, Liste und Grafik.

Voraussetzung

  • Facebook Seite
  • Facebook-Entwicklerkonto
  • Verständnis des Dialogflusses
  • Kenntnis von Node.js

Anfangen

Beginnen wir mit der Erstellung einer Facebook-App aus dem Facebook-Entwicklerkonto.

Sie werden zum Dashboard weitergeleitet. Fügen Sie von dort aus ein Messenger-Produkt hinzu

Wählen Sie nach dem Einrichten Ihre Facebook-Seite unter Token-Generierung aus und generieren Sie von dort aus Token.

Server einrichten

Das Erstellen eines einfachen Servers in node.js ist einfach.

Navigieren Sie zu dem gewünschten Ordner, in dem Sie dieses Projekt einrichten möchten. Öffnen Sie diesen Ordner in Ihrem Terminal und führen Sie npm init aus. Dadurch wird die Datei package.json generiert.

Jetzt müssen wir unsere Abhängigkeiten installieren. Führen Sie npm i apiai axios body-parser express uuid –save aus

Erstellen Sie nach der Installation der Abhängigkeiten die Datei index.js und importieren Sie die gerade installierten Abhängigkeiten und erstellen Sie einen einfachen Express-Server. Erstellen Sie außerdem eine config.js-Datei, damit wir unsere Anmeldeinformationen für eine bessere Codeverwaltung und Sicherheitszwecke in dieser Datei speichern können. Anstelle von config.js können Sie auch eine env-Datei erstellen.

Index.js

const apiai = erfordern ("apiai");
const express = require ("express");
const bodyParser = require ("body-parser");
const uuid = require ("uuid");
const axios = require ('axios');
// Konfigurationsdatei importieren
const config = require ("./ config");
// Port einstellen
app.set ("port", process.env.PORT || 5000);
// statische Dateien im öffentlichen Verzeichnis bereitstellen
app.use (express.static ("öffentlich"));
// Anwendung verarbeiten / x-www-form-urlencoded
app.use (
bodyParser.urlencoded ({
erweitert: falsch
})
);
// Anwendung / json verarbeiten
app.use (bodyParser.json ());
// Route indizieren
app.get ("/", Funktion (req, res) {
res.send ("Hallo Welt, ich bin ein Chat-Bot");
});
// zur Facebook-Überprüfung
app.get ("/ webhook /", Funktion (req, res) {
console.log ("Anfrage");
wenn (
req.query [“hub.mode”] === “subscribe” &&
req.query [“hub.verify_token”] === config.FB_VERIFY_TOKEN
) {
res.status (200) .send (req.query [“hub.challenge”]);
} else {
console.error ("Validierung fehlgeschlagen. Stellen Sie sicher, dass die Validierungstoken übereinstimmen.");
res.sendStatus (403);
}}
});
// Den Server hochfahren
app.listen (app.get ("port"), function () {
console.log ("Magic Started on Port", app.get ("Port"));
});

Starten Sie den Server. Wir müssen die Kommunikation live schalten, daher verwenden wir hier ngrok, um unseren lokalen Host live zu schalten. Sie können jedoch jederzeit jede andere Plattform wie Heroku, Localtunnel oder andere Dienste von Drittanbietern verwenden.

Um unseren Server live zu schalten, geben Sie ./ngrok http 5000 in Ihr Terminal ein, wodurch Sie eine Live-URL erhalten. Stellen Sie jedoch sicher, dass Sie ngrok für Ihr geeignetes Betriebssystem heruntergeladen haben, während Sie den obigen Befehl ausführen. Die Ngrok-Datei sollte sich in Ihrem aktuellen Arbeitsverzeichnis befinden, damit der obige Befehl erfolgreich ausgeführt werden kann.

Config.js

module.exports = {
FB_PAGE_TOKEN: "Seitenzugriffstoken",
FB_VERIFY_TOKEN: "Facebook-Bestätigungscode für Webhook",
API_AI_CLIENT_ACCESS_TOKEN: "DialogFlow-Token",
FB_APP_SECRET: "Facebook Secret Code",
};

FB_PAGE_TOKEN: Kopieren Sie das von uns generierte Seitenzugriffstoken und fügen Sie es in config.js ein. FB_APP_SECRET: App Secret finden Sie in den Einstellungen

Klicken Sie nun auf Webhook einrichten. Sie finden das direkt unter dem Fenster zur Token-Generierung. Fügen Sie Ihre Server-URL mit Endpoint / Webhook ein und Verify Token kann alles sein und Nachrichten und messaging_postbacks überprüfen.

Wenn Sie auf Überprüfen und Speichern klicken, erhalten Sie eine Bestätigungs-GET-Anfrage von Facebook. (Stellen Sie sicher, dass Sie https: // URL kopieren.)

FB_VERIFY_TOKEN: Fügen Sie das Überprüfungstoken in Ihre Datei config.js ein. SERVER_URL: Kopieren Sie Ihre ngrok-Live-URL und fügen Sie sie ein.

Dialogflow-Integration

Jetzt konfigurieren wir den Dialogfluss mit unserem Webhook-Code. Neuen Agenten hinzufügen und v1-API auswählen, Clientzugriffstoken kopieren und in API_AI_CLIENT_ACCESS_TOKEN einfügen.

Lassen Sie uns die Absicht im Dialogfluss erstellen.

  1. Fügen Sie die Absicht über die linke Seitenleiste hinzu.
  2. Geben Sie einen beabsichtigten Namen: Send-Text
  3. Fügen Sie Schulungsphrasen hinzu: „Hey, senden Sie mir ein Beispiel für eine Textnachricht“ oder eine relevante Nachricht.
  4. Fügen Sie den Aktionsnamen "send-text" hinzu.
  5. Speichern Sie es.
  6. Machen Sie jetzt dasselbe für Send-Image, Send-Media, Send-List, Send-Receipt, Send-Quick Reply, Send-Graph, Send-Carousel. Stellen Sie sicher, dass Sie allen Absichten die eindeutige Aktion geben. Wir müssen die Absicht eines Benutzers identifizieren, die entsprechende Antwort von unserem Webhook-Server zu senden.
  1. Klicken Sie auf die Registerkarte Erfüllung, fügen Sie hier Ihren Webhook-Endpunkt hinzu und speichern Sie ihn.
  1. Das ist nichts mehr in Dialogflow für dieses Beispiel.

Wenn Sie mit dem Dialogfluss nicht vertraut sind, lesen Sie bitte die Dokumentation.

Kehren wir zu index.js zurück. Fügen Sie dieses Code-Snippet hinzu, um eine Verbindung mit Dialogflow herzustellen.

const apiAiService = apiai (config.API_AI_CLIENT_ACCESS_TOKEN, {
Sprache: "en",
requestSource: "fb"
});
const sessionIds = new Map ();

Richten Sie den Webhook-Endpunkt ein

Wenn der Benutzer eine Nachricht auf Facebook sendet, erhalten wir die Post-Anfrage auf unserem Knotenserver. Wir müssen also diesen / webhook-Endpunkt behandeln.

/ *
* Alle Rückrufe für Messenger werden POST-bearbeitet. Sie werden an dieselbe gesendet
* Webhook. Abonnieren Sie Ihre App unbedingt auf Ihrer Seite, um Rückrufe zu erhalten
* für Ihre Seite.
* https://developers.facebook.com/docs/messenger-platform/product-overview/setup#subscribe_app
* *
* /
app.post ("/ webhook /", Funktion (req, res) {
var data = req.body;
// Stellen Sie sicher, dass dies ein Seitenabonnement ist
if (data.object == "page") {
// Iteriere über jeden Eintrag
// Im Stapel können mehrere vorhanden sein
data.entry.forEach (Funktion (pageEntry) {
var pageID = pageEntry.id;
var timeOfEvent = pageEntry.time;
// Iteriere über jedes Messaging-Ereignis
pageEntry.messaging.forEach (Funktion (messagingEvent) {
if (messagingEvent.message) {
receiveMessage (messagingEvent);
} else {
console.log ("Webhook hat unbekanntes messagingEvent erhalten:", messagingEvent);
}}
});
});
// Angenommen, alles ist gut gelaufen.
// Sie müssen innerhalb von 20 Sekunden eine 200 zurücksenden
res.sendStatus (200);
}}
});

Messages, Messaging_postbacks diese beiden Ereignisse, die wir beim Einrichten des Webhooks überprüft haben. (Wir verwenden hier kein Postback-Ereignis.) receiveMessage (messagingEvent) Lassen Sie uns diese Funktion jetzt ausführen.

Funktion receiveMessage (Ereignis) {
var senderID = event.sender.id;
var Empfänger-ID = event.recipient.id;
var timeOfMessage = event.timestamp;
var message = event.message;
if (! sessionIds.has (senderID)) {
sessionIds.set (senderID, uuid.v1 ());
}}
var messageId = message.mid;
var appId = message.app_id;
var metadata = message.metadata;
// Möglicherweise erhalten Sie einen Text oder Anhang, aber nicht beide
var messageText = message.text;
var messageAttachments = message.attachments;
if (messageText) {
// sende eine Nachricht an api.ai.
sendToApiAi (senderID, messageText);
} else if (messageAttachments) {
handleMessageAttachments (messageAttachments, senderID);
}}
}}

Wenn Sie das Ereignis trösten, erhalten Sie JSON wie folgt:

Konzentrieren Sie sich vorerst nur auf sender.id und What message.text. Wenn die Funktion receiveMessage () messageText enthält, rufen wir sendToApiAi () auf.

In dieser Funktion rufen wir zuerst sendTypingOn () auf, um zu zeigen, dass der Bot Messenger eingibt.

Funktion sendToApiAi (Absender, Text) {
sendTypingOn (Absender);
let apiaiRequest = apiAiService.textRequest (text, {
sessionId: sessionIds.get (Absender)
});
apiaiRequest.on ("Antwort", Antwort => {
if (isDefined (response.result)) {
handleApiAiResponse (Absender, Antwort);
}}
});
apiaiRequest.on ("Fehler", Fehler => console.error (Fehler));
apiaiRequest.end ();
}}

Typing On senden

SendTyping ruft die Facebook-API zum Senden der Typing-Aktion auf.

/ *
* Schalten Sie die Tippanzeige ein
* *
* /
const sendTypingOn = (Empfänger-ID) => {
var messageData = {
Empfänger: {
ID: Empfänger-ID
},
sender_action: "typing_on"
};
callSendAPI (messageData);
}}

Die Funktion callSendAPI () sendet die Nachrichtendaten, die wir generieren. (hier senden wir die Eingabe für die Aktion)

/ *
* Rufen Sie die Sende-API auf. Die Nachrichtendaten gehen in den Körper. Wenn erfolgreich, werden wir
* Erhalte die Nachrichten-ID in einer Antwort
* *
* /
const callSendAPI = async (messageData) => {
const url = "https://graph.facebook.com/v3.0/me/messages?access_token=" + config.FB_PAGE_TOKEN;
warte auf axios.post (url, messageData)
.then (Funktion (Antwort) {
if (response.status == 200) {
var receptId = response.data.recipient_id;
var messageId = response.data.message_id;
if (messageId) {
console.log (
"Nachricht mit ID% s erfolgreich an Empfänger% s gesendet",
Nachrichten ID,
Empfänger-ID
);
} else {
console.log (
"Send API für Empfänger% s erfolgreich aufgerufen",
Empfänger-ID
);
}}
}}
})
.catch (Funktion (Fehler) {
console.log (error.response.headers);
});
}}

Kehren wir zur Funktion sendToApiAi () zurück. Als Nächstes rufen wir eine Funktion isDefined () auf, um sicherzustellen, dass wir die richtige Antwort erhalten.

const isDefined = (obj) => {
if (typeof obj == "undefined") {
falsch zurückgeben;
}}
if (! obj) {
falsch zurückgeben;
}}
return obj! = null;
}}

In der gleichen Funktion sendToApiAi () erhalten wir die Antwort vom Dialogflow in Form von JSON.

Senden Sie diese Daten an handleApiAiResponse ().

Funktion handleApiAiResponse (Absender, Antwort) {
let responseText = response.result.fulfillment.speech;
let responseData = response.result.fulfillment.data;
let messages = response.result.fulfillment.messages;
let action = response.result.action;
let context = response.result.contexts;
let parameters = response.result.parameters;
sendTypingOff (Absender);
if (responseText == “” &&! isDefined (action)) {
// api ai konnte die Eingabe nicht auswerten.
console.log ("Unbekannte Abfrage" + response.result.resolvedQuery);
sende Textnachricht(
Absender,
„Ich bin mir nicht sicher, was du willst. Kannst du genauer sein?"
);
} else if (isDefined (Aktion)) {
handleApiAiAction (Absender, Aktion, Antworttext, Kontexte, Parameter);
} else if (isDefined (responseData) && isDefined (responseData.facebook)) {
Versuchen {
console.log ("Antwort als formatierte Nachricht" + responseData.facebook);
sendTextMessage (Absender, responseData.facebook);
} catch (err) {
sendTextMessage (Absender, err.message);
}}
} else if (isDefined (responseText)) {
sendTextMessage (Absender, responseText);
}}
}}

Senden Sie die Eingabe aus

Merken? Wir haben mit dem Tippen auf Aktion in Messenger begonnen. Jetzt haben wir die Antwort, es auszuschalten. Rufen Sie die Funktion sendTypingOff () auf.

/ *
* Schalten Sie die Tippanzeige aus
* *
* /
const sendTypingOff = (Empfänger-ID) => {
var messageData = {
Empfänger: {
ID: Empfänger-ID
},
sender_action: "typing_off"
};
callSendAPI (messageData);
}}

Sende Textnachricht

Immer wenn wir eine unbekannte Anfrage vom Benutzer erhalten, müssen wir eine Standardnachricht an diesen Benutzer senden.

const sendTextMessage = async (Empfänger-ID, Text) => {
var messageData = {
Empfänger: {
ID: Empfänger-ID
},
Botschaft: {
Text: Text
}}
};
warte auf callSendAPI (messageData);
}}

Die obige Funktion ruft die Facebook-Sende-API auf und sendet die Textnachricht, die wir als Standard definiert haben.

Wenn nun die Absicht des Benutzers mit dem Dialogfluss übereinstimmt, erhalten wir die Aktion (eine Aktion, die wir aus der Dialogflussantwort erhalten) dieser Absicht, basierend auf der Aktion, die wir an jeden Benutzer senden.

Wenn ein Benutzer fragt: "Senden Sie mir ein Beispiel für eine Textnachricht" -> wird unsere Absicht "Text senden" aufgerufen und basierend auf der Absicht erhalten wir die eindeutige Aktion davon. In meinem Fall habe ich denselben Aktionsnamen wie den Absichtsnamen angegeben.

Wenn wir eine Aktion aus der Dialogflussantwort erhalten, rufen wir handleApiAiAction () auf.

Funktion handleApiAiAction (Absender, Aktion, Antworttext, Kontexte, Parameter) {
Schalter (Aktion) {
case "send-text":
var responseText = "Dies ist ein Beispiel für eine Textnachricht."
sendTextMessage (Absender, responseText);
brechen;
Standard:
// nicht behandelte Aktion, senden Sie einfach den Text zurück
sendTextMessage (Absender, responseText);
}}

Ursprünglich veröffentlicht unter www.yudiz.com.

Geschrieben von Nikhil Savaliya