
Partager:
Ancien Developer Advocate pour Vonage, où son rôle était de soutenir la communauté technologique locale à Londres. Il est un organisateur d'événements expérimenté, un joueur de jeux de société et le père d'un adorable petit chien appelé Moo. Il est également l'organisateur principal de You Got This - un réseau d'événements sur les compétences de base nécessaires pour une vie professionnelle heureuse et saine.
Créer une ligne d'incident de code de conduite avec Node.js
Temps de lecture : 6 minutes
Disposer d'un code de conduite en tant qu'organisateur communautaire n'est qu'une partie de l'histoire - il est également vital de disposer de moyens bien pensés pour signaler les mauvais comportements et y répondre. Lors des événements que j'ai organisés par le passé, un numéro de téléphone a été mis à la disposition des participants : ils peuvent appeler ou envoyer un SMS et le numéro est transmis à plusieurs organisateurs qui ont la responsabilité d'être disponibles pour traiter tout problème.
Aujourd'hui, je vous montrerai comment créer votre propre système avec le logiciel Vonage Voice et Messages avec un simple tableau de bord pour télécharger les enregistrements d'appels et enregistrer les messages entrants.
Vous trouverez le code du projet final à l'adresse suivante https://github.com/nexmo-community/node-code-of-conduct-conference-call
Conditions préalables
Node.js installé sur votre machine
node-clique vous pouvez installer en exécutantnpm install nexmo-cli@beta -g
Créez un nouveau répertoire et ouvrez-le dans un terminal. Exécutez npm init -y pour créer un fichier package.json et installer les dépendances avec npm install express body-parser nunjucks uuid nedb-promises nexmo@beta.
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.
This tutorial also uses a virtual phone number. To purchase one, go to Numbers > Buy Numbers and search for one that meets your needs.
Mise en place des dépendances
Créez un fichier index.js et mettre en place les dépendances :
index.js
const uuid = require('uuid')
const app = require('express')()
const bodyParser = require('body-parser')
const nedb = require('nedb-promises')
const Nexmo = require('nexmo')
const nunjucks = require('nunjucks')
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({ extended: false }))
// Future code goes here
app.listen(3000)Une fois que vous avez fait cela, exécutez npx ngrok http 3000 dans un nouveau terminal, et notez l'URL temporaire de ngrok. Celle-ci est utilisée pour rendre localhost:3000 sur le web public.
Acheter un numéro virtuel et configurer le client Nexmo
Ouvrez un autre terminal dans le répertoire de votre projet et créez une nouvelle application avec l'interface de ligne de commande (CLI) :
nexmo app:create
-> Select Capabilities: voice, messages
-> Use the default HTTP methods? Y
-> Voice Answer URL: https://NGROK_URL/answer
-> Voice Event URL: https://NGROK_URL/event
-> Messages Inbound URL: https://NGROK_URL/inbound
-> Messages Status URL: https://NGROK_URL/event
-> Private Key path: private.key
Prenez note de l'identifiant de l'Application affiché dans votre terminal, puis recherchez un numéro (vous pouvez remplacer GB par l'indicatif de votre pays) :
nexmo number:search GB --sms --voiceCopiez l'un des numéros dans votre presse-papiers, achetez-le et associez-le à votre application :
nexmo number:buy NUMBER
nexmo link:app NUMBER APP_ID
nexmo numbers:update NUMBER --mo_http_url https://NGROK_URL/smsEn index.js, initialiser le client Nexmo :
const nexmo = new Nexmo({
apiKey: 'API_KEY',
apiSecret: 'API_SECRET',
applicationId: 'APPLICATION_ID',
privateKey: './private.key'
}) Répondre à un appel entrant par la parole
Créer le GET /answer et renvoie un objet de contrôle d'appel Nexmo (NCCO) avec une seule talk action :
app.get('/answer', async (req, res) => {
res.json([
{ action: 'talk', voiceName: 'Amy', text: 'This is the Code of Conduct Incident Response Line' }
])
})
app.post('/event', (req, res) => {
res.status(200).end()
})
Le point de terminaison POST /event Des données d'appel lui seront envoyées ultérieurement et, pour l'instant, il doit se contenter de répondre par un HTTP 200 OK statut.
Point de contrôle : Démarrez votre serveur en exécutant node index.js et appelez le numéro que vous avez acheté avec la CLI - le message devrait être lu à haute voix, puis l'appel devrait raccrocher. En cas de problème, vous pouvez toujours vérifier les paramètres du numéro et de l'application dans le tableau de bord.
Répondre à un appel entrant en composant le numéro Organisateurs
Au lieu de simplement lire le message, ajoutez l'appelant à une toute nouvelle conversation. Nous pouvons contrôler les conversations avec du code, y compris l'ajout de plusieurs participants à l'appel - il vous suffit de connaître le nom de la conversation pour le faire. Remplacez le contenu du point de terminaison /answer par :
const conferenceId = uuid.v4()
res.json([
{ action: 'talk', voiceName: 'Amy', text: 'This is the Code of Conduct Incident Response Line' },
{ action: 'conversation', name: conferenceId, record: true }
])Ce code génère un nouvel identifiant unique et ajoute ensuite l'appelant à une conversation qui utilise un nom comme identifiant (dans ce contexte, les conversations sont des appels avec un ou plusieurs participants). Cependant, les conférences téléphoniques à une personne sont tristes. Avant le début de la conférence, il faut appeler chaque organisateur et l'ajouter à la conversation. res.json()appeler chaque organisateur et l'ajouter à la conférence téléphonique :
for(let organizerNumber of ['NUMBER ONE', 'NUMBER TWO']) {
nexmo.calls.create({
to: [{ type: 'phone', number: organizerNumber }],
from: { type: 'phone', number: 'NEXMO NUMBER' },
ncco: [
{ action: 'conversation', name: conferenceId }
]
})
}Chaque numéro doit être au format format E.164et vous devez remplacer NEXMO NUMBER par le numéro lié à votre application. Lors des tests, assurez-vous que les numéros du tableau ne sont pas les mêmes que ceux que vous utiliserez pour appeler.
Point de contrôle : Redémarrez votre serveur et appelez votre numéro Numbers. L'application devrait faire sonner tous les numéros fournis dans le tableau de la boucle for().
Enregistrer l'appel
Lors de l'ajout de l'appelant à la conférence téléphonique, record: true a été passé comme option et, par conséquent, l'ensemble de l'appel a été enregistré. Une fois l'appel terminé, le point de terminaison POST /event reçoit une charge utile contenant l'identifiant de la conversation et une URL d'enregistrement.
Avant les points d'extrémité existants, créer une nouvelle base de données nedb :
const recordingsDb = nedb.create({ filename: 'data/recordings.db', autoload: true })Une fois que vous aurez redémarré votre serveur, un fichier sera créé à l'intérieur d'un répertoire data . Mettez à jour le point de terminaison de l'événement pour qu'il ressemble à ceci :
app.post('/event', async (req, res) => {
if(req.body.recording_url) {
await recordingsDb.insert(req.body)
}
res.status(200).end()
})
Point de contrôle : Redémarrez votre serveur et appelez votre numéro Numbers. Une fois que tous les participants ont raccroché, vous devriez voir une nouvelle entrée dans le fichier data/recordings.db une nouvelle entrée.
Créer un tableau de bord des enregistrements
Maintenant que les données d'enregistrement sont sauvegardées dans une base de données, il est temps de créer un tableau de bord. Configurez nunjucks avant le premier point de terminaison :
nunjucks.configure('views', { express: app })Cela permet à nunjucks de rendre n'importe quel fichier dans le répertoire views et les liens vers l'application express stockée dans la variable app . Créer un views et un fichier index.html à l'intérieur de celui-ci :
<h1>Recordings</h1>
{% for recording in recordings %}
<p>
<a href="/details/{{recording.conversation_uuid}}">{{recording.start_time}}</a>
</p>
{% endfor %}Créez également un fichier details.html dans le répertoire views dans le répertoire
<ul>
<li>{{caller}}</li>
<li>{{recording.timestamp}}</li>
<li><a href="/details/{{recording.conversation_uuid}}/download">Download</a></li>
</ul>Trois points d'extrémité sont nécessaires en index.js pour que ces vues fonctionnent. Le premier charge tous les enregistrements de la base de données et affiche la page d'index :
app.get('/', async (req, res) => {
const recordings = await recordingsDb.find().sort({ timestamp: -1 })
res.render('index.html', { recordings })
})
La page se présente désormais comme suit, avec les derniers enregistrements en premier :
Web page showing one recording timestamp with a blue underline
Le point de terminaison suivant charge la page de détails après avoir obtenu des détails de l'API Conversations, notamment le numéro de téléphone de l'appelant :
app.get('/details/:conversation', (req, res) => {
nexmo.conversations.get(req.params.conversation, async (error, result) => {
const caller = result.members.find(member => member.channel.from != process.env.NEXMO_NUMBER)
const number = caller.channel.from.number
const recording = await recordingsDb.findOne({ conversation_uuid: req.params.conversation })
res.render('detail.html', { caller: number, recording })
})
})
Enfin, un point d'accès qui récupère le fichier audio brut de l'API et l'envoie sous la forme d'un fichier MP3 téléchargeable :
app.get('/details/:conversation/download', async (req, res) => {
const recording = await recordingsDb.findOne({ conversation_uuid: req.params.conversation })
nexmo.files.get(recording.recording_url, (error, result) => {
res.writeHead(200, {
'Content-Disposition': 'attachment; filename="recording.mp3"',
'Content-Type': 'audio/mpeg',
})
res.end(Buffer.from(result, 'base64'))
})
})
A page showing a phone number, timestamp, and download link
Point de contrôle : Redémarrez votre serveur et appelez votre numéro Numbers. Une fois l'appel terminé, vous devriez voir la nouvelle entrée sur le tableau de bord. Allez à la page des détails et téléchargez-la.
Accepter et enregistrer le SMS
Comme il s'agit d'un numéro de téléphone, certaines personnes utilisant ce service peuvent également lui envoyer un SMS. Selon un schéma similaire, ces messages seront stockés et affichés sur le tableau de bord. Sous la création de la base de données existante, ajoutez-en une nouvelle pour les messages :
const messagesDb = nedb.create({ filename: 'data/messages.db', autoload: true })Enregistrer les nouveaux messages au fur et à mesure de leur réception en créant un point de terminaison que nous avons précédemment pointé lors de la mise en place de notre numéro virtuel :
app.post('/sms', async (req, res) => {
await messagesDb.insert(req.body)
res.status(200).end()
})
Mettre à jour le point de terminaison du tableau de bord pour qu'il récupère et affiche également les messages :
app.get('/', async (req, res) => {
const recordings = await recordingsDb.find().sort({ timestamp: -1 })
const messages = await messagesDb.find().sort({ 'message-timestamp': -1 })
res.render('index.html', { recordings, messages })
})
Ajouter cette section au bas de la page index.html:
{% for message in messages %}
<p>{{message.msisdn}} ({{message['message-timestamp']}}): {{message.text}}</p>
{% endfor %}
Web page showing both recordings and two example messages
Point de contrôle : Redémarrez votre serveur et envoyez un SMS à votre numéro de Numbers. Vous devriez le voir apparaître sur votre tableau de bord une fois que vous l'aurez actualisé.
Transférer un SMS et envoyer une réponse
Enfin, mettez à jour le point de terminaison SMS pour qu'il transmette le message aux organisateurs et réponde à l'expéditeur :
app.post('/sms', async (req, res) => {
await messagesDb.insert(req.body)
for(let organizerNumber of ['NUMBER ONE', 'NUMBER TWO']) {
nexmo.channel.send(
{ type: 'sms', number: organizerNumber },
{ type: 'sms', number: 'NEXMO NUMBER' },
{ content: { type: 'text', text: `From ${req.body.msisdn}\n\n${req.body.text}` } }
)
}
nexmo.channel.send(
{ type: 'sms', number: req.body.msisdn },
{ type: 'sms', number: 'NEXMO NUMBER' },
{ content: { type: 'text', text: 'Thank you for sending us a message. Organizers have been made aware and may be in touch for more information.' } }
)
res.status(200).end()
})
Point de contrôle : Redémarrez votre serveur et envoyez un SMS à votre numéro Numbers. Vous devriez recevoir une réponse et tous les organisateurs listés devraient également recevoir le message.
Prochaines étapes
Félicitations ! Vous disposez désormais d'une ligne fonctionnelle de réponse aux incidents liés au code de conduite qui fonctionne à la fois pour les appels téléphoniques et les messages SMS. Si vous disposez de plus de temps, vous pouvez explorer les possibilités suivantes :
Mise en œuvre de la gestion des erreurs
En utilisant notre nouveau système de reconnaissance vocale pour transcrire les appels
Vous trouverez le code du projet final à l'adresse suivante https://github.com/nexmo-community/node-code-of-conduct-conference-call
Comme toujours, si vous avez besoin d'aide, n'hésitez pas à nous contacter dans le Slack de la communauté des développeurs de Vonage. Communauté des développeurs de Vonage Slack. Nous espérons vous y voir.
Partager:
Ancien Developer Advocate pour Vonage, où son rôle était de soutenir la communauté technologique locale à Londres. Il est un organisateur d'événements expérimenté, un joueur de jeux de société et le père d'un adorable petit chien appelé Moo. Il est également l'organisateur principal de You Got This - un réseau d'événements sur les compétences de base nécessaires pour une vie professionnelle heureuse et saine.
