diff --git a/.vscode/settings.json b/.vscode/settings.json index ffa60fd..65e097a 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,6 +8,7 @@ "adapter", "ci", "starters", - "conflict" + "conflict", + "contexts" ] } diff --git a/packages/contexts/package.json b/packages/contexts/package.json index 9d27195..29c2dcd 100644 --- a/packages/contexts/package.json +++ b/packages/contexts/package.json @@ -8,7 +8,8 @@ ], "exports": { "./mock": "./lib/mock/index.cjs", - "./dialogflow": "./lib/dialogflow/index.cjs" + "./dialogflow": "./lib/dialogflow/index.cjs", + "./dialogflowcx": "./lib/dialogflow-cx/index.cjs" }, "dependencies": { "@bot-whatsapp/bot": "*" diff --git a/packages/contexts/rollup-contexts.config.js b/packages/contexts/rollup-contexts.config.js index 59a7624..07c3d67 100644 --- a/packages/contexts/rollup-contexts.config.js +++ b/packages/contexts/rollup-contexts.config.js @@ -21,4 +21,13 @@ module.exports = [ }, plugins: [commonjs()], }, + { + input: join(__dirname, 'src', 'dialogflow-cx', 'index.js'), + output: { + banner: banner['banner.output'].join(''), + file: join(__dirname, 'lib', 'dialogflow-cx', 'index.cjs'), + format: 'cjs', + }, + plugins: [commonjs()], + }, ] diff --git a/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js new file mode 100644 index 0000000..e851ca4 --- /dev/null +++ b/packages/contexts/src/dialogflow-cx/dialogflow-cx.class.js @@ -0,0 +1,112 @@ +const { CoreClass } = require('@bot-whatsapp/bot') +const { SessionsClient } = require('@google-cloud/dialogflow-cx').v3beta1 +const { existsSync, readFileSync } = require('fs') +const { join } = require('path') + +/** + * Necesita extender de core.class + * handleMsg(messageInComming) // const { body, from } = messageInComming + */ + +const GOOGLE_ACCOUNT_PATH = join(process.cwd(), 'google-key.json') + +class DialogFlowCXContext extends CoreClass { + // Opciones del usuario + optionsDX = { + language: 'es', + location: '', + agentId: '', + } + projectId = null + configuration = null + sessionClient = null + + constructor(_database, _provider, _optionsDX = {}) { + super(null, _database, _provider) + this.optionsDX = { ...this.optionsDX, ..._optionsDX } + this.init() + } + + /** + * Verificar conexión con servicio de DialogFlow + */ + init = () => { + if (!existsSync(GOOGLE_ACCOUNT_PATH)) { + console.log(`[ERROR]: No se encontro ${GOOGLE_ACCOUNT_PATH}`) + /** + * Emitir evento de error para que se mueste por consola dicinedo que no tiene el json + * */ + } + + if (!this.optionsDX.location.length) + throw new Error('LOCATION_NO_ENCONTRADO') + if (!this.optionsDX.agentId.length) + throw new Error('AGENTID_NO_ENCONTRADO') + + const rawJson = readFileSync(GOOGLE_ACCOUNT_PATH, 'utf-8') + const { project_id, private_key, client_email } = JSON.parse(rawJson) + + this.projectId = project_id + + this.sessionClient = new SessionsClient({ + credentials: { private_key, client_email }, + apiEndpoint: `${this.optionsDX.location}-dialogflow.googleapis.com`, + }) + } + + /** + * GLOSSARY.md + * @param {*} messageCtxInComming + * @returns + */ + handleMsg = async (messageCtxInComming) => { + const languageCode = this.optionsDX.language + const { from, body } = messageCtxInComming + + /** + * 📄 Creamos session de contexto basado en el numero de la persona + * para evitar este problema. + * https://github.com/codigoencasa/bot-whatsapp/pull/140 + */ + + const session = this.sessionClient.projectLocationAgentSessionPath( + this.projectId, + this.optionsDX.location, + this.optionsDX.agentId, + from + ) + + const reqDialog = { + session, + queryInput: { + text: { + text: body, + }, + languageCode, + }, + } + + const [single] = (await this.sessionClient.detectIntent(reqDialog)) || [ + null, + ] + + const listMessages = single.queryResult.responseMessages.map((res) => { + if (res.message == 'text') { + return { answer: res.text.text[0] } + } + + if (res.message == 'payload') { + const { values } = res.payload.fields.buttons.listValue + const buttonsArray = values.map((values) => { + const { stringValue } = values.structValue.fields.body + return { body: stringValue } + }) + return { buttons: buttonsArray } + } + }) + + this.sendFlow(listMessages, from) + } +} + +module.exports = DialogFlowCXContext diff --git a/packages/contexts/src/dialogflow-cx/index.js b/packages/contexts/src/dialogflow-cx/index.js new file mode 100644 index 0000000..2a561c4 --- /dev/null +++ b/packages/contexts/src/dialogflow-cx/index.js @@ -0,0 +1,14 @@ +const DialogCXFlowClass = require('./dialogflow-cx.class') + +/** + * Crear instancia de clase Bot + * @param {*} args + * @returns + */ +const createBotDialog = async ({ database, provider }, _options) => + new DialogCXFlowClass(database, provider, _options) + +module.exports = { + createBotDialog, + DialogCXFlowClass, +}