diff --git a/.env-example b/.env-example new file mode 100644 index 0000000..b003e1b --- /dev/null +++ b/.env-example @@ -0,0 +1,4 @@ +TWILIO_ACCOUNT_SID= +TWILIO_AUTH_TOKEN= +GOOGLE_APPLICATION_CREDENTIALS=absolute path to google service account.json +PORT=3000 \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..c17ff25 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.nyc_output/ +coverage/ +node_modules/ +npm-debug.log +package-lock.json +test/*.log +gcp-credentials.json +.env \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..aceaa63 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Twilio Whatsapp dialogflow \ No newline at end of file diff --git a/index.js b/index.js new file mode 100644 index 0000000..975e0f6 --- /dev/null +++ b/index.js @@ -0,0 +1,104 @@ +require('dotenv').config(); + +const express = require('express'); +const app = express(); +const PORT = process.env.port || 3000; + +const twilioClient = require('twilio')( + process.env.TWILIO_ACCOUNT_SID, + process.env.TWILIO_AUTH_TOKEN, +); + +const dialogflow = require('@google-cloud/dialogflow'); +const sessionClient = new dialogflow.SessionsClient(); + +// twilio sends application/x-www-form-urlencoded +app.use(express.urlencoded({ extended: true })) + +app.use(express.json()); + +app.post('/whatsapp', async function(req, res) { + + const from = req.body.From; + const to = req.body.To; + const body = req.body.Body; + + // session for current user + const projectId = await sessionClient.getProjectId(); + const sessionPath = sessionClient.projectAgentSessionPath(projectId, from); + + // query dialogflow + const response = await sessionClient.detectIntent({ + session: sessionPath, + queryInput: { + text: { + text: body, + languageCode: 'en-US', + } + } + }); + + + // handle emi due date action + if(response[0].queryResult.action == 'emi.due-date') { + let dueDate = new Date(); + dueDate.setTime(dueDate.getTime() + 5*24*60*60*1000); + + let dueAmount = "$200"; + + await twilioClient.messages.create({ + from: to, + to: from, + body: `Your next emi of ${dueAmount} is on ${dueDate.toDateString()}.` + }); + + res.status(200).end(); + return + } + + // relay message sent by dialogflow directly to user + // message can be in two formats + // 1) Normal String response + // 2) Json Object with url and text properies + // url: publically accessible url of image + // text: additional text + const messages = response[0].queryResult.fulfillmentMessages; + for (const message of messages) { + + // normal text message + if(message.text) { + await twilioClient.messages.create({ + from: to, + to: from, + body: message.text.text[0], + }); + } + + // response payload + if(message.payload) { + let url = ''; + let text = ''; + + if(message.payload.fields.media_url) { + url = message.payload.fields.media_url.stringValue; + } + + if(messages.payload.fields.text) { + text = message.payload.fields.text.stringValue + } + + await twilioClient.messages.create({ + from: to, + to: from, + body: text, + mediaUrl: url, + }); + } + } + + res.status(200).end(); +}); + +app.listen(PORT, () => { + console.log(`Listening on ${PORT}`); +}); \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..6d5c6e2 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "twilio-whatsapp", + "version": "1.0.0", + "description": "integrate twilio with whatsapp", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "@google-cloud/dialogflow": "^3.3.0", + "dotenv": "^8.2.0", + "express": "^4.17.1", + "twilio": "^3.53.0" + } +}