
Teilen Sie:
Shreyas Sreenivas is a High School Student currently residing in Bangalore, India. He has experience in building applications in JavaScript, TypeScript, Python and PHP. He's also a huge fan of React, GraphQL, Graph Databases and Serverless.
Bauen Sie einen WhatsApp und Messenger GraphQL Bot um Krankenhausbetten zu finden
Lesedauer: 13 Minuten
COVID hat sich auf uns alle ausgewirkt, auf einige jedoch mehr als auf andere. Eines der größten Probleme, mit denen die Menschen konfrontiert waren und immer noch sind, ist der Mangel an Krankenhausbetten. Vor ein paar Monaten habe ich eine GraphQL API, die die Verfügbarkeit von Betten in mehreren Städten und Bezirken in Indien liefert. Die Daten werden von offiziellen Websites gekratzt und in ein einheitliches Format normalisiert, das dann in Form einer GraphQL-API dargestellt wird.
Beachten Sie, dass die Daten nur für ausgewählte Städte in Indien verfügbar sind.
Sie können die API auch im GraphQL Spielplatz.
Mit Hilfe der Bedav API und der Vonage Messages API werden wir einen Chatbot erstellen, der mit WhatsApp und Facebook Messenger unter Verwendung von JavaScript funktioniert. Die Funktion dieses Chatbots besteht darin, den Nutzern bei der Suche nach Krankenhäusern in einer Stadt zu helfen, ein Krankenhaus mit freien Betten zu finden und zusätzliche Informationen über das Krankenhaus wie Telefonnummer und Adresse zu liefern. Wir werden auch einen Befehl erstellen, mit dem der Benutzer eine Wegbeschreibung zu einem Krankenhaus erhalten kann.
Voraussetzungen
Ein Vonage Account
Vonage API-Konto Um dieses Tutorial durchzuführen, benötigen Sie ein Vonage API-Konto. Wenn Sie noch keines haben, können Sie sich noch heute anmelden und mit einem kostenlosen Guthaben beginnen. Sobald Sie ein Konto haben, finden Sie Ihren API-Schlüssel und Ihr API-Geheimnis oben auf dem Vonage-API-Dashboard.
Projekt einrichten
Auch wenn der Code dafür im dem GitHub-Repositoryzu finden ist, empfiehlt es sich, diesem Tutorial zu folgen und das Repository nur als Referenz zu verwenden.
NPM initialisieren und Abhängigkeiten installieren
Beginnen Sie mit der Erstellung eines neuen Ordners, initialisieren Sie npm und erstellen Sie einen src Ordner darin:
Wir werden unsere Webhooks und unseren Server mit Express erstellen. Axios wird verwendet, um Anfragen an die Messages API zu senden und graphql-request wird verwendet, um Anfragen an die Bedav GraphQL API zu senden. Sie können sie zusammen mit weiteren Dienstprogrammen installieren, indem Sie den folgenden Befehl ausführen:
Und schließlich installieren Sie Nodemon als Dev-Abhängigkeit, damit wir unseren Node-Server nicht jedes Mal neu starten müssen, wenn wir eine Änderung vornehmen:
Fügen wir außerdem ein Skript zu unserem package.json um unseren Nodemon Dev-Server zu starten:
// package.json
{
"scripts": {
"dev": "nodemon src/app.js"
}
} Erstellen Sie die Webhooks
Bevor wir uns mit dem Code befassen: Was sind Webhooks? Webhooks sind im Wesentlichen eine URL, die jedes Mal aufgerufen wird, wenn eine bestimmte Aktion oder ein bestimmtes Ereignis ausgeführt wird. Webhooks können als ähnlich wie Rückrufe betrachtet werden, werden jedoch meist für die Interaktion zwischen zwei separaten und unabhängigen Anwendungen verwendet. In unserem Fall müssen wir zwei Webhooks bereitstellen: einen, der ausgelöst wird, wenn der Benutzer eine Nachricht sendet, und einen anderen, wenn eine Statusaktualisierung für eine Nachricht aus der API erfolgt (z. B. wenn der Benutzer eine von Ihnen gesendete Nachricht liest).
Richten wir zunächst Express in src/app.jseinrichten, wo wir unsere Haupt-Express-Anwendung und die Hauptfunktionen für die Verarbeitung von Befehlen haben:
// src/app.js
const express = require("express")
const app = express()
app.use(express.json())Als nächstes fügen wir zwei Endpunkte hinzu, einen für den Nachrichten-Webhook und einen weiteren für den Status-Webhook:
// src/app.js
const { fixedMessages, sendMessage } = require("./utils")
app.post("/webhooks/inbound", (request, response) => {
console.log(request.body)
)
app.post("/webhooks/status", (request, response) => {
console.log(request.body)
response.status(200).end()
})
app.listen(3000, () => {
console.log("Listening on port 3000")
})
Ngrok installieren und einrichten
Ngrok ermöglicht es Ihnen, Ihre Webhooks zu testen, indem Sie sie über eine temporäre URL dem Internet zugänglich machen. Um mit ngrok zu beginnen, können Sie auf die Website gehen und einen Account erstellen. Sobald Sie dies getan haben und eingeloggt sind, sollten Sie die Anweisungen zur Installation und Verbindung Ihres Accounts auf dem Dashboard sehen.
Nachdem wir nun ngrok installiert und konfiguriert haben, starten wir unseren Dev-Server, indem wir npm run dev. Verwenden Sie ngrok, um eine öffentliche URL für unseren lokalen Server zu erstellen, indem Sie ./ngrok http 3000. Dieser Befehl weist ngrok an, einen HTTP-Proxy für den Server zu erstellen, der auf localhost:3000.
Konfigurieren Sie die Nachrichten-Sandbox
Loggen Sie sich in das Vonage Dashboard ein und gehen Sie zu der Sandbox Abschnitt unter Nachrichten und Versand.

Um die WhatsApp-Sandbox zu erstellen, klicken Sie auf Zur Sandbox hinzufügen im Abschnitt WhatsApp. Die Vonage Sandbox muss Ihre Identität verifizieren. Dazu können Sie die im Dashboard angegebenen Schritte befolgen. Sie können ähnliche Schritte befolgen, um die Sandbox für Facebook Messenger zu erstellen.
Sie haben die WhatsApp-Sandbox nun erfolgreich aktiviert! Aber warten Sie, wir sind noch nicht fertig. Wir müssen Vonage noch die URL mitteilen, unter der unsere Webhooks zu finden sind. Wenn Sie auf der Sandbox-Seite nach unten scrollen, sollten Sie den Abschnitt "Webhooks" sehen, der etwa so aussieht wie unten:

Die erste ist der inbound Webhook, der auf der Route sein wird webhooks/inboundsein wird, also setzen Sie dieses Feld auf https://<your-ngrok-https-url>/webhooks/inbound. Setzen Sie auch die URL des status Webhook auf https://<your-ngrok-https-url>/webhooks/status. Jetzt sind wir mit der Einrichtung unserer Sandbox und Testumgebung fertig!
Hinweis: Jedes Mal, wenn Sie ngrok neu starten, erhalten Sie eine neue und andere URL, die Sie manuell im Vonage Dashboard ändern müssen.
Zurücksenden einer Nachricht an den Benutzer
Wir benötigen eine Hilfsfunktion, mit der wir Nachrichten an den Benutzer zurücksenden können.
Zunächst müssen wir unsere Vonage API-Anmeldedaten einrichten, damit wir die Messages API nutzen können. Diese Anmeldeinformationen werden in Umgebungsvariablen gespeichert. Erstellen Sie eine .env Datei im Stammverzeichnis des Ordners. Um die Umgebungsvariablen in die Knotenumgebung zu laden, verwenden wir das dotenv Paket. Fügen Sie die Felder wie unten aufgeführt hinzu:
VONAGE_API_KEY = // Your Vonage API key
VONAGE_API_SECRET = // Your Vonage API Secret
WHATSAPP_NUMBER = // The from number in the case of the WhatsApp Sandbox
MESSENGER_ID = // The from ID of the Messenger SandboxSobald das erledigt ist, fügen Sie den folgenden Code am Anfang von app.js ein, um die Umgebungsvariablen hinzuzufügen:
// src/app.js
require("dotenv").config()Erstellen Sie eine neue Datei mit dem Namen utils.js im Ordner src Ordner. Diese wird unsere Hilfsfunktionen enthalten, wie z. B. die Formatierung und das Senden einer Nachricht an den Benutzer.
Wir werden eine Anfrage an die Messages REST API stellen, um eine Nachricht zu senden. Im Falle der Messages Sandbox lautet die URL für die API https://messages-sandbox.nexmo.com/v0.1/messages. Wir werden Axios verwenden, um die Anfragen zu senden. Wir können mit der Option auth Option verwenden, um unsere API-Anmeldeinformationen wie unten gezeigt hinzuzufügen:
// src/utils.js
const axios = require("axios")
// default message type will be `text`
const sendMessage = async (to, message, type = "text") => { let from = {
// either 'WhatsApp' or 'messenger'
type: to.type,
}
if (to.type === "whatsapp") {
// the WhatsApp Sandbox number
from.number = proccess.env.WHATSAPP_NUMBER
} else if (to.type === "messenger") {
// the Messenger Sandbox ID
from.id = process.env.MESSENGER_ID
}
await axios.post(
"https://messages-sandbox.nexmo.com/v0.1/messages",
{
to,
from,
message: {
content: {
type,
[type]: message,
},
},
},
{
auth: {
username: process.env.VONAGE_API_KEY,
password: process.env.VONAGE_API_SECRET,
},
}
)
}
module.exports = {
sendMessage,
}
Der Nachrichtentyp ist dynamisch, denn wir werden eine Nachricht des Typs location senden, wenn der Benutzer eine Wegbeschreibung zu einem Krankenhaus anfordert. Auf WhatsApp wird eine Nachricht des Typs location eine Miniaturansicht des Standorts auf Google Maps zusammen mit dem angegebenen Namen und der Adresse an.
Erstellen Sie die Befehle
Nun können wir mit der Erstellung unserer Befehle beginnen:
help- Ein Menü mit allen Befehlen, die Sie verwenden könnencities- Erhalten Sie eine Liste aller verfügbaren Städtesearch <hospital-name> in <location>- Suchen Sie nach einem Krankenhaus an einem bestimmten Ort. Ein Beispiel,search sakra in bangaloresucht nach Krankenhäusern mit dem Namen Sakra in Bangalore.get directions to <hospital-id>- Erhalten Sie eine Wegbeschreibung zu einem Krankenhaus mit einer bestimmten ID. Zum Beispiel,get directions to 87sendet den Standort des Krankenhauses mit der ID 87.
Der Handler für eingehende Nachrichten
Lassen Sie uns eine Funktion erstellen, die die Anfragen an den inbound Webhook unter /webhooks/inbound. Diese Funktion analysiert die vom Benutzer gesendete Nachricht und übergibt die Nachricht an den Handler des Befehls, den der Benutzer zu verwenden versucht. Sie sendet die entsprechende Nachricht zurück und gibt einen Statuscode von 200 zurück.
Beachten Sie, dass der Webhook mit einem Statuscode von 200 antworten muss, andernfalls sendet die Messages API so lange eine Anfrage an den Webhook, bis sie eine 200-Antwort erhält.
Wir verwenden reguläre Ausdrücke, um zu prüfen, ob der Benutzer versucht, die search oder directions zu verwenden, und leiten dann die Nachricht an den entsprechenden Handler weiter. Wenn die Nachricht help, hi, , oder helloist, wird die Hilfemeldung an den Benutzer gesendet. Wenn die Nachricht citiesist, wird die Liste der verfügbaren Städte an den Benutzer gesendet. Und wenn die Nachricht keinem Befehl entspricht, wird eine ungültige Nachricht an den Benutzer gesendet.
// src/app.js
const handleInbound = async (request, response) => {
const content = request.body.message.content
const text = content.text.toLowerCase().trim()
// whom we have to reply to
const to = request.body.from
const searchRegex = /^search .* in .*$/i
const directionsRegex = /^get directions to .*/i
if (text.match(searchRegex)) {
handleSearch(text, to)
} else if (text.match(directionsRegex)) {
handleDirections(text, to)
} else if (["help", "hi", "hello"].includes(text)) {
sendMessage(to, fixedMessages.help)
} else if (text === "cities") {
sendMessage(to, fixedMessages.cities)
} else {
sendMessage(to, `Sorry, invalid message. Type *help* to get a list of all commands.`)
}
response.status(200).end()
}
Ändern wir nun den Handler für den eingehenden Webhook-Endpunkt, um die handleInbound Funktion.
// src/app.js
app.post("/webhooks/inbound", handleInbound) Die Befehle Hilfe und Willkommen
Wenn der Benutzer unseren Dienst zum ersten Mal kontaktiert, brauchen wir eine Nachricht, mit der wir ihn begrüßen können. Diese Nachricht sollte Informationen darüber enthalten, was unser Bot tut und welche verschiedenen Befehle zur Verfügung stehen. Außerdem brauchen wir eine Hilfsnachricht, die immer dann gesendet wird, wenn der Benutzer nicht weiß, was er tun soll und Folgendes eingibt help. Diese Nachrichten können ähnlich sein.
Die Bedav-API enthält nur Informationen über Krankenhäuser in bestimmten Regionen. Wir brauchen auch eine Nachricht, die eine Liste der Regionen enthält, in denen die Informationen verfügbar sind.
Wie in der Funktion handleInbound Funktion implementiert ist, wird die Hilfemeldung gesendet, wenn der Benutzer hallo, hallooder Hilfe und die Nachricht über die verfügbaren Städte wird gesendet, wenn der Benutzer Folgendes eingibt Städte.
Da diese beiden Meldungen konstant sind, können wir ein konstantes Objekt auf der obersten Ebene erstellen, um alle festen Meldungen zu definieren. Wir verwenden auch outdent um die zusätzlichen Leerzeichen in unserer Zeichenkette zu entfernen, die als Einrückung in unserem Code dienen sollen. Fügen Sie den Code in utils.js:
// src/utils.js
const outdent = require("outdent")
const fixedMessages = {
help: outdent`
The Bedav Bot gives you information on the availability of beds in hospitals and the contact information and location of those hospitals as well.
You can use the following commands:
1. *help* - Get this menu and all the commands you can use
2. *cities* - Get a list of all the cities available
2. *search* _<hospital-name>_ *in* _<location>_ - Search for a hospital in a particular location. For example, "search sakra in bangalore" searches for hospitals with the name Sakra in Bangalore
3. *get directions to* _<hospital-id>_ - Get directions to a hospital with a particular ID. You can get the hospital ID from the search results. The serial number preceding the Hospital name is the Hospital ID. For example, if the search result has _(87) Sakra Hospital_, send _get directions to 87_ to get directions to Sakra Hospital.
`,
cities: outdent`
The cities/districts currently available are:
*Karnataka*
1. Bangalore/Bengaluru
*Maharashtra*
2. Pune
3. Kohlapur
4. Sangli
5. Satara
6. Solapur
*Andhra Pradesh*
7. Anantapur
8. Chittoor
9. East Godavari
10. Guntur
11. Krishna
12. Kurnool
13. Prakasam
14. Nellore
15. Srikakulam
16. Vishakapatanam
17. Vizianagaram
18. West Godavari
19. Kadapa
`,
}
module.exports = {
...
fixedMessages,
} GraphQL-Client einrichten
Um die Abfrage der GraphQL-API zu vereinfachen, werden wir die graphql-request Bibliothek. Um den GraphQL-Client einzurichten, erstellen wir eine Instanz von GraphQLClient und geben die URL der GraphQL-API an.
// app.js
const { GraphQLClient } = require("graphql-request")
const client = new GraphQLClient("https://bedav.org/graphql") Erstellen einiger Utility-Funktionen
Wie bereits in der Beschreibung des hospitalId Feldes in den API-Dokumenten erwähnt, handelt es sich um eine Base64-kodierte Zeichenfolge, die dekodiert werden kann Hospital:<hospitalId> wobei hospitalId eine ganze Zahl ist, die für das Krankenhaus eindeutig ist. Aus Gründen, die Sie im nächsten Abschnitt sehen werden, lassen Sie uns zwei Funktionen erstellen: eine, um die Nummer der Krankenhaus-ID zu erhalten, und eine weitere, um eine ganze Zahl in einen Base64-String der folgenden Form zu kodieren Hospital:<hospitalId>. Wir verwenden die js-base64 Bibliothek, die wir vorhin zu unserem Projekt hinzugefügt haben, um mit den base64 kodierten Zeichenketten.
// src/utils.js
const { encode, decode } = require("js-base64")
const getHospitalId = (encodedId) => {
return decode(encodedId).slice(9)
}
const getEncodedString = (hospitalId) => {
return encode(`Hospital:${hospitalId}`)
}
module.exports = {
...
getEncodedString,
}
Der Suchbefehl
Utility-Funktionen zum Formatieren von Zeichenketten
Erstellen wir zwei weitere Hilfsfunktionen zur Formatierung der Krankenhausdaten, eine zur Formatierung eines einzelnen Krankenhauses und eine weitere, die diese Funktion zur Formatierung einer Gruppe von Krankenhäusern verwendet.
// src/utils.js
const getFormattedHospital = (hospital) => {
const index = getHospitalId(hospital.id)
const roundedString = (occupied, total) => {
return `${Math.floor((occupied * 100) / total)}% Occupied`
}
const h = hospital
// Percentages of beds available
const percentages = {
icu: roundedString(h.icuOccupied, h.icuTotal),
hdu: roundedString(h.hduOccupied, h.icuTotal),
oxygen: roundedString(h.oxygenOccupied, h.icuTotal),
general: roundedString(h.generalOccupied, h.icuTotal),
ventilators: roundedString(h.ventilatorsOccupied, h.icuTotal),
}
const formatted = outdent`
*(${index}) ${hospital.name}*
${h.icuTotal !== 0 && h.icuAvailable !== null ? `_ICU Available_: ${h.icuAvailable} (${percentages.icu})` : ""}
${h.hduTotal !== 0 && h.icuAvailable !== null ? `_HDU Avalable_: ${h.hduAvailable} (${percentages.hdu})` : ""}
${h.oxygenTotal !== 0 && h.oxygenAvailable !== null ? `_Oxygen Available_: ${h.oxygenAvailable} (${percentages.oxygen}})` : ""}
${h.generalTotal !== 0 && h.generalAvailable !== null ? `_General Available_: ${h.generalAvailable} (${percentages.general})` : ""}
${
h.ventilatorsTotal !== 0 && h.ventilatorsAvailable !== null
? `_Ventilators Available_: ${h.ventilatorsAvailable} (${percentages.ventilators})`
: ""
}
${h.phone !== null ? `_Phone_: ${h.phone}` : ""}
${h.phone !== null ? `_Website_: ${h.website}` : ""}
`
return removeEmptyLines(formatted)
}
Nicht jedes Krankenhaus verfügt über Betten auf der Intensivstation, der Intensivstation und der allgemeinen Station und nicht alle haben Sauerstoff und Beatmungsgeräte zur Verfügung. Wenn das Krankenhaus nicht über eines dieser Geräte verfügt, können wir diese Information in der Meldung weglassen. Das Krankenhaus hat eine bestimmte Art von Bett, Sauerstoff oder Beatmungsgerät nicht verfügbar, wenn die Gesamtzahl der verfügbaren Betten gleich Null ist oder wenn der Wert des Feldes "Verfügbar" gleich Null ist.
Wir drucken auch die Krankenhaus-ID aus, da der Benutzer die ID des Krankenhauses im Befehl get directions angeben muss. Wir zeigen dem Benutzer auch den Prozentsatz der belegten Betten in Klammern an.
Wenn kein Bett, Beatmungsgerät oder Sauerstoff verfügbar ist, bleibt eine Leerzeile übrig. Um dies zu beheben, erstellen wir eine weitere Hilfsfunktion, um diese Leerzeilen zu entfernen.
Um auf leere Zeilen zu prüfen, verwenden wir einen kurzen regulären Ausdruck, der prüft, ob die Zeile mehr als ein Leerzeichen enthält:
// src/utils.js
const removeEmptyLines = (string) => {
const lines = string.split("\n")
const newLines = []
for (const line of lines) {
// Continue if the line is a blank line
if (line.match(/^\s*$/)) continue
newLines.push(line)
}
return newLines.join("\n")
}
Als Nächstes erstellen Sie die Funktion zur Formatierung einer Liste von Krankenhäusern, indem Sie eine Schleife über alle Krankenhäuser ziehen, die formatierte Zeichenfolge für das jeweilige Krankenhaus abrufen und eine Leerzeile zwischen den einzelnen Krankenhäusern einfügen:
// src/utils.js
const getFormattedHospitals = (hospitals) => {
let message = ""
for (const hospital of hospitals) {
const formattedHospital = getFormattedHospital(hospital)
message += formattedHospital + "\n\n"
}
return message
}
module.exports = {
...
getFormattedHospitals,
}
Der Befehlshandler
Alle GraphQL-Abfragen werden in der Datei queries.js Datei im Ordner src Ordner gespeichert.
Wir verwenden die folgende GraphQL-Abfrage, um nach einem Krankenhaus an einem bestimmten Ort zu suchen und die erforderlichen Daten abzurufen. Das name Argument des Ortsfeldes wird verwendet, um der API mitzuteilen, welche Daten des Ortes wir abfragen. Das first Argument des Feldes hospitals Feldes gibt an, wie viele Krankenhäuser die API zurückgeben soll, und das searchQuery Argument liefert die Suchanfrage.
// src/queries.js
const searchGraphQLQuery = gql`
query($location: String, $query: String) {
# get hospitals from a city named Bengaluru in the state of Karnataka
locality(name: $location) {
hospitals(first: 5, searchQuery: $query) {
edges {
node {
id
name
phone
website
address
latitude
longitude
icuAvailable
hduAvailable
oxygenAvailable
generalAvailable
ventilatorsAvailable
icuOccupied
hduOccupied
oxygenOccupied
generalOccupied
ventilatorsOccupied
icuTotal
hduTotal
oxygenTotal
generalTotal
ventilatorsTotal
}
}
}
}
}
`
module.exports = {
searchGraphQLQuery,
}
`Beachten Sie, dass wir unsere GraphQL-Abfrage nicht mit dem
gqlTag umschließen. Aber mit den richtigen Erweiterungen und Werkzeugen können wir eine schöne Syntaxhervorhebung und Typüberprüfung erhalten.
Als nächstes müssen wir die Ortsnamen auf das name Argument des Feldes locality Feldes zuordnen, das in der Form <city/district_name>-<state_name>. Die Abbildung der city/district auf die Lokalität name kann in JavaScript in das folgende Objekt umgewandelt werden:
// src/utils.js
const locationKey = {
bangalore: "bengaluru-karnataka",
bengaluru: "bengaluru-karnataka",
pune: "pune-maharashtra",
kohlapur: "kohlapur-maharashtra",
sangli: "sangli-maharashtra",
satara: "satara-maharashtra",
solapur: "solapur-maharashtra",
anantapur: "anantapur-andhra pradesh",
chittoor: "chittoor-andhra pradesh",
"east godavari": "east godavari-andhra pradesh",
guntur: "guntur-andhra pradesh",
krishna: "krishna-andhra pradesh",
kurnool: "kurnool-andhra pradesh",
prakasam: "prakasam-andhra pradesh",
nellore: "spsr nellore-andhra pradesh",
srikakulam: "srikakulam-andhra pradesh",
vishakapatanam: "vishakapatanam-andhra pradesh",
vizianagaram: "vizianagaram-andhra pradesh",
"west godavari": "west godavari-andhra pradesh",
kadapa: "kadapa-andhra pradesh",
}
module.exports = {
...
locationKey,
}Der Text, den der Benutzer eingibt, um nach einem Krankenhaus an einem bestimmten Ort zu suchen, hat das Format search <search-query> in <location>. Erstellen wir die handleSearch Funktion, die die Suchanfrage und den Ort aus der Nachricht des Benutzers erhält. Diese Funktion ist für die Ausführung der Suchanfrage und die Rücksendung der entsprechenden Antwort an den Benutzer verantwortlich:
// src/app.js
const { fixedMessages, sendMessage, locationKey, getFormattedHospitals } = require("./utils")
const handleSearch = async (message, to) => {
// extract the search query and location from the message
const searchRegex = /^search (?<searchQuery>[a-zA-Z0-9_ ]+) in (?<location>[a-zA-Z0-9_ ]+)$/i
const match = searchRegex.exec(message)
if (match === null) {
sendMessage(to, "Please enter the hospital name you want to search for and the location")
return
}
const { groups: { searchQuery, location } } = match
if (!Object.keys(locationKey).includes(location)) {
sendMessage(to, "Invalid location entered. Type *cities* to look at all the cities available")
return
}
try {
const data = await client.request(searchGraphQLQuery, {
location: locationKey[location],
query: searchQuery,
})
const { edges } = data.locality.hospitals
const hospitals = edges.map((item) => item.node)
if (edges.length === 0) {
sendMessage(to, "Sorry, there were no hospitals that matched your search 🙁")
return
}
const formattedMessage = getFormattedHospitals(hospitals)
sendMessage(to, formattedMessage)
} catch (error) {
sendMessage(to, "Sorry, there were no hospitals that matched your search 🙁")
}
} Der Befehl Wegbeschreibung abrufen
Der letzte noch zu implementierende Befehl ist der Befehl get directions. Das Format des Befehls ist get directions to <hospital-id>.
Erstellen Sie zunächst die Abfrage, mit der Sie die Informationen über das Krankenhaus erhalten, die erforderlich sind, um den Standort des Krankenhauses an den Benutzer zu senden:
// src/queries.js
const directionsGraphQLQuery = gql`
query($id: ID!) {
hospital(id: $id) {
id
longitude
latitude
name
address
}
}
`
module.exports = {
...
directionsGraphQLQuery,
}Erstellen wir nun eine handleDirections Funktion, die die vom Benutzer angeforderten Wegbeschreibungen an das Krankenhaus sendet. Wenn der Nutzer WhatsApp verwendet, senden wir eine Nachricht des Typs location die den Namen und die Adresse des Krankenhauses enthält. Da es keine Nachricht des Typs location gibt, senden wir eine Nachricht des Typs text die einen Google Maps-Link zum Standort des Krankenhauses enthält:
// src/app.js
const handleDirections = async (message, to) => {
const directionsRegex = /^get directions to (?<hospitalId>\d+)$/i
const match = directionsRegex.exec(message)
if (match === null) {
sendMessage(to, "Please enter a valid Hospital ID")
return
}
const hospitalId = getEncodedString(parseInt(match.groups.hospitalId))
try {
const { hospital } = await client.request(directionsGraphQLQuery, {
id: hospitalId,
})
if (to.type === "whatsapp") {
sendMessage(
to,
{
type: "location",
location: {
longitude: hospital.longitude,
latitude: hospital.latitude,
name: hospital.name,
address: hospital.address,
},
},
"custom"
)
} else {
const link = `https://maps.google.com/maps?q=${hospital.latitude},${hospital.longitude}`
const message = `${link}\n*${hospital.name}*\n${hospital.address}\n`
sendMessage(to, message)
}
} catch (error) {
sendMessage(to, "Please enter a valid Hospital ID")
}
}Und das war's, wir sind fertig! Sie können alle Befehle selbst in der Sandbox ausprobieren und es sollte ungefähr so aussehen wie unten!

Was kommt als Nächstes?
Momentan ist unser Webhook für das gesamte Internet offen. Wir brauchen eine Möglichkeit, um sicherzustellen, dass nur die Vonage Messages API auf den Endpunkt zugreifen kann. Lesen Sie mehr über Zugriffsbeschränkung mit JWT-Tokens.
Wenn Sie sich mit maschinellem Lernen auskennen, können Sie Natural Language Processing einsetzen, um den Bot natürlicher zu machen natürlicher zu machen.
Die Verwendung der Krankenhaus-ID im Befehl "Wegbeschreibung abrufen" ist nicht die beste Benutzererfahrung. Versuchen Sie stattdessen, einen Befehl zu implementieren, bei dem der Benutzer den Namen des Krankenhauses eingibt, zu dem er eine Wegbeschreibung erhalten möchte. Wenn es mehrere Krankenhäuser mit einem ähnlichen Namen gibt, geben Sie eine Liste von Krankenhäusern mit ihren IDs zurück und bitten Sie den Benutzer, die ID des Krankenhauses einzugeben, zu dem er eine Wegbeschreibung erhalten möchte.
Der endgültige Code für das Tutorial ist zu finden auf GitHub.
