https://d226lax1qjow5r.cloudfront.net/blog/blogposts/build-a-whatsapp-and-messenger-graphql-bot-to-find-hospital-beds/whatsapp_messenger_graphql_1200x600.png

Construire un bot WhatsApp et Messenger GraphQL pour trouver des lits d'hôpitaux

Publié le March 25, 2021

Temps de lecture : 14 minutes

COVID a eu un impact sur chacun d'entre nous, mais sur certains plus que sur d'autres. L'un des principaux problèmes auxquels les gens ont été confrontés et continuent de l'être est la pénurie de lits d'hôpitaux. Il y a quelques mois, j'ai créé une API GraphQL qui renvoie la disponibilité des lits dans plusieurs villes et districts en Inde. Les données sont extraites des sites web officiels et normalisées dans un format uniforme qui est ensuite exposé sous la forme d'une API GraphQL.

Attention, les données ne sont disponibles que pour certaines villes de l'Inde.

Vous pouvez également explorer l'API dans le Terrain de jeu GraphQL.

En utilisant l'API Bedav et l'API Messages de Vonage, nous allons construire un chatbot qui fonctionne avec WhatsApp et Facebook Messenger en utilisant JavaScript. La fonction de ce chatbot est d'aider les utilisateurs à rechercher des hôpitaux dans une ville, à trouver un hôpital avec des lits disponibles et à fournir des informations supplémentaires sur l'hôpital, telles que son numéro de téléphone et son adresse. Nous créerons également une commande permettant à l'utilisateur d'obtenir des indications pour se rendre à l'hôpital.

Conditions préalables

  1. Node et npm

  2. Un Account Vonage

    Vonage API Account

    To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Configuration du projet

Même si le code pour cela peut être trouvé dans le dépôt GitHub de le dépôt GitHubil est recommandé de suivre ce tutoriel et de n'utiliser le dépôt qu'à titre de référence.

Initialiser NPM et installer les dépendances

Commencez par créer un nouveau dossier, initialisez npm et créez un dossier src dans ce dossier :

mkdir chatbot && cd chatbot mkdir src npm init -y

Nous allons créer nos webhooks et notre serveur en utilisant Express. Axios sera utilisé pour envoyer des requêtes à l'API Messages et graphql-request sera utilisé pour envoyer des requêtes à l'API Bedav GraphQL. Vous pouvez les installer avec d'autres utilitaires en lançant la commande suivante :

npm i express axios graphql-request js-base64 outdent dotenv

Enfin, nous installons Nodemon en tant que dépendance dev afin de ne pas avoir à redémarrer notre serveur node à chaque fois que nous faisons un changement :

npm i -D nodemon

Ajoutons également un script à notre package.json pour démarrer notre serveur de développement Nodemon :

// package.json

{
  "scripts": {
    "dev": "nodemon src/app.js"
  }
}

Créer les Webhooks

Avant d'entrer dans le code, qu'est-ce qu'un webhook ? Les webhooks sont essentiellement une URL qui est appelée chaque fois qu'une certaine action ou un certain événement est réalisé. Les webhooks peuvent être considérés comme similaires aux callbacks, mais ils sont le plus souvent utilisés pour interagir entre deux applications distinctes et indépendantes. Dans notre cas, nous devons exposer deux webhooks : un qui se déclenche lorsque l'utilisateur envoie un message et un autre lorsqu'il y a une mise à jour de l'état d'un message provenant de l'API (par exemple, lorsque l'utilisateur lit un message que vous avez envoyé).

Tout d'abord, configurons Express dans src/app.jsoù se trouvent notre application principale Express et les fonctions principales chargées de gérer les commandes :

// src/app.js

const express = require("express")

const app = express()
app.use(express.json())

Ensuite, ajoutons deux points de terminaison, l'un pour le webhook de message et l'autre pour le webhook d'état :

// 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")
})

Installation et configuration de Ngrok

Ngrok vous permet de tester vos webhooks en les exposant à l'internet à l'aide d'une URL temporaire. Pour commencer avec ngrok, vous pouvez aller sur leur site et créer un Account. Une fois que vous avez fait cela et que vous vous êtes connecté, vous devriez voir les instructions pour installer et connecter votre compte sur leur tableau de bord.

Maintenant que ngrok est installé et configuré, démarrons notre serveur de développement en lançant npm run dev. Utilisons ngrok pour créer une URL publique pour notre serveur local en lançant ./ngrok http 3000. Cette commande indique à ngrok de créer un proxy HTTP vers le serveur tournant sur localhost:3000.

Configuration de l'Environnement de test des messages

Connectez-vous au tableau de bord de Vonage et rendez-vous dans la section bac à sable sous la rubrique Messages et répartition.

Vonage Dashboard Menu Bar with the Sandbox section highlighted

Pour créer le bac à sable WhatsApp, cliquez sur Ajouter à la sandbox dans la section WhatsApp. Le bac à sable de Vonage a besoin de vérifier votre identité et pour ce faire, vous pouvez suivre les étapes données dans le tableau de bord. Vous pouvez suivre des étapes similaires pour créer le bac à sable pour Facebook Messenger.

Vous avez maintenant activé avec succès le bac à sable de WhatsApp ! Mais attendez, nous n'avons pas encore terminé. Nous devons encore fournir à Vonage l'URL où nos webhooks sont présents. Si vous faites défiler la page Sandbox vers le bas, vous devriez voir la section Webhooks qui ressemble à ce qui suit :

Webhooks section on the Sandbox page of the Vonage Dashboard

Le premier est le inbound qui sera sur la route webhooks/inbounddonc définissez ce champ à https://<your-ngrok-https-url>/webhooks/inbound. De même, définissez l'URL du status à https://<your-ngrok-https-url>/webhooks/status. Nous avons maintenant terminé la mise en place de notre bac à sable et de notre environnement de test !

Note : Chaque fois que vous redémarrez ngrok, vous recevrez une nouvelle URL différente que vous devrez changer manuellement dans le tableau de bord de Vonage.

Renvoi d'un message à l'utilisateur

Nous aurons besoin d'une fonction d'aide qui sera utilisée pour renvoyer des messages à l'utilisateur.

Tout d'abord, nous devons configurer nos identifiants API Vonage afin de pouvoir utiliser l'API Messages. Ces informations d'identification seront stockées dans des variables d'environnement. Créez un fichier .env à la racine du dossier. Pour charger les variables d'environnement dans l'environnement du nœud, nous utiliserons le paquetage dotenv package. Ajoutez les champs comme indiqué ci-dessous :

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 Sandbox

Une fois que c'est fait, ajoutez le code suivant au début de app.js pour ajouter les variables d'environnement :

// src/app.js
require("dotenv").config()

Créez un nouveau fichier nommé utils.js dans le dossier src . Il contiendra nos fonctions utilitaires, telles que le formatage et l'envoi d'un message à l'utilisateur.

Nous allons faire une demande à l'API Messages REST pour envoyer un message. Dans le cas de l'Environnement de test de Messages, l'URL de l'API est la suivante https://messages-sandbox.nexmo.com/v0.1/messages. Nous utiliserons Axios pour envoyer les requêtes. Nous pouvons utiliser l'option auth pour ajouter nos identifiants d'API, comme indiqué ci-dessous :

// 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,
}

Le type de message est dynamique, car nous enverrons un message de type location lorsque l'utilisateur demandera des indications pour se rendre à l'hôpital. Sur WhatsApp, un message de type location joindra une vignette du lieu sur Google Maps ainsi que le nom et l'adresse fournis.

Créer les commandes

Nous pouvons maintenant créer nos commandes :

  1. help - Obtenir un menu de toutes les commandes que vous pouvez utiliser

  2. cities - Obtenir une liste de toutes les villes disponibles

  3. search <hospital-name> in <location> - Recherchez un hôpital dans un lieu particulier. Par exemple, search sakra in bangalore recherche les hôpitaux portant le nom de Sakra à Bangalore.

  4. get directions to <hospital-id> - Obtenir des indications pour se rendre dans un hôpital avec un identifiant particulier. Par exemple, get directions to 87 enverra l'emplacement de l'hôpital portant l'ID 87.

Le gestionnaire de messages entrants

Créons une fonction qui gère les requêtes adressées à l'application inbound à l'adresse /webhooks/inbound. Cette fonction analyse le message envoyé par l'utilisateur et le transmet au gestionnaire de la commande que l'utilisateur essaie d'utiliser. Elle renvoie le message approprié et renvoie un code d'état de 200.

Notez que le webhook doit répondre avec un code d'état 200, sinon l'API Messages continuera à envoyer une demande au webhook jusqu'à ce qu'il obtienne une réponse 200.

Nous utilisons des expressions régulières pour vérifier si l'utilisateur essaie d'utiliser la fonction search ou directions puis nous transmettons le message au gestionnaire approprié. Si le message est help, hi, ou hellole message d'aide est envoyé à l'utilisateur. Si le message est citiesla liste des villes disponibles est envoyée à l'utilisateur. Enfin, si le message ne correspond à aucune commande, un message invalide est envoyé à l'utilisateur.

// 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()
}

Modifions maintenant le gestionnaire du point de terminaison du webhook entrant pour utiliser la fonction handleInbound fonction.

// src/app.js
app.post("/webhooks/inbound", handleInbound)

Les commandes Help et Welcome

Lorsque l'utilisateur envoie son premier message à notre service, nous avons besoin d'un message d'accueil. Ce message doit contenir des informations sur ce que fait notre robot et sur les différentes commandes disponibles. Nous aurons également besoin d'un message d'aide qui sera envoyé lorsque l'utilisateur ne sait pas quoi faire et tape help. Ces messages peuvent être similaires.

L'API Bedav ne dispose d'informations sur les hôpitaux que dans certaines régions. Nous aurons également besoin d'un message pour donner une liste des régions où l'information est disponible.

Tel qu'il est mis en œuvre dans la fonction handleInbound le message d'aide est envoyé lorsque l'utilisateur tape hi, bonjourou aide et le message sur les villes disponibles est envoyé lorsque l'utilisateur tape villes.

Comme ces deux messages seront constants, nous pouvons créer un objet constant au niveau supérieur pour définir tous les messages fixes. Nous utilisons également outdent pour supprimer les espaces supplémentaires dans notre chaîne de caractères qui sont censés être des indentations dans notre code. Ajoutez le code à 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,
}

Configuration du client GraphQL

Pour simplifier l'interrogation de l'API GraphQL, nous utiliserons la bibliothèque graphql-request pour simplifier les requêtes à l'API GraphQL. Pour configurer le client GraphQL, nous créons une instance de GraphQLClient et fournissons l'URL de l'API GraphQL.

// app.js

const { GraphQLClient } = require("graphql-request")
const client = new GraphQLClient("https://bedav.org/graphql")

Créer des fonctions utilitaires

Comme indiqué dans la description du champ hospitalId dans la documentation de l'API, il s'agit d'une chaîne encodée en Base64 qui peut être décodée en Hospital:<hospitalId>hospitalId est un nombre entier unique à l'hôpital. Pour des raisons que vous verrez dans la section suivante, créons deux fonctions utilitaires : l'une pour obtenir le numéro d'identification de l'hôpital et l'autre pour encoder un nombre entier en une chaîne Base64 de la forme Hospital:<hospitalId>. Nous utiliserons la bibliothèque js-base64 que nous avons ajoutée à notre projet pour travailler avec les chaînes encodées. base64 encodées.

// 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,
}

La commande de recherche

Fonctions utilitaires pour formater les chaînes de caractères

Créons deux autres fonctions utilitaires pour formater les données hospitalières, l'une pour formater un hôpital individuel et l'autre qui utilise cette fonction pour formater un groupe d'hôpitaux.

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

Tous les hôpitaux ne disposent pas de lits dans les unités de soins intensifs, les unités de soins intensifs et les unités de soins généraux, ni d'oxygène et de ventilateurs. Si l'hôpital ne dispose pas de l'un de ces éléments, nous pouvons omettre cette information dans le message. L'hôpital ne dispose pas d'un certain type de lits, d'oxygène ou de ventilateurs si le total disponible est égal à zéro ou si la valeur du champ disponible est nulle.

Nous imprimons également l'ID de l'hôpital car l'utilisateur doit fournir l'ID de l'hôpital dans la commande get directions. Nous indiquons également à l'utilisateur le pourcentage de lits occupés entre parenthèses.

Il reste une ligne vide si un lit, un ventilateur ou de l'oxygène n'est pas disponible. Pour remédier à ce problème, nous créons une autre fonction d'aide pour supprimer ces lignes vides.

Pour vérifier la présence de lignes vides, nous utilisons une courte expression régulière qui vérifie si la ligne contient plus d'un seul caractère espace :

// 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")
}

Ensuite, créez la fonction de formatage d'une liste d'hôpitaux en parcourant tous les hôpitaux, en obtenant la chaîne formatée pour cet hôpital et en ajoutant une ligne vide entre chaque hôpital :

// 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,
}

Le gestionnaire de commandes

Toutes les requêtes GraphQL seront stockées dans le fichier queries.js dans le dossier src dans le dossier

Nous utilisons la requête GraphQL ci-dessous pour rechercher un hôpital dans une certaine localité et récupérer les données nécessaires. L'argument name du champ locality est utilisé pour indiquer à l'API les données de l'emplacement que nous recherchons. L'argument first du champ hospitals précise le nombre d'hôpitaux que l'API doit renvoyer, et l'argument searchQuery fournit la requête de recherche.

// 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,
}
`

Notez que nous n'avons pas besoin d'envelopper notre requête GraphQL avec la balise gql . Mais, avec les bonnes extensions et les bons outils, nous pouvons obtenir une mise en évidence de la syntaxe et une vérification du type.

Ensuite, nous devons faire correspondre les noms des lieux à l'argument name du champ locality qui est de la forme <city/district_name>-<state_name>. Le mappage de l'argument city/district à la localité name peut être converti en l'objet ci-dessous en JavaScript :

// 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,
}

Le texte que l'utilisateur saisit pour rechercher un hôpital dans une certaine localité aura le format suivant search <search-query> in <location>. Créons la fonction handleSearch qui récupère la requête de recherche et le lieu dans le message de l'utilisateur. Cette fonction est chargée d'exécuter la requête de recherche et de renvoyer la réponse appropriée à l'utilisateur :

// 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 🙁")
  }
}

La commande Get Directions

La dernière commande qu'il reste à mettre en œuvre est la commande "get directions". Le format de la commande est le suivant get directions to <hospital-id>.

Tout d'abord, créez la requête qui obtiendra les informations de l'hôpital nécessaires pour envoyer l'emplacement de l'hôpital à l'utilisateur :

// src/queries.js

const directionsGraphQLQuery = gql`
  query($id: ID!) {
    hospital(id: $id) {
      id
      longitude
      latitude
      name
      address
    }
  }
`

module.exports = {
  ...
  directionsGraphQLQuery,
}

Créons maintenant une fonction handleDirections qui enverra l'itinéraire vers l'hôpital demandé par l'utilisateur. Si l'utilisateur utilise WhatsApp, nous envoyons un message de type location qui contient le nom et l'adresse de l'hôpital. Comme il n'y a pas de message de type location sur Messenger, nous envoyons un message de type text qui contient un lien Google Maps vers l'emplacement de l'hôpital :

// 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")
  }
}

Et voilà, nous avons terminé ! Vous pouvez essayer toutes les commandes vous-même dans le bac à sable et cela devrait ressembler à ce qui suit !

Final Example

Prochaines étapes

  • Actuellement, notre webhook est ouvert à l'ensemble de l'Internet. Nous avons besoin d'un moyen pour nous assurer que seule l'API Messages de Vonage peut accéder au point de terminaison. En savoir plus sur limiter l'accès à l'aide de jetons JWT.

  • Si vous vous intéressez à l'apprentissage automatique, vous pouvez utiliser le traitement du langage naturel pour rendre le robot plus naturel. naturel plus naturel.

  • L'utilisation de l'identifiant de l'hôpital dans la commande d'itinéraire n'est pas la meilleure solution pour l'utilisateur. Essayez plutôt de mettre en place une commande dans laquelle l'utilisateur saisit le nom de l'hôpital pour lequel il souhaite obtenir un itinéraire. S'il existe plusieurs hôpitaux portant un nom similaire, renvoyez une liste d'hôpitaux avec leurs identifiants et demandez à l'utilisateur d'entrer l'identifiant de l'hôpital pour lequel il souhaite obtenir un itinéraire.

Le code final du tutoriel se trouve sur GitHub.

Partager:

https://a.storyblok.com/f/270183/400x514/4b6d6f78ee/shreyas-sreenivas.png
Shreyas Sreenivas

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.