fix: check commits and changes

This commit is contained in:
2022-12-27 02:16:50 -06:00
parent b7d89411b3
commit 629b13de23
8 changed files with 4461 additions and 190 deletions

View File

@@ -1,6 +1,7 @@
const dialogflow = require('@google-cloud/dialogflow');
const fs = require('fs')
const { nanoid } = require('nanoid')
const {struct} = require('pb-util');
/**
* Debes de tener tu archivo con el nombre "chatbot-account.json" en la raíz del proyecto
*/
@@ -30,9 +31,10 @@ const checkFileCredentials = () => {
// Detect intent method
const detectIntent = async (queryText) => {
const detectIntent = async (queryText, waPhoneNumber) => {
let media = null;
const sessionId = KEEP_DIALOG_FLOW ? 1 : nanoid();
let actions = null;
const sessionId = KEEP_DIALOG_FLOW ? 1 : waPhoneNumber;
const sessionPath = sessionClient.projectAgentSessionPath(PROJECID, sessionId);
const languageCode = process.env.LANGUAGE
const request = {
@@ -54,24 +56,26 @@ const detectIntent = async (queryText) => {
// console.log(singleResponse)
if (parsePayload && parsePayload.payload) {
const { fields } = parsePayload.payload
actions = struct.decode(fields.actions.structValue) || null;
media = fields.media.stringValue || null
}
const customPayload = parsePayload['payload']
const customPayload = parsePayload ? parsePayload['payload'] : null
const parseData = {
replyMessage: queryResult.fulfillmentText,
media,
actions,
trigger: null
}
return parseData
}
const getDataIa = (message = '', cb = () => { }) => {
detectIntent(message).then((res) => {
const getDataIa = (message = '', sessionId = '', cb = () => { }) => {
detectIntent(message, sessionId).then((res) => {
cb(res)
})
}
checkFileCredentials();
module.exports = { getDataIa }
module.exports = { getDataIa }

103
adapter/gdrive,.js Normal file
View File

@@ -0,0 +1,103 @@
require('dotenv').config({ path: `${__dirname}/../.env` });
const { google } = require('googleapis');
const path = require('path');
const fs = require('fs');
//const clientEmail = require(`${__dirname}/../chatbot-account.json`);
/**
* La funcion 'generatePublicUrl' genera un error muy menor al enviar el 'requestBody'
* siempre y cuando necesites que el acceso sea restringido y solo ciertos usuarios puedan acceder.
* Esto se logra con la combinacion requerida: 'reader', 'user' y 'emailAddress':
* requestBody: {
* role: 'reader',
* type: 'user',
* emailAddress: usuario@gmail.com,
* },
* Segun la documentacion https://developers.google.com/drive/api/v3/reference/permissions/create#request-body,
* los datos se envian correctamente, pero la respuesta del API regresa este error:
* Bad Request. User message: "You cannot share this item because it has been flagged as inappropriate."
* Al parecer, es un error conocido en stackoverflow.com entre varios usuarios del API.
*/
if (process.env.DATABASE === 'dialogflow') {
/**
* Debes de tener tu archivo con el nombre "chatbot-account.json" en la raíz del proyecto
*/
const KEYFILEPATH = path.join(`${__dirname}/../chatbot-account.json`);
const SCOPES = ['https://www.googleapis.com/auth/drive'];
const auth = new google.auth.GoogleAuth({
keyFile: KEYFILEPATH,
scopes: SCOPES,
});
const drive = google.drive({
version: 'v3',
auth,
});
const uploadSingleFile = async (fileName, filePath) => {
const folderId = process.env.GDRIVE_FOLDER_ID;
const { data: { id, name } = {} } = await drive.files.create({
resource: {
name: fileName,
parents: [folderId],
},
media: {
mimeType: 'image/jpg',
body: fs.createReadStream(filePath),
},
fields: 'id,name',
});
generatePublicUrl(id).then(() => {
console.log(`Se generó enlace https://drive.google.com/open?id=${id} para el archivo ${name}`);
});
return `https://drive.google.com/open?id=${id}`
};
const scanFolderForFiles = async (folderPath) => {
const folder = await fs.promises.opendir(folderPath);
for await (const dirent of folder) {
if (dirent.isFile() && dirent.name.endsWith('.jpeg')) {
await uploadSingleFile(dirent.name, path.join(folderPath, dirent.name));
await fs.promises.rm(filePath);
}
}
};
async function generatePublicUrl(id) {
try {
const fileId = id;
await drive.permissions.create({
fileId: fileId,
supportsAllDrives: true,
requestBody: {
role: 'reader',
type: 'domain', // 'anyone' da acceso al publico vía enlace https://drive.google.com...
domain: 'gserviceaccount.com', // Si tu cuenta esta bajo un dominio (usuario@empresa.com) y no bajo gmail.com
allowFileDiscovery: false,
},
});
/*
webViewLink: Ver el archivo en el navegador
webContentLink: Enlace de descarga directa
*/
const result = await drive.files.get({
fileId: fileId,
fields: 'webViewLink, webContentLink',
});
console.log(result.data);
} catch (error) {
//console.log(error.message); // Imprime 'Internal Error', pero aún así genera el enlace
console.error = () => { }; // No muestra el error anterior
}
}
module.exports = { uploadSingleFile, scanFolderForFiles }
} else {
console.log(`Actualmente, la base de datos es:\n\t'DATABASE=${process.env.DATABASE}'\nPara usar Google Drive, cambiar a:\n\t'DATABASE=dialogflow'`);
}

53
app.js
View File

@@ -13,8 +13,8 @@ const mysqlConnection = require('./config/mysql')
const { middlewareClient } = require('./middleware/client')
const { generateImage, cleanNumber, checkEnvFile, createClient, isValidNumber } = require('./controllers/handle')
const { connectionReady, connectionLost } = require('./controllers/connection')
const { saveMedia } = require('./controllers/save')
const { getMessages, responseMessages, bothResponse } = require('./controllers/flows')
const { saveMedia, saveMediaToGoogleDrive } = require('./controllers/save')
const { getMessages, responseMessages, bothResponse, waitFor } = require('./controllers/flows')
const { sendMedia, sendMessage, lastTrigger, sendMessageButton, sendMessageList, readChat } = require('./controllers/send');
const { remplazos, stepsInitial} = require('./adapter/index');//MOD by CHV - Agregamos para utilizar remplazos y stepsInitial
const { isUndefined } = require('util');
@@ -29,6 +29,7 @@ const server = require('http').Server(app)
const port = process.env.PORT || 3000
var client;
var dialogflowFilter = false;
var totalMsjs; //MOD by CHV -
var vamosA = ""; //MOD by CHV -
var newBody; //MOD by CHV -
@@ -68,7 +69,7 @@ const listenMessage = () => client.on('message', async msg => {
/**
* Guardamos el archivo multimedia que envia
*/
if (process.env.SAVE_MEDIA && hasMedia) {
if (process.env.SAVE_MEDIA === 'true' && hasMedia) {
const media = await msg.downloadMedia();
saveMedia(media);
}
@@ -78,11 +79,28 @@ const listenMessage = () => client.on('message', async msg => {
*/
if (process.env.DATABASE === 'dialogflow') {
if(!message.length) return;
const response = await bothResponse(message);
if (process.env.DIALOGFLOW_MEDIA_FOR_SLOT_FILLING === 'true' && dialogflowFilter) {
waitFor(_ => hasMedia, 30000)
.then(async _ => {
if (hasMedia) {
const media = await msg.downloadMedia();
message = await saveMediaToGoogleDrive(media);
const response = await bothResponse(message.substring(256, -1), number);
await sendMessage(client, from, response.replyMessage);
}
return
});
dialogflowFilter = false;
}
if (!message.length) return;
const response = await bothResponse(message.substring(256, -1), number);
await sendMessage(client, from, response.replyMessage);
if (response.actions) {
await sendMessageButton(client, from, null, response.actions);
return
}
if (response.media) {
sendMedia(client, from, response.media, response.trigger);
sendMedia(client, from, response.media);
}
return
}
@@ -277,6 +295,28 @@ const listenMessage = () => client.on('message', async msg => {
}
});
/**
* Este evento es necesario para el filtro de Dialogflow
*/
const listenMessageFromBot = () => client.on('message_create', async botMsg => {
const { body } = botMsg;
const dialogflowFilterConfig = fs.readFileSync('./flow/dialogflow.json', 'utf8');
const keywords = JSON.parse(dialogflowFilterConfig);
for (i = 0; i < keywords.length; i++) {
key = keywords[i];
for (var j = 0; j < key.phrases.length; j++) {
let filters = key.phrases[j];
if (body.includes(filters)) {
dialogflowFilter = true;
//console.log(`El filtro de Dialogflow coincidió con el mensaje: ${filters}`);
}
}
}
});
client = new Client({
authStrategy: new LocalAuth(),
puppeteer: { headless: true, args: ['--no-sandbox','--disable-setuid-sandbox'] }
@@ -291,6 +331,7 @@ const listenMessage = () => client.on('message', async msg => {
client.on('ready', (a) => {
connectionReady()
listenMessage()
listenMessageFromBot()
// socketEvents.sendStatus(client)
});

View File

@@ -1,5 +1,5 @@
const {get, reply, getIA} = require('../adapter')
const {saveExternalFile, checkIsUrl} = require('./handle')
const { get, reply, getIA } = require('../adapter')
const { saveExternalFile, checkIsUrl } = require('./handle')
const getMessages = async (message, num) => { //MOD by CHV - Agregamos el parametro "num" para recibir el numero desde "app.js"
// console.log("GETMESSAGES (flow.js)")
@@ -9,9 +9,9 @@ const getMessages = async (message, num) => { //MOD by CHV - Agregamos el parame
const responseMessages = async (step) => {
const data = await reply(step)
if(data && data.media){
if( data && data.media ){
const file = checkIsUrl(data.media) ? await saveExternalFile(data.media) : data.media;
return {...data,...{media:file}}
return { ...data, ...{media:file}}
}
return data
}
@@ -25,5 +25,13 @@ const bothResponse = async (message) => {
return data
}
const waitFor = (conditionFunction, WAIT_TIME) => {
const poll = resolve => {
if (conditionFunction())
resolve();
else setTimeout(_ => poll(resolve), WAIT_TIME);
}
return new Promise(poll);
}
module.exports = { getMessages, responseMessages, bothResponse }
module.exports = { getMessages, responseMessages, bothResponse, waitFor }

View File

@@ -1,23 +1,38 @@
const mimeDb = require('mime-db')
const fs = require('fs')
const mimeDb = require('mime-db');
const { uploadSingleFile } = require('../adapter/gdrive');
const fs = require('fs');
var fileName;
/**
* Guardamos archivos multimedia que nuestro cliente nos envie!
* @param {*} media
*/
const saveMedia = (media) => {
const extensionProcess = mimeDb[media.mimetype];
let ext;
if (!extensionProcess) {
const fileType = media.mimetype.split('/');
ext = fileType[1].split(';')[0];
} else {
ext = extensionProcess.extensions[0];
}
fs.writeFile(`./media/${Date.now()}.${ext}`, media.data, { encoding: 'base64' }, function (err) {
console.log('** Archivo Media Guardado **');
});
const extensionProcess = mimeDb[media.mimetype];
let ext;
if (!extensionProcess) {
const fileType = media.mimetype.split('/');
ext = fileType[1].split(';')[0];
} else {
ext = extensionProcess.extensions[0];
}
fileName = `${Date.now()}.${ext}`;
fs.writeFile(`./media/${fileName}`, media.data, { encoding: 'base64' }, function (err) {
console.log(`** Archivo Media ${fileName} Guardado **`);
});
return fileName
}
module.exports = {saveMedia}
const saveMediaToGoogleDrive = async (media) => {
fileName = saveMedia(media);
filePath = `${__dirname}/../media/${fileName}`
const googleDriveUrl = await uploadSingleFile(fileName, filePath);
return googleDriveUrl
}
module.exports = { saveMedia, saveMediaToGoogleDrive }

View File

@@ -78,6 +78,7 @@ const sendMessageButton = async (client, number = null, text = null, actionButto
number = cleanNumber(number)
const { title = null, message = null, footer = null, buttons = [] } = actionButtons;
let button = new Buttons(remplazos(message, client),[...buttons], remplazos(title, client), remplazos(footer, client));
await readChat(number, message, actionButtons)
client.sendMessage(number, button);
console.log(`⚡⚡⚡ Enviando mensajes (botones)....`);
// console.log("sendMessageButton.");

4412
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -18,10 +18,11 @@
"exceljs": "^4.3.0",
"express": "^4.18.1",
"file-type": "^17.1.6",
"googleapis": "^109.0.1",
"mime-db": "^1.52.0",
"moment": "^2.29.4",
"mysql": "^2.18.1",
"nanoid": "^3.0.0",
"pb-util": "^1.0.3",
"qr-image": "^3.2.0",
"qrcode-terminal": "^0.12.0",
"socket.io": "^4.5.1",