From 398a6be82b3136e1d5c1245c1e763fbe47a725e8 Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 24 Jul 2023 12:21:36 -0300 Subject: [PATCH 01/19] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20na=20api=20de=20s?= =?UTF-8?q?ess=C3=A3o=20remota=20para=20centralizar=20informa=C3=A7=C3=B5e?= =?UTF-8?q?s=20de=20banco=20de=20dados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TEST_SERVER1/api/.env | 6 +- TEST_SERVER1/api/app.js | 817 ++++++++-------- TEST_SERVER1/api/db/connMongo.js | 11 + TEST_SERVER1/api/helpers/PassHash.js | 20 + TEST_SERVER1/api/model/db_conn.js | 33 + TEST_SERVER1/api/package-lock.json | 1328 ++++++++++++++++++++++++++ TEST_SERVER1/api/package.json | 2 + 7 files changed, 1810 insertions(+), 407 deletions(-) create mode 100644 TEST_SERVER1/api/db/connMongo.js create mode 100644 TEST_SERVER1/api/helpers/PassHash.js create mode 100644 TEST_SERVER1/api/model/db_conn.js diff --git a/TEST_SERVER1/api/.env b/TEST_SERVER1/api/.env index 1109bfc..8e97f45 100644 --- a/TEST_SERVER1/api/.env +++ b/TEST_SERVER1/api/.env @@ -1,3 +1,7 @@ PORT=8019 PORT_START=8020 -BASE_URL=http://localhost \ No newline at end of file +BASE_URL=http://localhost +PASS="strongpassword, strongpassword32" +DB_MONGO_URL=mongodb://localhost:27017 +DB_MONGO_NAME=session_out_omnihit_db + \ No newline at end of file diff --git a/TEST_SERVER1/api/app.js b/TEST_SERVER1/api/app.js index c84b124..c68f564 100644 --- a/TEST_SERVER1/api/app.js +++ b/TEST_SERVER1/api/app.js @@ -1,486 +1,491 @@ -const express = require('express'); -const bodyparser = require('body-parser'); -const dotenv = require('dotenv'); -dotenv.config({ path: '.env' }); +const express = require('express') +const bodyparser = require('body-parser') +const dotenv = require('dotenv') +dotenv.config({ path: '.env' }) const copyFolder = require('./helpers/copyFolder') const createDir = require('./helpers/createDir') const createFile = require('./helpers/createFile') -const path = require('path'); +const path = require('path') const db_info = require('./db_conn') -const fs = require('fs'); -let mysql_conn = require('./helpers/mysql_conn.js'); -const { exec, execSync, spawn } = require("child_process"); +const fs = require('fs') +let mysql_conn = require('./helpers/mysql_conn.js') +const { exec, execSync, spawn } = require('child_process') -const startPm2Process = require('./helpers/startPm2Process'); -const removeDir = require('./helpers/remove_dir'); +const startPm2Process = require('./helpers/startPm2Process') +const removeDir = require('./helpers/remove_dir') const setSessionName = require('./helpers/setSessionNumber') const getNumberFromName = require('./helpers/getNumberSequence') -const pm2 = require('pm2'); +const pm2 = require('pm2') +const bcrypt = require('bcrypt') +const OmnihitDBConn = require('./model/db_conn') -const app = express(); +const app = express() -app.use(bodyparser.json()); +app.use(bodyparser.json()) -app.get('/', function (req, res) { return res.send('Express + TypeScript Server'); }); +app.get('/', function (req, res) { + return res.send('Express + TypeScript Server') +}) app.post('/api/session', async function (req, res) { + let { app_name, whatsappId, client_url, number } = req.body - let { app_name, whatsappId, client_url, number } = req.body + if (app_name) { + app_name = app_name.trim() + } - if(app_name){ - app_name = app_name.trim() + console.log('__dirname: ', path.join(__dirname, '..', app_name)) + + console.log( + 'app_name: ', + app_name, + ' | whatsappId: ', + whatsappId, + ' | client_url: ', + client_url + ) + + const sessionsPath = path.join(__dirname, '..', 'sessions') + + const directoriesInDIrectory = fs + .readdirSync(sessionsPath, { withFileTypes: true }) + .filter((item) => item.isDirectory()) + .map((item) => item.name) + + console.log('directoriesInDIrectory: ', directoriesInDIrectory) + + const dirExist = directoriesInDIrectory.filter((e) => e.trim() == app_name) + + let dirSessionsApp = path.join(sessionsPath, app_name) + + if (dirExist.length == 0) { + let create = createDir(dirSessionsApp) + + if (!create) { + res.status(500).json({ message: 'Cannot create the directory path!' }) + return } + } - console.log('__dirname: ', path.join(__dirname, '..', app_name)) + let appPort = [] - console.log('app_name: ', app_name, ' | whatsappId: ', whatsappId, ' | client_url: ',client_url) + let existSubDir = false - const sessionsPath = path.join(__dirname, '..', 'sessions') + for (let i = 0; i < directoriesInDIrectory.length; i++) { + console.log('directoriesInDIrectory[i]', directoriesInDIrectory[i]) - const directoriesInDIrectory = fs.readdirSync(sessionsPath, { withFileTypes: true }) - .filter((item) => item.isDirectory()) - .map((item) => item.name); + const subDir = fs + .readdirSync(path.join(sessionsPath, directoriesInDIrectory[i]), { + withFileTypes: true, + }) + .filter((item) => item.isDirectory()) + .map((item) => item.name) - console.log('directoriesInDIrectory: ', directoriesInDIrectory) + for (let x = 0; x < subDir.length; x++) { + console.log('subdir: ', subDir[x]) - const dirExist = directoriesInDIrectory.filter((e) => e.trim() == app_name) + let whatsId = subDir[x].split('_')[0] - let dirSessionsApp = path.join(sessionsPath, app_name) + if (whatsId == whatsappId && app_name == directoriesInDIrectory[i]) { + let currPath = path.join( + sessionsPath, + directoriesInDIrectory[i], + subDir[x] + ) - if (dirExist.length == 0) { + console.log( + 'PATH: ', + path.join(sessionsPath, directoriesInDIrectory[i], subDir[x]) + ) - let create = createDir(dirSessionsApp) + let oldNumber = subDir[x].split('_')[1] - if (!create) { - - res.status(500).json({ message: 'Cannot create the directory path!' }) - return + if (oldNumber != number) { + deletePm2Process(subDir[x], currPath) + removeDir(currPath) + } else { + res.send('ok') + return } - } + } - let appPort = [] + let auxPort = subDir[x].split('_')[3] + console.log('---------> auxPort: ' + auxPort) + if (auxPort) { + auxPort = +auxPort.trim() - let existSubDir = false - - for (let i = 0; i < directoriesInDIrectory.length; i++) { - - console.log('directoriesInDIrectory[i]', directoriesInDIrectory[i]) - - const subDir = fs.readdirSync(path.join(sessionsPath, directoriesInDIrectory[i]), { withFileTypes: true }) - .filter((item) => item.isDirectory()) - .map((item) => item.name); - - for (let x = 0; x < subDir.length; x++) { - - console.log('subdir: ', subDir[x]) - - let whatsId = subDir[x].split('_')[0] - - if (whatsId == whatsappId && app_name == directoriesInDIrectory[i]) { - - let currPath = path.join(sessionsPath, directoriesInDIrectory[i], subDir[x]) - - console.log('PATH: ', path.join(sessionsPath, directoriesInDIrectory[i], subDir[x])) - - let oldNumber = subDir[x].split('_')[1] - // let sessionNum = subDir[x].split('_')[2] - // let sessionPort = subDir[x].split('_')[3] - // let newSessionAppName = `${whatsId}_${number}_${sessionNum}_${sessionPort}` - - // let newPath = path.join(sessionsPath, directoriesInDIrectory[i], newSessionAppName) - - // console.log(`number: ${number}\noldNumber: ${oldNumber}\nsessionNum: ${sessionNum}\nsessionPort: ${sessionPort}\nnewSessionAppName:${newSessionAppName}`) - - if (oldNumber != number) { - - deletePm2Process(subDir[x], currPath) - - removeDir(currPath) - } - else { - res.send('ok') - return - } - - - - - // try { - - // // - - // fs.renameSync(currPath, newPath) - - // console.log("Successfully renamed the directory.") - - // const data = fs.readFileSync(path.join(`${newPath}`, '.env'), 'utf-8'); - - // // console.log('Data: ', data) - - // const newValue = data.replace(`MOBILEUID=${oldNumber}`, `MOBILEUID=${number}`) - - // fs.writeFileSync(path.join(`${newPath}`, '.env'), newValue, 'utf-8'); - - // if (oldNumber != number) { - // removeDir(path.join(newPath, '.wwebjs_auth')) - // } - - // startPm2Process(newSessionAppName, 'app.js', newPath, sessionPort) - - - // } catch (err) { - // console.log(err) - // } - - - // res.send('ok') - // return - } - - appPort.push(+subDir[x].split('_')[3]) - - console.log('---------> appPort: '+appPort) - - existSubDir = true - + if (!isNaN(auxPort)) { + appPort.push(auxPort) } + } + existSubDir = true } + } - appPort = existSubDir ? Math.max(...appPort) + 1 : process.env.PORT_START + appPort = existSubDir ? Math.max(...appPort) + 1 : process.env.PORT_START - console.log('new port: ', appPort) + console.log('new port: ', appPort) + let dirSessionAppName + let numberSession = 1 - let dirSessionAppName + let lstPass = process.env.PASS - let numberSession = 1 + if (!lstPass) { + console.log('PASS VARIABLE NOT FOUND INTO .ENV!') + return res.send('OK') + } - // const dirSessionsNumberAppDirectories = fs.readdirSync(dirSessionsApp, { withFileTypes: true }) - // .filter((item) => item.isDirectory() && item.name.includes(`${number}`)) - // .map((item) => item.name); + let db_credentials + try { + db_credentials = await OmnihitDBConn.findOne({ client_url }) - // console.log('dirSessionsNumberAppDirectories', dirSessionsNumberAppDirectories, ' | dirSessionsApp: ', dirSessionsApp) - - console.log('client_url: ', client_url) - - let db = db_info.filter((e) => e.client_url == client_url) - - if (db && db.length > 0) { - - db = db[0].db_conf + if (!db_credentials) { + db_credentials = new OmnihitDBConn({ + client_url: client_url, + db_conf: { + DB: '', + DB_HOST: '', + DB_USER: '', + DB_PASS: '', + DB_PORT: '', + }, + }) + await db_credentials.save() + return res.send('ok') } + } catch (error) { + console.log(error) + } - // if (dirSessionsNumberAppDirectories.length > 0) { - - if (db && Object.keys(db).length > 0) { - - const whatsapp_numbers = await new Promise((resolve, reject) => { - mysql_conn(db).query('SELECT name FROM Whatsapps WHERE name LIKE ?', [`%${number}%`], (err, result) => { - if (err) { - reject(err) - } - else { - resolve(result) - } - }); - }) - - console.log('whatsapp_numbers: ', whatsapp_numbers) - - let session_num = [] - - if (whatsapp_numbers && whatsapp_numbers.length > 0) { - - console.log('whatsapp_numbers.length: ', whatsapp_numbers.length) - - if (whatsapp_numbers.length == 5) { - res.status(400).json({ message: 'Cannot create more than 4 sessions from the same number' }) - return - } - - let regex = /-> [a-zA-Z]\d$/ - - let numbered_sessions = whatsapp_numbers.filter((e) => regex.test(e.name)) - - console.log('numbered_sessions: ', numbered_sessions) - - session_num = numbered_sessions.map((e) => parseInt((e.name.split('->')[e.name.split('->').length - 1]).trim().match(/\d+/)[0])) - - console.log('session_num', session_num) - - } - - let index = 1; - - while (index <= 4) { - - if (!session_num.includes(index)) { - console.log(index) - numberSession = index - break - } - index++ - } + if (db_credentials && db_credentials.db_conf.DB.trim().length > 0) { + lstPass = lstPass.split(',') + let password = null + password = await lstPass.find( + async (pass) => + await bcrypt.compare(pass.trim(), db_credentials.db_conf.DB_PASS) + ) + if (password) { + db_credentials.db_conf.DB_PASS = password + } else { + return res.send('ok') + } + } + if ( + db_credentials.db_conf && + Object.keys(db_credentials.db_conf).length > 0 + ) { + const whatsapp_numbers = await new Promise((resolve, reject) => { + mysql_conn(db_credentials.db_conf).query( + 'SELECT name FROM Whatsapps WHERE name LIKE ?', + [`%${number}%`], + (err, result) => { + if (err) { + reject(err) + } else { + resolve(result) + } } + ) + }) + console.log('whatsapp_numbers: ', whatsapp_numbers) - // numberSession = Math.max(...session_number) + 1 + let session_num = [] - console.log('Number session: ', numberSession) - - // } - - dirSessionAppName = `${whatsappId}_${number}_${numberSession}_${appPort}` - - - - destDir = path.join(dirSessionsApp, dirSessionAppName) - - originDir = path.join(__dirname, '..', 'whats') - - copyFolder(originDir, destDir) - - - if (db && Object.keys(db).length > 0) { - - console.log('kkkkkkkkkkkkkkk') - - let whatsName - - const whatsapp = await new Promise((resolve, reject) => { - - mysql_conn(db).query("SELECT name from Whatsapps where id = ?", [whatsappId], (err, result) => { - - if (err) { - reject(err) - } - else { - resolve(result) - } - }); + if (whatsapp_numbers && whatsapp_numbers.length > 0) { + console.log('whatsapp_numbers.length: ', whatsapp_numbers.length) + if (whatsapp_numbers.length == 5) { + res.status(400).json({ + message: 'Cannot create more than 4 sessions from the same number', }) + return + } - if (whatsapp[0]["name"].split('->').length > 0) { - whatsName = `${whatsapp[0]["name"].split('->')[0]} -> S${numberSession}` - } - else { - whatsName = `${whatsapp[0]["name"]} -> S${numberSession}` - } + let regex = /-> [a-zA-Z]\d$/ - console.log('whatsName: ', whatsName) + let numbered_sessions = whatsapp_numbers.filter((e) => regex.test(e.name)) - console.log(`url: ${process.env.BASE_URL}:${appPort}\n whatsname: ${whatsName}\n whatsappId: ${whatsappId}`) + console.log('numbered_sessions: ', numbered_sessions) - await new Promise((resolve, reject) => { - mysql_conn(db).query("UPDATE Whatsapps SET url = ?, name = ? where id = ?", [`${process.env.BASE_URL}:${appPort}`, `${whatsName}`, whatsappId], - - function (err, result) { - if (err) { - reject(err) - console.log("===> ERROR: " + err); - } - else { - resolve(result) - // console.log('RESULT: ', result) - } - // else - // console.log('myslq result: ', result); - }); - }) - - let whatsappName = `${number} - s${numberSession}` - - console.log('-------------- numberSession', numberSession) - - if (whatsapp.length > 0) { - - if (whatsapp[0]['name'].split(' ').length > 0) { - - whatsappName = `${whatsapp[0]['name'].split(' ')[0]} - S${numberSession}` - - } - - } - - console.log('whatsapp: ', whatsapp) - console.log("whatsapp[0]['name']: ", whatsapp[0]['name']) - - const keys = Object.keys(db); - - var stream = fs.createWriteStream(path.join(destDir, '.env')); - stream.once('open', function (fd) { - stream.write("# NUMBER AND NAME THAT WILL BE DISPLAYED ON CONSOLE\n"); - stream.write(`MOBILEUID=${number}\n`); - stream.write(`MOBILENAME=${whatsappName}\n`); - stream.write("\n"); - - stream.write("# PORT NUMBER FOR THIS API\n"); - stream.write(`PORT=${appPort}\n`); - stream.write("\n"); - - stream.write("# URL FROM THE OMNIHIT BACKEND API\n"); - stream.write(`CLIENT_URL=${client_url}\n`); - stream.write("\n"); - - stream.write("# OMNIHIT DATABASE\n"); - keys.forEach((key, index) => { - stream.write(`${key}=${db[key]}\n`); - }); - stream.write("\n"); - - stream.write(`# WHATSAPP ID OF THE TABLE Whatsapps FROM THE OMNIHIT DATABASE\n`); - stream.write(`WHATSAPP_ID=${whatsappId}`); - - stream.end(); - }); - - - - console.log('----------------destDir: ', destDir) - - - execSync(`npm install`, { cwd: destDir }, (error, stdout, stderr) => { - if (error) { - console.log(`error: ${error.message}`); - return; - } - if (stderr) { - console.log(`stderr: ${stderr}`); - return; - } - console.log(`stdout: ${stdout}`); - }); - - startPm2Process(dirSessionAppName, 'app.js', destDir, appPort) + session_num = numbered_sessions.map((e) => + parseInt( + e.name + .split('->') + [e.name.split('->').length - 1].trim() + .match(/\d+/)[0] + ) + ) + console.log('session_num', session_num) } - res.send("OK"); + let index = 1 -}); + while (index <= 4) { + if (!session_num.includes(index)) { + console.log(index) + numberSession = index + break + } + index++ + } + } + + // numberSession = Math.max(...session_number) + 1 + + console.log('Number session: ', numberSession) + + // } + + dirSessionAppName = `${whatsappId}_${number}_${numberSession}_${appPort}` + + destDir = path.join(dirSessionsApp, dirSessionAppName) + + originDir = path.join(__dirname, '..', 'whats') + + copyFolder(originDir, destDir) + + if ( + db_credentials.db_conf && + Object.keys(db_credentials.db_conf).length > 0 + ) { + console.log('***SUCCESS SEED DIRECTORY CREATED***') + + let whatsName + + const whatsapp = await new Promise((resolve, reject) => { + mysql_conn(db_credentials.db_conf).query( + 'SELECT name from Whatsapps where id = ?', + [whatsappId], + (err, result) => { + if (err) { + reject(err) + } else { + resolve(result) + } + } + ) + }) + + if (whatsapp[0]['name'].split('->').length > 0) { + whatsName = `${whatsapp[0]['name'].split('->')[0]} -> S${numberSession}` + } else { + whatsName = `${whatsapp[0]['name']} -> S${numberSession}` + } + + console.log('whatsName: ', whatsName) + + console.log( + `url: ${process.env.BASE_URL}:${appPort}\n whatsname: ${whatsName}\n whatsappId: ${whatsappId}` + ) + + await new Promise((resolve, reject) => { + mysql_conn(db_credentials.db_conf).query( + 'UPDATE Whatsapps SET url = ?, name = ? where id = ?', + [`${process.env.BASE_URL}:${appPort}`, `${whatsName}`, whatsappId], + + function (err, result) { + if (err) { + reject(err) + console.log('===> ERROR: ' + err) + } else { + resolve(result) + // console.log('RESULT: ', result) + } + // else + // console.log('myslq result: ', result); + } + ) + }) + + let whatsappName = `${number} - s${numberSession}` + + console.log('-------------- numberSession', numberSession) + + if (whatsapp.length > 0) { + if (whatsapp[0]['name'].split(' ').length > 0) { + whatsappName = `${ + whatsapp[0]['name'].split(' ')[0] + } - S${numberSession}` + } + } + + console.log('whatsapp: ', whatsapp) + console.log("whatsapp[0]['name']: ", whatsapp[0]['name']) + + const keys = Object.keys(db_credentials.db_conf) + + var stream = fs.createWriteStream(path.join(destDir, '.env')) + stream.once('open', function (fd) { + stream.write('# NUMBER AND NAME THAT WILL BE DISPLAYED ON CONSOLE\n') + stream.write(`MOBILEUID=${number}\n`) + stream.write(`MOBILENAME=${whatsappName}\n`) + stream.write('\n') + + stream.write('# PORT NUMBER FOR THIS API\n') + stream.write(`PORT=${appPort}\n`) + stream.write('\n') + + stream.write('# URL FROM THE OMNIHIT BACKEND API\n') + stream.write(`CLIENT_URL=${client_url}\n`) + stream.write('\n') + + stream.write('# OMNIHIT DATABASE\n') + keys.forEach((key, index) => { + stream.write(`${key}=${db_credentials.db_conf[key]}\n`) + }) + stream.write('\n') + + stream.write( + `# WHATSAPP ID OF THE TABLE Whatsapps FROM THE OMNIHIT DATABASE\n` + ) + stream.write(`WHATSAPP_ID=${whatsappId}`) + + stream.end() + }) + + console.log('----------------destDir: ', destDir) + + execSync(`npm install`, { cwd: destDir }, (error, stdout, stderr) => { + if (error) { + console.log(`error: ${error.message}`) + return + } + if (stderr) { + console.log(`stderr: ${stderr}`) + return + } + console.log(`stdout: ${stdout}`) + }) + + startPm2Process(dirSessionAppName, 'app.js', destDir, appPort) + } + + res.send('OK') +}) app.post('/api/session/edit', async function (req, res) { - - const { app_name, whatsappId, client_url, number } = req.body - + const { app_name, whatsappId, client_url, number } = req.body }) app.post('/api/session/del', async function (req, res) { + let { whatsappId, app_name } = req.body - let { whatsappId, app_name } = req.body + if (app_name) { + app_name = app_name.trim() + } - if(app_name){ - app_name = app_name.trim() + const sessionsPath = path.join(__dirname, '..', 'sessions') + + const directoriesInDIrectory = fs + .readdirSync(sessionsPath, { withFileTypes: true }) + .filter((item) => item.isDirectory()) + .map((item) => item.name) + + console.log('directoriesInDIrectory: ', directoriesInDIrectory) + + const dirExist = directoriesInDIrectory.filter((e) => e.trim() == app_name) + + console.log('dirExist: ', dirExist) + + if (dirExist.length == 0) res.send('ok') + + for (let i = 0; i < directoriesInDIrectory.length; i++) { + console.log('directoriesInDIrectory[i]', directoriesInDIrectory[i]) + + const subDir = fs + .readdirSync(path.join(sessionsPath, directoriesInDIrectory[i]), { + withFileTypes: true, + }) + .filter((item) => item.isDirectory()) + .map((item) => item.name) + + for (let x = 0; x < subDir.length; x++) { + console.log('subdir: ', subDir[x]) + + let whatsId = subDir[x].split('_')[0] + + if (whatsId == whatsappId && app_name == directoriesInDIrectory[i]) { + let currPath = path.join( + sessionsPath, + directoriesInDIrectory[i], + subDir[x] + ) + + deletePm2Process(subDir[x], currPath) + + console.log('currPath: ', currPath) + + removeDir(currPath) + + return res.send('ok') + } } + } - const sessionsPath = path.join(__dirname, '..', 'sessions') - - const directoriesInDIrectory = fs.readdirSync(sessionsPath, { withFileTypes: true }) - .filter((item) => item.isDirectory()) - .map((item) => item.name); - - console.log('directoriesInDIrectory: ', directoriesInDIrectory) - - const dirExist = directoriesInDIrectory.filter((e) => e.trim() == app_name) - - console.log('dirExist: ', dirExist) - - if (dirExist.length == 0) - res.send('ok') - - - for (let i = 0; i < directoriesInDIrectory.length; i++) { - - console.log('directoriesInDIrectory[i]', directoriesInDIrectory[i]) - - const subDir = fs.readdirSync(path.join(sessionsPath, directoriesInDIrectory[i]), { withFileTypes: true }) - .filter((item) => item.isDirectory()) - .map((item) => item.name); - - for (let x = 0; x < subDir.length; x++) { - - console.log('subdir: ', subDir[x]) - - let whatsId = subDir[x].split('_')[0] - - if (whatsId == whatsappId && app_name == directoriesInDIrectory[i]) { - - let currPath = path.join(sessionsPath, directoriesInDIrectory[i], subDir[x]) - - deletePm2Process(subDir[x], currPath); - - console.log('currPath: ', currPath) - - removeDir(currPath) - - return res.send('ok') - - } - - } - - } - - res.send('ok') - + res.send('ok') }) - - app.listen(process.env.PORT || 8003, function () { - console.log("\u26A1[server]: Server is running at Port ::: " + process.env.PORT || 8003); -}); + console.log( + '\u26A1[server]: Server is running at Port ::: ' + process.env.PORT || 8003 + ) +}) process.on('uncaughtException', function (err) { - console.error(' '); - console.error('----- ' + (new Date).toUTCString() + ' ----------------------------------') - console.error('Erro uncaughtException: ', err.message) - console.error(err.stack) - console.error(' '); - return -}); + console.error(' ') + console.error( + '----- ' + new Date().toUTCString() + ' ----------------------------------' + ) + console.error('Erro uncaughtException: ', err.message) + console.error(err.stack) + console.error(' ') + return +}) function deletePm2Process(process_name, currPath) { - pm2.connect(function (err) { - if (err) { - console.error(err); - } + pm2.connect(function (err) { + if (err) { + console.error(err) + } - pm2.list(function (err, processes) { - if (err) { - console.error(err); + pm2.list(function (err, processes) { + if (err) { + console.error(err) + } + + processes.forEach(function (process) { + console.log('.........process.name: ', process.name) + + if (process.name === process_name) { + execSync( + `pm2 delete ${process_name} && pm2 save --force`, + { cwd: currPath }, + (error, stdout, stderr) => { + if (error) { + console.log(`error: ${error.message}`) + return + } + if (stderr) { + console.log(`stderr: ${stderr}`) + return + } + console.log(`stdout: ${stdout}`) } + ) + } + }) - processes.forEach(function (process) { - - console.log(".........process.name: ", process.name); - - if (process.name === process_name) { - execSync(`pm2 delete ${process_name} && pm2 save --force`, { cwd: currPath }, (error, stdout, stderr) => { - if (error) { - console.log(`error: ${error.message}`); - return; - } - if (stderr) { - console.log(`stderr: ${stderr}`); - return; - } - console.log(`stdout: ${stdout}`); - }); - } - - }); - - pm2.disconnect(); - }); - }); + pm2.disconnect() + }) + }) } - diff --git a/TEST_SERVER1/api/db/connMongo.js b/TEST_SERVER1/api/db/connMongo.js new file mode 100644 index 0000000..2026782 --- /dev/null +++ b/TEST_SERVER1/api/db/connMongo.js @@ -0,0 +1,11 @@ +const mongoose = require('mongoose') +require('dotenv').config({ path: `${process.cwd()}/.env` }) + +async function main(){ + await mongoose.connect(process.env.DB_MONGO_URL, { dbName: process.env.DB_MONGO_NAME }) + console.log('Conectou ao Mongoose!') +} + +main().catch((err)=>console.log(err)) + +module.exports = mongoose \ No newline at end of file diff --git a/TEST_SERVER1/api/helpers/PassHash.js b/TEST_SERVER1/api/helpers/PassHash.js new file mode 100644 index 0000000..7b15e55 --- /dev/null +++ b/TEST_SERVER1/api/helpers/PassHash.js @@ -0,0 +1,20 @@ +const bcrypt = require('bcrypt') + +const pass = async () => { + // create a password + const salt = await bcrypt.genSalt(12) + const passwordHash = await bcrypt.hash('strongpassword', salt) + console.log(passwordHash) +} +pass() + +// const passDec = async () => { +// const _pass = await bcrypt.compare( +// 'strongpassword', +// '$2b$12$R/bpS7b9FzdXlHAijmP.3.gJqgeUjwQVSuK6q.G0PZbb0wowCnrN.' +// ) +// console.log('_pass: ', _pass) +// } +// passDec() + +console.log('process.cwd(): ', process.cwd()) diff --git a/TEST_SERVER1/api/model/db_conn.js b/TEST_SERVER1/api/model/db_conn.js new file mode 100644 index 0000000..5f677b3 --- /dev/null +++ b/TEST_SERVER1/api/model/db_conn.js @@ -0,0 +1,33 @@ +const mongoose = require('../db/connMongo') +const { Schema } = mongoose + +const OmnihitDBConn = mongoose.model( + 'Omnihit_db_conn', + new Schema( + { + client_url: { + type: String, + }, + db_conf: { + DB: { + type: String, + }, + DB_HOST: { + type: String, + }, + DB_USER: { + type: String, + }, + DB_PASS: { + type: String, + }, + DB_PORT: { + type: String, + }, + }, + }, + { timestamps: true } + ) +) + +module.exports = OmnihitDBConn diff --git a/TEST_SERVER1/api/package-lock.json b/TEST_SERVER1/api/package-lock.json index 34fb6eb..06387b3 100644 --- a/TEST_SERVER1/api/package-lock.json +++ b/TEST_SERVER1/api/package-lock.json @@ -9,15 +9,64 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "bcrypt": "^5.1.0", "body-parser": "^1.20.1", "dotenv": "^16.0.3", "express": "^4.18.2", "fs-extra": "^11.1.0", + "mongoose": "^7.4.0", "mysql": "^2.18.1", "nodemon": "^2.0.20", "socket.io": "^4.5.4" } }, + "node_modules/@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "dependencies": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@mapbox/node-pre-gyp/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -41,6 +90,20 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -58,6 +121,46 @@ "node": ">= 0.6" } }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/agent-base/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/agent-base/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -70,6 +173,36 @@ "node": ">= 8" } }, + "node_modules/aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "node_modules/are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/are-we-there-yet/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -88,6 +221,19 @@ "node": "^4.5.0 || >= 5.9" } }, + "node_modules/bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "hasInstallScript": true, + "dependencies": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -147,6 +293,14 @@ "node": ">=8" } }, + "node_modules/bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "engines": { + "node": ">=14.20.1" + } + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -193,11 +347,32 @@ "fsevents": "~2.3.2" } }, + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "bin": { + "color-support": "bin.js" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "node_modules/console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "node_modules/content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -255,6 +430,11 @@ "ms": "2.0.0" } }, + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "node_modules/depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -272,6 +452,14 @@ "npm": "1.2.8000 || >= 1.4.16" } }, + "node_modules/detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==", + "engines": { + "node": ">=8" + } + }, "node_modules/dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -285,6 +473,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -461,6 +654,33 @@ "node": ">=14.14" } }, + "node_modules/fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "dependencies": { + "minipass": "^3.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "node_modules/fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -479,6 +699,25 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "dependencies": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -492,6 +731,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -538,6 +796,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "node_modules/http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -553,6 +816,39 @@ "node": ">= 0.8" } }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/https-proxy-agent/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -569,11 +865,25 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "node_modules/ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -601,6 +911,14 @@ "node": ">=0.10.0" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -636,6 +954,47 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "bin": { + "semver": "bin/semver.js" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -644,6 +1003,12 @@ "node": ">= 0.6" } }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -698,6 +1063,163 @@ "node": "*" } }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "dependencies": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.201.0", + "@mongodb-js/zstd": "^1.1.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongoose": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.0.tgz", + "integrity": "sha512-oHE1eqodfKzugXRlQxpo+msIea7jPcRoayDuEMr50+bYwM/juA5f+1stjkWlXcg6vo1PdJFVA6DGaKOPLuG5mA==", + "dependencies": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -730,6 +1252,49 @@ "node": ">= 0.6" } }, + "node_modules/node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node_modules/node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-fetch/node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "node_modules/node-fetch/node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "node_modules/node-fetch/node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, "node_modules/nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", @@ -792,6 +1357,17 @@ "node": ">=0.10.0" } }, + "node_modules/npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "dependencies": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -819,6 +1395,14 @@ "node": ">= 0.8" } }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -827,6 +1411,14 @@ "node": ">= 0.8" } }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -865,6 +1457,14 @@ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, "node_modules/qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -931,6 +1531,20 @@ "node": ">=8.10.0" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -955,6 +1569,18 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -1005,6 +1631,11 @@ "node": ">= 0.8.0" } }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -1023,6 +1654,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "node_modules/simple-update-notifier": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", @@ -1042,6 +1683,15 @@ "semver": "bin/semver.js" } }, + "node_modules/smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, "node_modules/socket.io": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz", @@ -1117,6 +1767,28 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, "node_modules/sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", @@ -1146,6 +1818,30 @@ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -1157,6 +1853,22 @@ "node": ">=4" } }, + "node_modules/tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -1187,6 +1899,17 @@ "nodetouch": "bin/nodetouch.js" } }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -1241,6 +1964,39 @@ "node": ">= 0.8" } }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "node_modules/ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", @@ -1260,9 +2016,48 @@ "optional": true } } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } }, "dependencies": { + "@mapbox/node-pre-gyp": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz", + "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==", + "requires": { + "detect-libc": "^2.0.0", + "https-proxy-agent": "^5.0.0", + "make-dir": "^3.1.0", + "node-fetch": "^2.6.7", + "nopt": "^5.0.0", + "npmlog": "^5.0.1", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "tar": "^6.1.11" + }, + "dependencies": { + "nopt": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", + "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==", + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "requires": { + "lru-cache": "^6.0.0" + } + } + } + }, "@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -1286,6 +2081,20 @@ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.11.18.tgz", "integrity": "sha512-DHQpWGjyQKSHj3ebjFI/wRKcqQcdR+MoFBygntYOZytCqNfkd2ZC4ARDJ2DQqhjH5p85Nnd3jhUJIXrszFX/JA==" }, + "@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "requires": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -1300,6 +2109,34 @@ "negotiator": "0.6.3" } }, + "agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "requires": { + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + }, "anymatch": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", @@ -1309,6 +2146,32 @@ "picomatch": "^2.0.4" } }, + "aproba": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", + "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" + }, + "are-we-there-yet": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz", + "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, + "dependencies": { + "readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + } + } + }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -1324,6 +2187,15 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, + "bcrypt": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-5.1.0.tgz", + "integrity": "sha512-RHBS7HI5N5tEnGTmtR/pppX0mmDSBpQ4aCBsj7CEQfYXDcO74A8sIBYcJMuCsis2E81zDxeENYhv66oZwLiA+Q==", + "requires": { + "@mapbox/node-pre-gyp": "^1.0.10", + "node-addon-api": "^5.0.0" + } + }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -1370,6 +2242,11 @@ "fill-range": "^7.0.1" } }, + "bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==" + }, "bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1399,11 +2276,26 @@ "readdirp": "~3.6.0" } }, + "chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==" + }, + "color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==" + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==" + }, "content-disposition": { "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", @@ -1449,6 +2341,11 @@ "ms": "2.0.0" } }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" + }, "depd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", @@ -1459,6 +2356,11 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, + "detect-libc": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.2.tgz", + "integrity": "sha512-UX6sGumvvqSaXgdKGUsgZWqcUyIXZ/vZTrlRT/iobiKhGL0zL4d3osHj3uqllWJK+i+sixDS/3COVEOFbupFyw==" + }, "dotenv": { "version": "16.0.3", "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", @@ -1469,6 +2371,11 @@ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, "encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", @@ -1606,6 +2513,29 @@ "universalify": "^2.0.0" } }, + "fs-minipass": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", + "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", + "requires": { + "minipass": "^3.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, "fsevents": { "version": "2.3.2", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", @@ -1617,6 +2547,22 @@ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, + "gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "requires": { + "aproba": "^1.0.3 || ^2.0.0", + "color-support": "^1.1.2", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.1", + "object-assign": "^4.1.1", + "signal-exit": "^3.0.0", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wide-align": "^1.1.2" + } + }, "get-intrinsic": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", @@ -1627,6 +2573,19 @@ "has-symbols": "^1.0.3" } }, + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1658,6 +2617,11 @@ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==" }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" + }, "http-errors": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", @@ -1670,6 +2634,30 @@ "toidentifier": "1.0.1" } }, + "https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "requires": { + "agent-base": "6", + "debug": "4" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1683,11 +2671,25 @@ "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==" }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, + "ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, "ipaddr.js": { "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", @@ -1706,6 +2708,11 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==" }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -1733,11 +2740,45 @@ "universalify": "^2.0.0" } }, + "kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "requires": { + "yallist": "^4.0.0" + } + }, + "make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "requires": { + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==" + } + } + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==" }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, "merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", @@ -1774,6 +2815,104 @@ "brace-expansion": "^1.1.7" } }, + "minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + }, + "minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "requires": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "dependencies": { + "minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "requires": { + "yallist": "^4.0.0" + } + } + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==" + }, + "mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "requires": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "saslprep": "^1.0.3", + "socks": "^2.7.1" + } + }, + "mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "requires": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "mongoose": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.0.tgz", + "integrity": "sha512-oHE1eqodfKzugXRlQxpo+msIea7jPcRoayDuEMr50+bYwM/juA5f+1stjkWlXcg6vo1PdJFVA6DGaKOPLuG5mA==", + "requires": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1802,6 +2941,40 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, + "node-addon-api": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-5.1.0.tgz", + "integrity": "sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==" + }, + "node-fetch": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.12.tgz", + "integrity": "sha512-C/fGU2E8ToujUivIO0H+tpQ6HWo4eEmchoPIoXtxCrVghxdKq+QOHqEZW7tuP3KlV3bC8FRMO5nMCC7Zm1VP6g==", + "requires": { + "whatwg-url": "^5.0.0" + }, + "dependencies": { + "tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + }, + "webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + }, + "whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "requires": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + } + } + }, "nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", @@ -1847,6 +3020,17 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==" }, + "npmlog": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", + "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", + "requires": { + "are-we-there-yet": "^2.0.0", + "console-control-strings": "^1.1.0", + "gauge": "^3.0.0", + "set-blocking": "^2.0.0" + } + }, "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", @@ -1865,11 +3049,24 @@ "ee-first": "1.1.1" } }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "requires": { + "wrappy": "1" + } + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==" + }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", @@ -1899,6 +3096,11 @@ "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==" }, + "punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==" + }, "qs": { "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", @@ -1952,6 +3154,14 @@ "picomatch": "^2.2.1" } }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "requires": { + "glob": "^7.1.3" + } + }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -1962,6 +3172,15 @@ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, "semver": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", @@ -2005,6 +3224,11 @@ "send": "0.18.0" } }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==" + }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2020,6 +3244,16 @@ "object-inspect": "^1.9.0" } }, + "sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, + "signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, "simple-update-notifier": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", @@ -2035,6 +3269,11 @@ } } }, + "smart-buffer": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz", + "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==" + }, "socket.io": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/socket.io/-/socket.io-4.5.4.tgz", @@ -2092,6 +3331,24 @@ } } }, + "socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "requires": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + } + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, "sqlstring": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", @@ -2117,6 +3374,24 @@ } } }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "requires": { + "ansi-regex": "^5.0.1" + } + }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2125,6 +3400,19 @@ "has-flag": "^3.0.0" } }, + "tar": { + "version": "6.1.15", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.15.tgz", + "integrity": "sha512-/zKt9UyngnxIT/EAGYuxaMYgOIJiP81ab9ZfkILq4oNLPFX50qyYmu7jRj9qeXoxmJHjGlbH0+cm2uy1WCs10A==", + "requires": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + } + }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2146,6 +3434,14 @@ "nopt": "~1.0.10" } }, + "tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "requires": { + "punycode": "^2.1.1" + } + }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2185,10 +3481,42 @@ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==" }, + "webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" + }, + "whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "requires": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + } + }, + "wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "requires": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, "ws": { "version": "8.2.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.2.3.tgz", "integrity": "sha512-wBuoj1BDpC6ZQ1B7DWQBYVLphPWkm8i9Y0/3YdHjHKHiohOJ1ws+3OccDWtH+PoC9DZD5WOTrJvNbWvjS6JWaA==" + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" } } } diff --git a/TEST_SERVER1/api/package.json b/TEST_SERVER1/api/package.json index ba0a368..389f14b 100644 --- a/TEST_SERVER1/api/package.json +++ b/TEST_SERVER1/api/package.json @@ -11,10 +11,12 @@ "author": "Adriano ", "license": "MIT", "dependencies": { + "bcrypt": "^5.1.0", "body-parser": "^1.20.1", "dotenv": "^16.0.3", "express": "^4.18.2", "fs-extra": "^11.1.0", + "mongoose": "^7.4.0", "mysql": "^2.18.1", "nodemon": "^2.0.20", "socket.io": "^4.5.4" From 417f9472633c204c12ae9831818ffab98c18fc20 Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 24 Jul 2023 17:29:41 -0300 Subject: [PATCH 02/19] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20para=20descriptog?= =?UTF-8?q?rafar=20hash?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TEST_SERVER1/api/app.js | 21 +++++++++++++++---- TEST_SERVER1/api/helpers/PassHash.js | 30 ++++++++++++++-------------- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/TEST_SERVER1/api/app.js b/TEST_SERVER1/api/app.js index c68f564..540f988 100644 --- a/TEST_SERVER1/api/app.js +++ b/TEST_SERVER1/api/app.js @@ -167,10 +167,23 @@ app.post('/api/session', async function (req, res) { lstPass = lstPass.split(',') let password = null - password = await lstPass.find( - async (pass) => - await bcrypt.compare(pass.trim(), db_credentials.db_conf.DB_PASS) - ) + // password = await lstPass.find( + // async (pass) => + // await bcrypt.compare(pass.trim(), db_credentials.db_conf.DB_PASS) + // ) + + for (let i = 0; i < lstPass.length; i++) { + const hasPass = await bcrypt.compare( + lstPass[i].trim(), + db_credentials.db_conf.DB_PASS + ) + + if (hasPass) { + password = lstPass[i].trim() + break + } + } + if (password) { db_credentials.db_conf.DB_PASS = password } else { diff --git a/TEST_SERVER1/api/helpers/PassHash.js b/TEST_SERVER1/api/helpers/PassHash.js index 7b15e55..81d1be1 100644 --- a/TEST_SERVER1/api/helpers/PassHash.js +++ b/TEST_SERVER1/api/helpers/PassHash.js @@ -1,20 +1,20 @@ const bcrypt = require('bcrypt') -const pass = async () => { - // create a password - const salt = await bcrypt.genSalt(12) - const passwordHash = await bcrypt.hash('strongpassword', salt) - console.log(passwordHash) -} -pass() - -// const passDec = async () => { -// const _pass = await bcrypt.compare( -// 'strongpassword', -// '$2b$12$R/bpS7b9FzdXlHAijmP.3.gJqgeUjwQVSuK6q.G0PZbb0wowCnrN.' -// ) -// console.log('_pass: ', _pass) +// const pass = async () => { +// // create a password +// const salt = await bcrypt.genSalt(12) +// const passwordHash = await bcrypt.hash('7901228899', salt) +// console.log(passwordHash) // } -// passDec() +// pass() + +const passDec = async () => { + const _pass = await bcrypt.compare( + 'strongpassword', + '$2b$12$PZ8N1jU77nnNUCCGyKTMNOi2QI7X/SgPsISVQfr.cQ/jgdx5Z7AqC' + ) + console.log('_pass: ', _pass) +} +passDec() console.log('process.cwd(): ', process.cwd()) From 4ee65ad3007ec25f52a3921b8e3d57397a879c20 Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 26 Jul 2023 17:24:10 -0300 Subject: [PATCH 03/19] modulo canpanha em desenvolvimento --- backend/src/controllers/TicketController.ts | 228 +++++++++--------- .../src/helpers/CheckContactOpenTickets.ts | 28 ++- .../helpers/whatsappQueueMatchingUserQueue.ts | 34 +++ .../TicketServices/CreateTicketService.ts | 70 +++--- .../FindOrCreateTicketService.ts | 54 +++-- .../TicketServices/UpdateTicketService.ts | 72 +++--- .../services/UserServices/ShowQueuesByUser.ts | 68 ++++-- .../WhatsappService/ListWhatsAppsNumber.ts | 42 ++-- 8 files changed, 339 insertions(+), 257 deletions(-) create mode 100644 backend/src/helpers/whatsappQueueMatchingUserQueue.ts diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index f19751d..2bc8b61 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -8,24 +8,22 @@ import ShowTicketService from "../services/TicketServices/ShowTicketService"; import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; import SendWhatsAppMessage from "../services/WbotServices/SendWhatsAppMessage"; import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; -import ShowStatusChatEndService from '../services/StatusChatEndService/ShowStatusChatEndService' +import ShowStatusChatEndService from "../services/StatusChatEndService/ShowStatusChatEndService"; import CreateSchedulingNotifyService from "../services/SchedulingNotifyServices/CreateSchedulingNotifyService"; import ListSchedulingNotifyContactService from "../services/SchedulingNotifyServices/ListSchedulingNotifyContactService"; -import { isScheduling } from "../helpers/CheckSchedulingReminderNotify" +import { isScheduling } from "../helpers/CheckSchedulingReminderNotify"; -import ptBR from 'date-fns/locale/pt-BR'; +import ptBR from "date-fns/locale/pt-BR"; import { splitDateTime } from "../helpers/SplitDateTime"; -import format from 'date-fns/format'; +import format from "date-fns/format"; import ListTicketsServiceCache from "../services/TicketServices/ListTicketServiceCache"; -import { searchTicketCache, loadTicketsCache, } from '../helpers/TicketCache' +import { searchTicketCache, loadTicketsCache } from "../helpers/TicketCache"; import { Op } from "sequelize"; - - type IndexQuery = { searchParam: string; pageNumber: string; @@ -35,7 +33,7 @@ type IndexQuery = { withUnreadMessages: string; queueIds: string; unlimited?: string; - searchParamContent?: string + searchParamContent?: string; }; interface TicketData { @@ -43,13 +41,12 @@ interface TicketData { status: string; queueId: number; userId: number; - whatsappId?: string | number - msg?: string, - transfer?: boolean | undefined, - fromMe?: boolean + whatsappId?: string | number; + msg?: string; + transfer?: boolean | undefined; + fromMe?: boolean; } - import ListStatusChatEndService from "../services/StatusChatEndService/ListStatusChatEndService"; import Ticket from "../models/Ticket"; import ShowUserServiceReport from "../services/UserServices/ShowUserServiceReport"; @@ -60,7 +57,6 @@ import ShowUserService from "../services/UserServices/ShowUserService"; import axios from "axios"; import User from "../models/User"; import CheckContactOpenTickets from "../helpers/CheckContactOpenTickets"; -import QueuesByUser from "../services/UserServices/ShowQueuesByUser"; import GetDefaultWhatsApp from "../helpers/GetDefaultWhatsApp"; import { getWbot } from "../libs/wbot"; import endPointQuery from "../helpers/old_EndPointQuery"; @@ -69,7 +65,6 @@ import BotIsOnQueue from "../helpers/BotIsOnQueue"; import { setMessageAsRead } from "../helpers/SetMessageAsRead"; export const index = async (req: Request, res: Response): Promise => { - const { pageNumber, status, @@ -82,7 +77,6 @@ export const index = async (req: Request, res: Response): Promise => { searchParamContent } = req.query as IndexQuery; - const userId = req.user.id; let queueIds: number[] = []; @@ -110,22 +104,23 @@ export const index = async (req: Request, res: Response): Promise => { export const store = async (req: Request, res: Response): Promise => { const { contactId, status, userId, msg, queueId }: TicketData = req.body; - const botInfo = await BotIsOnQueue('botqueue') + // const botInfo = await BotIsOnQueue("botqueue"); let ticket = await Ticket.findOne({ where: { [Op.or]: [ - { contactId, status: 'queueChoice' }, - { contactId, status: 'open', userId: botInfo.userIdBot } + { contactId, status: "queueChoice" } + // { contactId, status: "open", userId: botInfo.userIdBot } ] } }); if (ticket) { - await UpdateTicketService({ ticketData: { status: 'open', userId: userId, queueId }, ticketId: ticket.id }); - - } - else { + await UpdateTicketService({ + ticketData: { status: "open", userId: userId, queueId }, + ticketId: ticket.id + }); + } else { ticket = await CreateTicketService({ contactId, status, userId, queueId }); } @@ -134,8 +129,7 @@ export const store = async (req: Request, res: Response): Promise => { action: "update", ticket }); - // - + // // const ticket = await CreateTicketService({ contactId, status, userId }); @@ -148,58 +142,65 @@ export const store = async (req: Request, res: Response): Promise => { return res.status(200).json(ticket); }; - export const show = async (req: Request, res: Response): Promise => { const { ticketId } = req.params; const contact = await ShowTicketService(ticketId); - const { statusChatEnd, count, hasMore } = await ListStatusChatEndService({ searchParam: "", pageNumber: "1" }); + const { statusChatEnd, count, hasMore } = await ListStatusChatEndService({ + searchParam: "", + pageNumber: "1" + }); ////////////////// - const schedulesContact = await ListSchedulingNotifyContactService(contact.contact.number); + const schedulesContact = await ListSchedulingNotifyContactService( + contact.contact.number + ); ///////////////// - return res.status(200).json({ contact, statusChatEnd, schedulesContact }); }; export const count = async (req: Request, res: Response): Promise => { - // type indexQ = { status: string; date?: string; }; - const { status, date } = req.query as IndexQuery + const { status, date } = req.query as IndexQuery; const ticketCount = await CountTicketService(status, date); return res.status(200).json(ticketCount); }; - -export const update = async (req: Request, res: Response): Promise => { - - console.log('ENTROU NO UPDATE TICKET CONTROLLER') +export const update = async ( + req: Request, + res: Response +): Promise => { + console.log("ENTROU NO UPDATE TICKET CONTROLLER"); const { ticketId } = req.params; - const userOldInfo = await Ticket.findByPk(ticketId) + const userOldInfo = await Ticket.findByPk(ticketId); - let ticket2 = {} - - if (req.body['status'] === "closed") { + let ticket2 = {}; + if (req.body["status"] === "closed") { const { status, userId, schedulingNotifyData } = req.body; // lembrete - const scheduleData = JSON.parse(schedulingNotifyData) + const scheduleData = JSON.parse(schedulingNotifyData); - const statusChatEndName = await ShowStatusChatEndService(scheduleData.statusChatEndId) + const statusChatEndName = await ShowStatusChatEndService( + scheduleData.statusChatEndId + ); const { ticket } = await UpdateTicketService({ - ticketData: { 'status': status, 'userId': userId, 'statusChatEnd': statusChatEndName.name }, + ticketData: { + status: status, + userId: userId, + statusChatEnd: statusChatEndName.name + }, ticketId }); - if (scheduleData.farewellMessage) { const whatsapp = await ShowWhatsAppService(ticket.whatsappId); @@ -210,37 +211,33 @@ export const update = async (req: Request, res: Response): Promise => } } - // lembrete // agendamento - if (scheduleData.statusChatEndId === '2' || scheduleData.statusChatEndId === '3') { - - - if (isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime)) { - console.log('*** É AGENDAMENTO!') - } - else { - console.log('*** É LEMBRETE!') + if ( + scheduleData.statusChatEndId === "2" || + scheduleData.statusChatEndId === "3" + ) { + if ( + isScheduling(scheduleData.schedulingDate, scheduleData.schedulingTime) + ) { + console.log("*** É AGENDAMENTO!"); + } else { + console.log("*** É LEMBRETE!"); } - const schedulingNotifyCreate = await CreateSchedulingNotifyService( - { - ticketId: scheduleData.ticketId, - statusChatEndId: scheduleData.statusChatEndId, - schedulingDate: scheduleData.schedulingDate, - schedulingTime: scheduleData.schedulingTime, - message: scheduleData.message - } - ) + const schedulingNotifyCreate = await CreateSchedulingNotifyService({ + ticketId: scheduleData.ticketId, + statusChatEndId: scheduleData.statusChatEndId, + schedulingDate: scheduleData.schedulingDate, + schedulingTime: scheduleData.schedulingTime, + message: scheduleData.message + }); } - ticket2 = ticket - - } - else { - + ticket2 = ticket; + } else { // Para aparecer pendente para todos usuarios que estao na fila if (req.body.transfer) { - req.body.userId = null + req.body.userId = null; } let ticketData: TicketData = req.body; @@ -250,75 +247,75 @@ export const update = async (req: Request, res: Response): Promise => // return res.send() + if (1 == 1 + 1) { + } else { + if (ticketData.transfer) { + const defaultWhatsapp: any = await GetDefaultWhatsApp( + ticketData.userId + ); - // if (ticketData.transfer) { + const _ticket: any = await Ticket.findByPk(ticketId); - // const defaultWhatsapp: any = await GetDefaultWhatsApp(ticketData.userId); + if (defaultWhatsapp && ticketData.status != "open") { + await CheckContactOpenTickets( + _ticket.dataValues.contactId, + defaultWhatsapp.dataValues.id + ); + } - // const _ticket: any = await Ticket.findByPk(ticketId) - - // if (defaultWhatsapp && ticketData.status != 'open') { - - // await CheckContactOpenTickets(_ticket.dataValues.contactId, defaultWhatsapp.dataValues.id) - - // } - - // ticketData.whatsappId = defaultWhatsapp.dataValues.id - - // } - - console.log('--------> ticketData.status: ', ticketData.status, ' | ticketData.fromMe: ', ticketData.fromMe) + ticketData.whatsappId = defaultWhatsapp.dataValues.id; + } + } + console.log( + "--------> ticketData.status: ", + ticketData.status, + " | ticketData.fromMe: ", + ticketData.fromMe + ); const { ticket } = await UpdateTicketService({ ticketData, - ticketId, + ticketId }); - - if (ticketData.status == 'open' && !ticketData.fromMe) { - + if (ticketData.status == "open" && !ticketData.fromMe) { await setMessageAsRead(ticket); - } - console.log('ticket.unreadMessages: ', ticket.unreadMessages) + console.log("ticket.unreadMessages: ", ticket.unreadMessages); if (ticketData.userId) { - - const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - TicketEmiterSumOpenClosedByUser(ticketData.userId.toString(), dateToday.fullDate, dateToday.fullDate) - + const dateToday = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) + ); + TicketEmiterSumOpenClosedByUser( + ticketData.userId.toString(), + dateToday.fullDate, + dateToday.fullDate + ); } - ticket2 = ticket - + ticket2 = ticket; } - - - if (userOldInfo) { - - const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) + const dateToday = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) + ); if (userOldInfo.userId) { - - TicketEmiterSumOpenClosedByUser(userOldInfo.userId.toString(), dateToday.fullDate, dateToday.fullDate) - + TicketEmiterSumOpenClosedByUser( + userOldInfo.userId.toString(), + dateToday.fullDate, + dateToday.fullDate + ); } - } - - return res.status(200).json(ticket2); }; - - - - // export const update = async ( // req: Request, // res: Response @@ -341,7 +338,6 @@ export const update = async (req: Request, res: Response): Promise => // } // } - // return res.status(200).json(ticket); // }; @@ -354,13 +350,10 @@ export const remove = async ( const ticket = await DeleteTicketService(ticketId); const io = getIO(); - io.to(ticket.status) - .to(ticketId) - .to("notification") - .emit("ticket", { - action: "delete", - ticketId: +ticketId - }); + io.to(ticket.status).to(ticketId).to("notification").emit("ticket", { + action: "delete", + ticketId: +ticketId + }); return res.status(200).json({ message: "ticket deleted" }); }; @@ -371,4 +364,3 @@ export const remove = async ( // await endPointQuery(`${wbot_url}/api/sendSeen`, { number: `${ticket.contact.number}@${ticket.isGroup ? "g" : "c"}.us` }); // } - diff --git a/backend/src/helpers/CheckContactOpenTickets.ts b/backend/src/helpers/CheckContactOpenTickets.ts index 3437cce..4d2fd78 100644 --- a/backend/src/helpers/CheckContactOpenTickets.ts +++ b/backend/src/helpers/CheckContactOpenTickets.ts @@ -1,11 +1,31 @@ import { Op } from "sequelize"; import AppError from "../errors/AppError"; import Ticket from "../models/Ticket"; +import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; -const CheckContactOpenTickets = async (contactId: number): Promise => { - const ticket = await Ticket.findOne({ - where: { contactId, status: { [Op.or]: ["open", "pending"] } } - }); +const CheckContactOpenTickets = async ( + contactId: number, + whatsappId: number | string +): Promise => { + let ticket; + + if (1 == 1 + 1) { + ticket = await Ticket.findOne({ + where: { contactId, status: { [Op.or]: ["open", "pending"] } } + }); + } else { + let whats = await ListWhatsAppsNumber(whatsappId); + + ticket = await Ticket.findOne({ + where: { + [Op.and]: [ + { contactId: contactId }, + { whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } }, + { status: { [Op.or]: ["open", "pending"] } } + ] + } + }); + } if (ticket) { throw new AppError("ERR_OTHER_OPEN_TICKET"); diff --git a/backend/src/helpers/whatsappQueueMatchingUserQueue.ts b/backend/src/helpers/whatsappQueueMatchingUserQueue.ts new file mode 100644 index 0000000..1ed355c --- /dev/null +++ b/backend/src/helpers/whatsappQueueMatchingUserQueue.ts @@ -0,0 +1,34 @@ +import Whatsapp from "../models/Whatsapp"; +import ShowQueuesByUser from "../services/UserServices/ShowQueuesByUser"; +import ShowWhatsAppService from "../services/WhatsappService/ShowWhatsAppService"; + +async function whatsappQueueMatchingUserQueue( + userId: number, + whatsapp: Whatsapp, + userProfile: string = "user" +) { + const userQueues = await ShowQueuesByUser({ + profile: userProfile, + userId: userId + }); + + if (!userQueues || (userQueues && userQueues.length == 0)) return; + + // console.log('-----> userQueues: ', userQueues); + + let whats: any = await ShowWhatsAppService(whatsapp.id); + + if (!whats.queues || (whats.queues && whats.queues.length == 0)) return; + + const whatsappQueues = whats.queues.map((e: any) => e.dataValues.name); + + // console.log('-----> whatsappQueues: ', whatsappQueues); + + const matchingQueue = userQueues.find(queue => + whatsappQueues.includes(queue.name) + ); + + return matchingQueue; +} + +export default whatsappQueueMatchingUserQueue; diff --git a/backend/src/services/TicketServices/CreateTicketService.ts b/backend/src/services/TicketServices/CreateTicketService.ts index 376a90c..bfcd8fa 100644 --- a/backend/src/services/TicketServices/CreateTicketService.ts +++ b/backend/src/services/TicketServices/CreateTicketService.ts @@ -4,42 +4,50 @@ import GetDefaultWhatsApp from "../../helpers/GetDefaultWhatsApp"; import Ticket from "../../models/Ticket"; import ShowContactService from "../ContactServices/ShowContactService"; - import { getIO } from "../../libs/socket"; import ShowUserServiceReport from "../UserServices/ShowUserServiceReport"; -import format from 'date-fns/format'; -import ptBR from 'date-fns/locale/pt-BR'; +import format from "date-fns/format"; +import ptBR from "date-fns/locale/pt-BR"; import { splitDateTime } from "../../helpers/SplitDateTime"; import TicketEmiterSumOpenClosedByUser from "../../helpers/OnlineReporEmiterInfoByUser"; -import { createOrUpdateTicketCache } from '../../helpers/TicketCache' -let flatten = require('flat') - - +import { createOrUpdateTicketCache } from "../../helpers/TicketCache"; +import User from "../../models/User"; +import whatsappQueueMatchingUserQueue from "../../helpers/whatsappQueueMatchingUserQueue"; +let flatten = require("flat"); interface Request { contactId: number; status: string; - userId: number; + userId: number; queueId?: number | undefined; } const CreateTicketService = async ({ contactId, status, - userId, + userId, queueId = undefined }: Request): Promise => { - - - console.log('========> queueId: ', queueId) + console.log("========> queueId: ", queueId); try { + const defaultWhatsapp = await GetDefaultWhatsApp(userId); - const defaultWhatsapp = await GetDefaultWhatsApp(userId); + const user = await User.findByPk(userId, { raw: true }); - await CheckContactOpenTickets(contactId); + if (!queueId) { + const matchingQueue = await whatsappQueueMatchingUserQueue( + userId, + defaultWhatsapp, + user?.profile + ); + + queueId = matchingQueue ? matchingQueue.queueId : undefined; + } + + await CheckContactOpenTickets(contactId, defaultWhatsapp.id); const { isGroup } = await ShowContactService(contactId); @@ -59,27 +67,32 @@ const CreateTicketService = async ({ // console.log('CONTACT ticket.id: ', ticket.id) - - // TEST DEL + // TEST DEL try { - - let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data + let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data let ticket_obj = JSON.parse(jsonString); //to make plain json - delete ticket_obj['contact']['extraInfo'] + delete ticket_obj["contact"]["extraInfo"]; - ticket_obj = flatten(ticket_obj) - - await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj) + ticket_obj = flatten(ticket_obj); + await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj); } catch (error) { - console.log('There was an error on UpdateTicketService.ts on createTicketCache from user: ', error) + console.log( + "There was an error on UpdateTicketService.ts on createTicketCache from user: ", + error + ); } // + const dateToday = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) + ); - const dateToday = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - - TicketEmiterSumOpenClosedByUser(userId.toString(), dateToday.fullDate, dateToday.fullDate) + TicketEmiterSumOpenClosedByUser( + userId.toString(), + dateToday.fullDate, + dateToday.fullDate + ); const io = getIO(); io.emit("ticketStatus", { @@ -87,14 +100,11 @@ const CreateTicketService = async ({ ticketStatus: { ticketId: ticket.id, status: ticket.status } }); - return ticket; - } catch (error: any) { - console.error('===> Error on CreateTicketService.ts file: \n', error) + console.error("===> Error on CreateTicketService.ts file: \n", error); throw new AppError(error.message); } - }; export default CreateTicketService; diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts index 601a99f..c104bff 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketService.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -6,7 +6,7 @@ import Ticket from "../../models/Ticket"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; import ShowTicketService from "./ShowTicketService"; import AppError from "../../errors/AppError"; - +import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber"; const FindOrCreateTicketService = async ( contact: Contact, @@ -14,26 +14,37 @@ const FindOrCreateTicketService = async ( unreadMessages: number, groupContact?: Contact ): Promise => { - try { + let ticket; - let ticket = await Ticket.findOne({ - where: { - status: { - [Op.or]: ["open", "pending", "queueChoice"] - }, - contactId: groupContact ? groupContact.id : contact.id - } - }); + if (1 == 1 + 1) { + ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "queueChoice"] + }, + contactId: groupContact ? groupContact.id : contact.id + } + }); + } else { + let whats = await ListWhatsAppsNumber(whatsappId); + + ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "queueChoice"] + }, + contactId: groupContact ? groupContact.id : contact.id, + whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } + } + }); + } const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId); - //Habilitar esse caso queira usar o bot - // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false } - - + // const botInfo = await BotIsOnQueue('botqueue') + const botInfo = { isOnQueue: false }; if (ticket) { await ticket.update({ unreadMessages }); @@ -47,10 +58,7 @@ const FindOrCreateTicketService = async ( order: [["updatedAt", "DESC"]] }); - - if (ticket) { - await ticket.update({ status: "pending", userId: null, @@ -60,7 +68,6 @@ const FindOrCreateTicketService = async ( } if (!ticket && !groupContact) { - ticket = await Ticket.findOne({ where: { updatedAt: { @@ -78,7 +85,6 @@ const FindOrCreateTicketService = async ( }); if (ticket) { - await ticket.update({ status: "pending", userId: null, @@ -88,11 +94,10 @@ const FindOrCreateTicketService = async ( } if (!ticket) { - - let status = "pending" + let status = "pending"; if (queues.length > 1 && !botInfo.isOnQueue) { - status = "queueChoice" + status = "queueChoice"; } ticket = await Ticket.create({ @@ -114,9 +119,8 @@ const FindOrCreateTicketService = async ( ticket = await ShowTicketService(ticket.id); return ticket; - } catch (error: any) { - console.error('===> Error on FindOrCreateTicketService.ts file: \n', error) + console.error("===> Error on FindOrCreateTicketService.ts file: \n", error); throw new AppError(error.message); } }; diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts index eed34da..b77a324 100644 --- a/backend/src/services/TicketServices/UpdateTicketService.ts +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -6,25 +6,24 @@ import SendWhatsAppMessage from "../WbotServices/SendWhatsAppMessage"; import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; import ShowTicketService from "./ShowTicketService"; -import { createOrUpdateTicketCache } from '../../helpers/TicketCache' +import { createOrUpdateTicketCache } from "../../helpers/TicketCache"; import AppError from "../../errors/AppError"; import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; -var flatten = require('flat') - - +var flatten = require("flat"); interface TicketData { status?: string; userId?: number; queueId?: number; - statusChatEnd?: string; + statusChatEnd?: string; unreadMessages?: number; + whatsappId?: string | number; } interface Request { ticketData: TicketData; - ticketId: string | number; - msg?: string + ticketId: string | number; + msg?: string; } interface Response { @@ -35,13 +34,18 @@ interface Response { const UpdateTicketService = async ({ ticketData, - ticketId, - msg='' + ticketId, + msg = "" }: Request): Promise => { - try { - - const { status, userId, queueId, statusChatEnd, unreadMessages } = ticketData; + const { + status, + userId, + queueId, + statusChatEnd, + unreadMessages, + whatsappId + } = ticketData; const ticket = await ShowTicketService(ticketId); // await SetTicketMessagesAsRead(ticket); @@ -50,7 +54,7 @@ const UpdateTicketService = async ({ const oldUserId = ticket.user?.id; if (oldStatus === "closed") { - await CheckContactOpenTickets(ticket.contact.id); + await CheckContactOpenTickets(ticket.contact.id, ticket.whatsappId); } await ticket.update({ @@ -58,36 +62,35 @@ const UpdateTicketService = async ({ queueId, userId, unreadMessages, - statusChatEnd + statusChatEnd, + whatsappId }); await ticket.reload(); - if (msg.length > 0) { - + if (msg.length > 0) { setTimeout(async () => { - - sendWhatsAppMessageSocket(ticket, msg) - - }, 2000) + sendWhatsAppMessageSocket(ticket, msg); + }, 2000); } - // TEST DEL + // TEST DEL try { + // const { name, number } = await ShowContactService(ticket.contactId) - // const { name, number } = await ShowContactService(ticket.contactId) - - let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data + let jsonString = JSON.stringify(ticket); //convert to string to remove the sequelize specific meta data let ticket_obj = JSON.parse(jsonString); //to make plain json - delete ticket_obj['contact']['extraInfo'] - delete ticket_obj['user'] + delete ticket_obj["contact"]["extraInfo"]; + delete ticket_obj["user"]; - ticket_obj = flatten(ticket_obj) - - await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj) + ticket_obj = flatten(ticket_obj); + await createOrUpdateTicketCache(`ticket:${ticket.id}`, ticket_obj); } catch (error) { - console.log('There was an error on UpdateTicketService.ts on createTicketCache: ', error) + console.log( + "There was an error on UpdateTicketService.ts on createTicketCache: ", + error + ); } // @@ -100,7 +103,6 @@ const UpdateTicketService = async ({ }); } - io.to(ticket.status) .to("notification") .to(ticketId.toString()) @@ -109,20 +111,16 @@ const UpdateTicketService = async ({ ticket }); - io.emit("ticketStatus", { action: "update", ticketStatus: { ticketId: ticket.id, status: ticket.status } }); - return { ticket, oldStatus, oldUserId }; - } catch (error: any) { - console.error('===> Error on UpdateTicketService.ts file: \n', error) + console.error("===> Error on UpdateTicketService.ts file: \n", error); throw new AppError(error.message); } - }; -export default UpdateTicketService; \ No newline at end of file +export default UpdateTicketService; diff --git a/backend/src/services/UserServices/ShowQueuesByUser.ts b/backend/src/services/UserServices/ShowQueuesByUser.ts index 38d12f6..c401693 100644 --- a/backend/src/services/UserServices/ShowQueuesByUser.ts +++ b/backend/src/services/UserServices/ShowQueuesByUser.ts @@ -1,40 +1,62 @@ - -import { Sequelize, } from "sequelize"; +import { Sequelize } from "sequelize"; const dbConfig = require("../../config/database"); const sequelize = new Sequelize(dbConfig); -const { QueryTypes } = require('sequelize'); +const { QueryTypes } = require("sequelize"); interface Request { - profile: string; - userId?: string | number; + profile?: string; + userId?: string | number; } const QueuesByUser = async ({ profile, userId }: Request): Promise => { + let queueByUsersInfo: any = []; - let queueByUsersInfo = [] - - if (userId) { - // CONSULTANDO FILAS PELO ID DO USUARIO - queueByUsersInfo = await sequelize.query(`select UserQueues.userId, UserQueues.queueId, Users.name, + if (userId && profile) { + // CONSULTANDO FILAS PELO ID DO USUARIO + queueByUsersInfo = await sequelize.query( + `select UserQueues.userId, UserQueues.queueId, Users.name, Queues.name, Queues.color from UserQueues inner join Users inner join Queues on - UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.id = '${userId}' and Users.profile = '${profile}' order by userId, queueId;`, { type: QueryTypes.SELECT }); - - } else { - - // CONSULTANDO FILAS PELO USUARIO - queueByUsersInfo = await sequelize.query(`select UserQueues.userId, UserQueues.queueId, Users.name, + UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.id = '${userId}' and Users.profile = '${profile}' order by userId, queueId;`, + { type: QueryTypes.SELECT } + ); + } else if (profile) { + // CONSULTANDO FILAS PELO USUARIO + queueByUsersInfo = await sequelize.query( + `select UserQueues.userId, UserQueues.queueId, Users.name, Queues.name, Queues.color from UserQueues inner join Users inner join Queues on - UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.profile = '${profile}' order by userId, queueId;`, { type: QueryTypes.SELECT }); + UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.profile = '${profile}' order by userId, queueId;`, + { type: QueryTypes.SELECT } + ); + } else if (userId) { + queueByUsersInfo = await sequelize.query( + `select UserQueues.userId, UserQueues.queueId, Users.name, + Queues.name, Queues.color from UserQueues inner join Users inner join Queues on + UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.id = '${userId}' order by userId, queueId;`, + { type: QueryTypes.SELECT } + ); + } - } + // if (userId) { + // // CONSULTANDO FILAS PELO ID DO USUARIO + // queueByUsersInfo = await sequelize.query( + // `select UserQueues.userId, UserQueues.queueId, Users.name, + // Queues.name, Queues.color from UserQueues inner join Users inner join Queues on + // UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.id = '${userId}' and Users.profile = '${profile}' order by userId, queueId;`, + // { type: QueryTypes.SELECT } + // ); + // } else { + // // CONSULTANDO FILAS PELO USUARIO + // queueByUsersInfo = await sequelize.query( + // `select UserQueues.userId, UserQueues.queueId, Users.name, + // Queues.name, Queues.color from UserQueues inner join Users inner join Queues on + // UserQueues.queueId = Queues.id and UserQueues.userId = Users.id and Users.profile = '${profile}' order by userId, queueId;`, + // { type: QueryTypes.SELECT } + // ); + // } - return queueByUsersInfo; + return queueByUsersInfo; }; export default QueuesByUser; - - - - diff --git a/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts b/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts index 44b5589..3c8a072 100644 --- a/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts +++ b/backend/src/services/WhatsappService/ListWhatsAppsNumber.ts @@ -1,30 +1,32 @@ - import Whatsapp from "../../models/Whatsapp"; -const ListWhatsAppsNumber = async (whatsappId: string | number, status: string): Promise => { +const ListWhatsAppsNumber = async ( + whatsappId: string | number, + status?: string +): Promise => { + const whatsapp = await Whatsapp.findByPk(whatsappId, { raw: true }); - // const whatsapp = await Whatsapp.findOne({ - // raw: true, - // where: { id: whatsappId } - // }) - - const whatsapp = await Whatsapp.findByPk(whatsappId, { raw: true }) - - if (whatsapp) { - - const whatsapps = await Whatsapp.findAll({ - raw: true, - where: { number: whatsapp.number, status: status }, - attributes: ['id', 'number', 'status', 'isDefault', 'url'] - }); - - return { whatsapps, whatsapp }; + let whatsapps: any = []; + if (whatsapp) { + if (status) { + whatsapps = await Whatsapp.findAll({ + raw: true, + where: { number: whatsapp.number, status: status }, + attributes: ["id", "number", "status", "isDefault", "url"] + }); + } else { + whatsapps = await Whatsapp.findAll({ + raw: true, + where: { number: whatsapp.number }, + attributes: ["id", "number", "status", "isDefault", "url"] + }); } - return { whatsapps: [], whatsapp: null } - + return { whatsapps, whatsapp }; + } + return { whatsapps: [], whatsapp: null }; }; export default ListWhatsAppsNumber; From 1e0b8b9d29dfb0847125fa53ba79b92463ff7f74 Mon Sep 17 00:00:00 2001 From: adriano Date: Fri, 28 Jul 2023 09:25:13 -0300 Subject: [PATCH 04/19] =?UTF-8?q?finaliza=C3=A7=C3=A3o=20da=20implementa?= =?UTF-8?q?=C3=A7=C3=A3o=20para=20que=20um=20mesmo=20contato=20fale=20com?= =?UTF-8?q?=20whatsapps=20distintos=20da=20interface=20omnihit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/controllers/SettingController.ts | 3 + backend/src/controllers/TicketController.ts | 9 +- ...7191215-add-contact-multi-chat-settings.ts | 22 + .../src/helpers/CheckContactOpenTickets.ts | 11 +- backend/src/helpers/LoadSettings.ts | 27 + backend/src/helpers/WhaticketSettings.ts | 18 + backend/src/server.ts | 86 +-- .../FindOrCreateTicketService.ts | 21 +- .../WbotServices/wbotMessageListener.ts | 728 +++++++++--------- frontend/src/pages/Settings/index.js | 28 + 10 files changed, 532 insertions(+), 421 deletions(-) create mode 100644 backend/src/database/seeds/20230727191215-add-contact-multi-chat-settings.ts create mode 100644 backend/src/helpers/LoadSettings.ts create mode 100644 backend/src/helpers/WhaticketSettings.ts diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts index 7144a89..711af60 100644 --- a/backend/src/controllers/SettingController.ts +++ b/backend/src/controllers/SettingController.ts @@ -5,6 +5,7 @@ import AppError from "../errors/AppError"; import UpdateSettingService from "../services/SettingServices/UpdateSettingService"; import ListSettingsService from "../services/SettingServices/ListSettingsService"; +import loadSettings from "../helpers/LoadSettings"; export const index = async (req: Request, res: Response): Promise => { // if (req.user.profile !== "master") { @@ -31,6 +32,8 @@ export const update = async ( value }); + loadSettings(); + const io = getIO(); io.emit("settings", { action: "update", diff --git a/backend/src/controllers/TicketController.ts b/backend/src/controllers/TicketController.ts index 2bc8b61..defdaaf 100644 --- a/backend/src/controllers/TicketController.ts +++ b/backend/src/controllers/TicketController.ts @@ -63,6 +63,7 @@ import endPointQuery from "../helpers/old_EndPointQuery"; import Contact from "../models/Contact"; import BotIsOnQueue from "../helpers/BotIsOnQueue"; import { setMessageAsRead } from "../helpers/SetMessageAsRead"; +import { getSettingValue } from "../helpers/WhaticketSettings"; export const index = async (req: Request, res: Response): Promise => { const { @@ -242,13 +243,7 @@ export const update = async ( let ticketData: TicketData = req.body; - // console.log('ticketData: ', ticketData) - // console.log('ticketData.transfer', ticketData.transfer) - - // return res.send() - - if (1 == 1 + 1) { - } else { + if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { if (ticketData.transfer) { const defaultWhatsapp: any = await GetDefaultWhatsApp( ticketData.userId diff --git a/backend/src/database/seeds/20230727191215-add-contact-multi-chat-settings.ts b/backend/src/database/seeds/20230727191215-add-contact-multi-chat-settings.ts new file mode 100644 index 0000000..cdafb33 --- /dev/null +++ b/backend/src/database/seeds/20230727191215-add-contact-multi-chat-settings.ts @@ -0,0 +1,22 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "Settings", + [ + { + key: "oneContactChatWithManyWhats", + value: "enabled", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("Settings", {}); + } +}; diff --git a/backend/src/helpers/CheckContactOpenTickets.ts b/backend/src/helpers/CheckContactOpenTickets.ts index 4d2fd78..6c75ce4 100644 --- a/backend/src/helpers/CheckContactOpenTickets.ts +++ b/backend/src/helpers/CheckContactOpenTickets.ts @@ -2,6 +2,7 @@ import { Op } from "sequelize"; import AppError from "../errors/AppError"; import Ticket from "../models/Ticket"; import ListWhatsAppsNumber from "../services/WhatsappService/ListWhatsAppsNumber"; +import { getSettingValue } from "./WhaticketSettings"; const CheckContactOpenTickets = async ( contactId: number, @@ -9,11 +10,7 @@ const CheckContactOpenTickets = async ( ): Promise => { let ticket; - if (1 == 1 + 1) { - ticket = await Ticket.findOne({ - where: { contactId, status: { [Op.or]: ["open", "pending"] } } - }); - } else { + if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { let whats = await ListWhatsAppsNumber(whatsappId); ticket = await Ticket.findOne({ @@ -25,6 +22,10 @@ const CheckContactOpenTickets = async ( ] } }); + } else { + ticket = await Ticket.findOne({ + where: { contactId, status: { [Op.or]: ["open", "pending"] } } + }); } if (ticket) { diff --git a/backend/src/helpers/LoadSettings.ts b/backend/src/helpers/LoadSettings.ts new file mode 100644 index 0000000..14f531f --- /dev/null +++ b/backend/src/helpers/LoadSettings.ts @@ -0,0 +1,27 @@ +import Setting from "../models/Setting"; +import fs from "fs"; +import dir from "path"; +import os from "os"; + +async function loadSettings() { + const setting = await Setting.findAll({}); + + if (setting) { + let sett = setting.map((s: any) => { + return { key: s.key, value: s.value }; + }); + + try { + const keyFilename = dir.join(os.tmpdir(), `whaticket_settings.json`); + + const jsonSettings = JSON.stringify(sett, null, 2); + + fs.writeFileSync(keyFilename, jsonSettings); + console.log(`Settings saved to ${keyFilename}`); + } catch (err) { + console.error("Error saving Settings to file:", err); + } + } +} + +export default loadSettings; diff --git a/backend/src/helpers/WhaticketSettings.ts b/backend/src/helpers/WhaticketSettings.ts new file mode 100644 index 0000000..41a512a --- /dev/null +++ b/backend/src/helpers/WhaticketSettings.ts @@ -0,0 +1,18 @@ +import fs from "fs"; +import dir from "path"; +import os from "os"; + +export function getSettingValue(key: any) { + let value: any = {}; + + try { + const keyFilename = dir.join(os.tmpdir(), `whaticket_settings.json`); + const jsonData = fs.readFileSync(keyFilename, "utf8"); + const settings = JSON.parse(jsonData); + value = settings.find((s: any) => s.key === key); + } catch (err) { + console.error("Error reading or parsing data from file:", err); + } + + return value; +} diff --git a/backend/src/server.ts b/backend/src/server.ts index 2ab92c0..45082d5 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -11,15 +11,20 @@ import { loadContactsCache } from "./helpers/ContactsCache"; import { loadSchedulesCache } from "./helpers/SchedulingNotifyCache"; import { delRestoreControllFile } from "./helpers/RestoreControll"; -import "./helpers/SchedulingNotifySendMessage" +import "./helpers/SchedulingNotifySendMessage"; import axios from "axios"; -import os from 'os'; +import os from "os"; +import Setting from "./models/Setting"; + +import fs from "fs"; +import dir from "path"; +import { getSettingValue } from "./helpers/WhaticketSettings"; +import loadSettings from "./helpers/LoadSettings"; const server = app.listen(process.env.PORT, () => { logger.info(`Server started on port: ${process.env.PORT}`); }); - // if (global.gc) { // console.log(">> Starting Garbage Collector..."); // global.gc(); @@ -33,96 +38,83 @@ initIO(server); gracefulShutdown(server); (async () => { + console.log("os.tmpdir(): ", os.tmpdir()); - console.log('os.tmpdir(): ', os.tmpdir()) + loadSettings(); - let whatsapps: any = await Whatsapp.findAll({ attributes: ['id', 'url'] }) + let whatsapps: any = await Whatsapp.findAll({ attributes: ["id", "url"] }); // console.log('whatsapps: ', whatsapps) if (whatsapps && whatsapps.length > 0) { - for (let i = 0; i < whatsapps.length; i++) { - try { + console.log( + `API URL: ${whatsapps[i].dataValues.url}/api/connection/status` + ); - console.log(`API URL: ${whatsapps[i].dataValues.url}/api/connection/status`) + const response = await axios.get( + `${whatsapps[i].dataValues.url}/api/connection/status`, + {} + ); - const response = await axios.get(`${whatsapps[i].dataValues.url}/api/connection/status`, {}); - - console.log(`-------> Response: ${response.data.data}`) + console.log(`-------> Response: ${response.data.data}`); if (!response) { - throw new Error('Response null'); + throw new Error("Response null"); } - if (response.data.data && response.data.data == 'CONNECTED') { - await whatsapps[i].update({ status: 'CONNECTED' }); + if (response.data.data && response.data.data == "CONNECTED") { + await whatsapps[i].update({ status: "CONNECTED" }); } - } catch (error: any) { + await whatsapps[i].update({ status: "OPENING" }); - await whatsapps[i].update({ status: 'OPENING' }); - - console.log(`There was an error on try acess the api sessions ${whatsapps[i].dataValues.url}`) + console.log( + `There was an error on try acess the api sessions ${whatsapps[i].dataValues.url}` + ); } await new Promise(f => setTimeout(f, 100)); - } } - if (process.env.CACHE) { + const cacheLength = await cacheSize(); - const cacheLength = await cacheSize() - - console.log('cacheSize: ', cacheLength) + console.log("cacheSize: ", cacheLength); if (cacheLength == 0) { - console.log('Loading from cache...') - await flushCache() - await loadContactsCache() - await loadTicketsCache() + console.log("Loading from cache..."); + await flushCache(); + await loadContactsCache(); + await loadTicketsCache(); } - await loadSchedulesCache() + await loadSchedulesCache(); // await loadWhatsappCache() } - delRestoreControllFile() -})() + delRestoreControllFile(); +})(); setTimeout(async () => { - const io = getIO(); - console.log('Triggered socket!') + console.log("Triggered socket!"); - let users = await User.findAll({ raw: true, attributes: ["id"], }) + let users = await User.findAll({ raw: true, attributes: ["id"] }); if (users && users.length > 0) { - for (let i = 0; i < users.length; i++) { - io.emit("reload_page", { action: "update", userId: users[i].id }); - console.log('USER ID: ', users[i].id) + console.log("USER ID: ", users[i].id); await new Promise(f => setTimeout(f, 100)); - } } - - -}, 5000) - - - - - - - +}, 5000); diff --git a/backend/src/services/TicketServices/FindOrCreateTicketService.ts b/backend/src/services/TicketServices/FindOrCreateTicketService.ts index c104bff..e7d8bf9 100644 --- a/backend/src/services/TicketServices/FindOrCreateTicketService.ts +++ b/backend/src/services/TicketServices/FindOrCreateTicketService.ts @@ -7,6 +7,7 @@ import ShowWhatsAppService from "../WhatsappService/ShowWhatsAppService"; import ShowTicketService from "./ShowTicketService"; import AppError from "../../errors/AppError"; import ListWhatsAppsNumber from "../WhatsappService/ListWhatsAppsNumber"; +import { getSettingValue } from "../../helpers/WhaticketSettings"; const FindOrCreateTicketService = async ( contact: Contact, @@ -17,16 +18,7 @@ const FindOrCreateTicketService = async ( try { let ticket; - if (1 == 1 + 1) { - ticket = await Ticket.findOne({ - where: { - status: { - [Op.or]: ["open", "pending", "queueChoice"] - }, - contactId: groupContact ? groupContact.id : contact.id - } - }); - } else { + if (getSettingValue("oneContactChatWithManyWhats")?.value == "enabled") { let whats = await ListWhatsAppsNumber(whatsappId); ticket = await Ticket.findOne({ @@ -38,6 +30,15 @@ const FindOrCreateTicketService = async ( whatsappId: { [Op.in]: whats.whatsapps.map((w: any) => w.id) } } }); + } else { + ticket = await Ticket.findOne({ + where: { + status: { + [Op.or]: ["open", "pending", "queueChoice"] + }, + contactId: groupContact ? groupContact.id : contact.id + } + }); } const { queues, greetingMessage } = await ShowWhatsAppService(whatsappId); diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 053b625..8b1ef87 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -5,12 +5,10 @@ import * as Sentry from "@sentry/node"; import { copyFolder } from "../../helpers/CopyFolder"; import { removeDir } from "../../helpers/DeleteDirectory"; -import path from 'path'; +import path from "path"; import { format } from "date-fns"; -import ptBR from 'date-fns/locale/pt-BR'; - - +import ptBR from "date-fns/locale/pt-BR"; import { Contact as WbotContact, @@ -34,38 +32,44 @@ import UpdateTicketService from "../TicketServices/UpdateTicketService"; import { date } from "faker"; import ShowQueueService from "../QueueService/ShowQueueService"; -import ShowTicketMessage from "../TicketServices/ShowTicketMessage" -import BotIsOnQueue from "../../helpers/BotIsOnQueue" +import ShowTicketMessage from "../TicketServices/ShowTicketMessage"; +import BotIsOnQueue from "../../helpers/BotIsOnQueue"; import Queue from "../../models/Queue"; -import fs from 'fs'; +import fs from "fs"; import { StartWhatsAppSession } from "../../services/WbotServices/StartWhatsAppSession"; -import { removeWbot } from '../../libs/wbot' +import { removeWbot } from "../../libs/wbot"; import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; -// test del -import data_ura from './ura' -import msg_client_transfer from './ura_msg_transfer' +// test del +import data_ura from "./ura"; +import msg_client_transfer from "./ura_msg_transfer"; import final_message from "./ura_final_message"; import SendWhatsAppMessage from "./SendWhatsAppMessage"; import Whatsapp from "../../models/Whatsapp"; import { splitDateTime } from "../../helpers/SplitDateTime"; -// +// -import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' -import { insertMessageContactCache, getLastId } from '../../helpers/LastMessageIdByContactCache' +import { updateTicketCacheByTicketId } from "../../helpers/TicketCache"; +import { + insertMessageContactCache, + getLastId +} from "../../helpers/LastMessageIdByContactCache"; import autoRestore from "../../helpers/AutoRestore"; import { _restore } from "../../helpers/RestoreControll"; import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; -import { getWhatsappIds, setWhatsappId } from "../../helpers/WhatsappIdMultiSessionControl"; +import { + getWhatsappIds, + setWhatsappId +} from "../../helpers/WhatsappIdMultiSessionControl"; import AppError from "../../errors/AppError"; import { setMessageAsRead } from "../../helpers/SetMessageAsRead"; +import { getSettingValue } from "../../helpers/WhaticketSettings"; +import { Op } from "sequelize"; - -var lst: any[] = getWhatsappIds() - +var lst: any[] = getWhatsappIds(); interface Session extends Client { id?: number; @@ -113,7 +117,7 @@ const verifyMediaMessage = async ( ticket: Ticket, contact: Contact, media: any, - quotedMsg?: any, + quotedMsg?: any ): Promise => { // const quotedMsg = await verifyQuotedMessage(msg); @@ -123,12 +127,15 @@ const verifyMediaMessage = async ( throw new Error("ERR_WAPP_DOWNLOAD_MEDIA"); } - console.log('MEDIA.FILENAME: ', media.fileName, ' | msg.fromMe: ', msg.fromMe) + console.log( + "MEDIA.FILENAME: ", + media.fileName, + " | msg.fromMe: ", + msg.fromMe + ); if (!media.filename) { - - console.log('No file name -----------------------------------------') - + console.log("No file name -----------------------------------------"); const ext = media.mimetype.split("/")[1].split(";")[0]; media.filename = `${new Date().getTime()}.${ext}`; @@ -141,15 +148,13 @@ const verifyMediaMessage = async ( // "base64" // ); - console.log('FROM wbotMessageListener.ts media.filename: ', media.filename) - + console.log("FROM wbotMessageListener.ts media.filename: ", media.filename); await writeFileAsync( join(__dirname, "..", "..", "..", "..", "..", "public", media.filename), media.data, "base64" ); - } catch (err) { Sentry.captureException(err); logger.error(`There was an error: wbotMessageLitener.ts: ${err}`); @@ -178,11 +183,8 @@ const verifyMessage = async ( msg: WbotMessage, ticket: Ticket, contact: Contact, - quotedMsg?: any, + quotedMsg?: any ) => { - - - // const quotedMsg = await verifyQuotedMessage(msg); // const quotedMsg = await verifyQuotedMessage(msg); @@ -199,21 +201,17 @@ const verifyMessage = async ( // quotedMsgId: quotedMsg?.id }; - await ticket.update({ lastMessage: msg.body }); await CreateMessageService({ messageData }); }; - - const verifyQueue = async ( wbot: Session, msg: WbotMessage, ticket: Ticket, contact: Contact ) => { - const { queues, greetingMessage } = await ShowWhatsAppService(wbot.id!); /*if (queues.length === 1) { @@ -224,45 +222,53 @@ const verifyQueue = async ( return; }*/ - - let selectedOption = null; - let choosenQueue = null + let choosenQueue = null; //Habilitar esse caso queira usar o bot - // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 } + // const botInfo = await BotIsOnQueue('botqueue') + const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; if (botInfo.isOnQueue) { - choosenQueue = await ShowQueueService(botInfo.botQueueId); - - } - - else if (queues.length === 1) { + } else if (queues.length === 1) { selectedOption = 1; choosenQueue = queues[+selectedOption - 1]; - } - else { - + } else { selectedOption = msg.body; //////////////// EXTRAIR APENAS O NÚMERO /////////////////// - selectedOption = selectedOption.replace(/[^1-9]/g, '') + selectedOption = selectedOption.replace(/[^1-9]/g, ""); /////////////////////////////////// choosenQueue = queues[+selectedOption - 1]; } - - if (choosenQueue) { + // TEST DEL + // let _ticket = await Ticket.findOne({ + // where: { + // status: { + // [Op.or]: ["open", "pending", "queueChoice"] + // }, + // contactId: contact.id, + // queueId: choosenQueue.id + // } + // }); + + // if (_ticket) { + // await UpdateTicketService({ + // ticketData: { queueId: choosenQueue.id }, + // ticketId: ticket.id + // }); + + // return; + // } + // // Atualizando o status do ticket para mostrar notificação para o atendente da fila escolhida pelo usuário. De queueChoice para pending if (queues.length > 1 && !botInfo.isOnQueue) { - await ticket.update({ status: "pending" }); - } // @@ -271,48 +277,42 @@ const verifyQueue = async ( ticketId: ticket.id }); - - let botOptions = '' + let botOptions = ""; // O bot abre a mensagem na fila para atender o usuario if (botInfo.isOnQueue) { - await UpdateTicketService({ - ticketData: { status: 'open', userId: botInfo.userIdBot }, + ticketData: { status: "open", userId: botInfo.userIdBot }, ticketId: ticket.id }); - data_ura.forEach((s, index) => { botOptions += `*${index + 1}* - ${s.option}\n` }); + data_ura.forEach((s, index) => { + botOptions += `*${index + 1}* - ${s.option}\n`; + }); } // - let body = '' + let body = ""; if (botOptions.length > 0) { body = `\u200e${choosenQueue.greetingMessage}\n\n${botOptions}\n${final_message.msg}`; - } - else { + } else { body = `\u200e${choosenQueue.greetingMessage}`; } - // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); - // await verifyMessage(sentMessage, ticket, contact); + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // await verifyMessage(sentMessage, ticket, contact); - sendWhatsAppMessageSocket(ticket, body) - - } - else { - - - //test del transfere o atendimento se entrar na ura infinita + sendWhatsAppMessageSocket(ticket, body); + } else { + //test del transfere o atendimento se entrar na ura infinita let ticket_message = await ShowTicketMessage(ticket.id, false); if (ticket_message.length > 10) { - - await UpdateTicketService({ ticketData: { status: 'pending', queueId: queues[0].id }, ticketId: ticket.id }); - - } - else { - + await UpdateTicketService({ + ticketData: { status: "pending", queueId: queues[0].id }, + ticketId: ticket.id + }); + } else { let options = ""; queues.forEach((queue, index) => { @@ -323,24 +323,17 @@ const verifyQueue = async ( const debouncedSentMessage = debounce( async () => { - - // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); // verifyMessage(sentMessage, ticket, contact); - sendWhatsAppMessageSocket(ticket, body) - - + sendWhatsAppMessageSocket(ticket, body); }, 3000, ticket.id ); debouncedSentMessage(); - } - - - } }; @@ -360,36 +353,44 @@ const isValidMsg = (msg: WbotMessage): boolean => { return false; }; - const queuesOutBot = async (wbot: Session, botId: string | number) => { - const { queues, greetingMessage } = await ShowWhatsAppService(wbot.id!); - const indexQueue = queues.findIndex((q) => q.id == botId) + const indexQueue = queues.findIndex(q => q.id == botId); if (indexQueue != -1) { - queues.splice(indexQueue, 1) + queues.splice(indexQueue, 1); } - return { queues, greetingMessage } - -} - -const botTransferTicket = async (queues: Queue, ticket: Ticket, contact: Contact, wbot: Session) => { + return { queues, greetingMessage }; +}; +const botTransferTicket = async ( + queues: Queue, + ticket: Ticket, + contact: Contact, + wbot: Session +) => { await ticket.update({ userId: null }); - await UpdateTicketService({ ticketData: { status: 'pending', queueId: queues.id }, ticketId: ticket.id }); - -} - - -const botSendMessage = (ticket: Ticket, contact: Contact, wbot: Session, msg: string) => { + await UpdateTicketService({ + ticketData: { status: "pending", queueId: queues.id }, + ticketId: ticket.id + }); +}; +const botSendMessage = ( + ticket: Ticket, + contact: Contact, + wbot: Session, + msg: string +) => { const debouncedSentMessage = debounce( - async () => { - const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, `${msg}`); + const sentMessage = await wbot.sendMessage( + `${contact.number}@c.us`, + `${msg}` + ); verifyMessage(sentMessage, ticket, contact); }, 3000, @@ -397,69 +398,61 @@ const botSendMessage = (ticket: Ticket, contact: Contact, wbot: Session, msg: st ); debouncedSentMessage(); - -} +}; const _clear_lst = () => { + console.log("THE lst.length: ", lst.length); - console.log('THE lst.length: ', lst.length) + if (lst.length <= 199) return; - if (lst.length <= 199) return - - const chunk: any = Math.floor((lst.length / 2)) + const chunk: any = Math.floor(lst.length / 2); lst = lst.slice(chunk, chunk + lst.length); - let whatsappIdsSplited = lst.map((e) => `${e.id}`).toString() + let whatsappIdsSplited = lst.map(e => `${e.id}`).toString(); - setWhatsappId(whatsappIdsSplited, true) - -} - -const handleMessage = async ( - msg: any, - wbot: any -): Promise => { + setWhatsappId(whatsappIdsSplited, true); +}; +const handleMessage = async (msg: any, wbot: any): Promise => { if (!msg.fromMe) { + _clear_lst(); - _clear_lst() + let index = lst.findIndex((x: any) => x.id == msg.id.id); - let index = lst.findIndex((x: any) => x.id == msg.id.id) - - console.log('INDEX: ', index) + console.log("INDEX: ", index); if (index == -1) { - // console.log('-----------------> LST: ', lst):q - lst.push({ id: msg.id.id }) + lst.push({ id: msg.id.id }); - setWhatsappId(msg.id.id) + setWhatsappId(msg.id.id); + } else { + console.log("IGNORED ID: ", msg.id.id); - } - else { - console.log('IGNORED ID: ', msg.id.id) - - return + return; } // console.log('LIST OF ID MESSAGE lst: ', lst) - console.log('PASSOU.................................FROM: ', msg.from.split("@")[0], ' | ID: ', msg.id.id) + console.log( + "PASSOU.................................FROM: ", + msg.from.split("@")[0], + " | ID: ", + msg.id.id + ); } - if (!isValidMsg(msg)) { return; } try { - let msgContact: any = wbot.msgContact + let msgContact: any = wbot.msgContact; // let groupContact: Contact | undefined; if (msg.fromMe) { - // console.log('FROM ME: ', msg.fromMe, ' | /\u200e/.test(msg.body[0]: ', (/\u200e/.test(msg.body[0]))) // messages sent automatically by wbot have a special character in front of it @@ -479,14 +472,12 @@ const handleMessage = async ( // console.log('1 --------------> msgContat: ', JSON.parse(JSON.stringify(msgContact))) // console.log(' # msg.type: ', msg.type ) - } else { - // msgContact = await msg.getContact(); // console.log('2 --------------> msgContat: ', JSON.parse(JSON.stringify(msgContact))) - // + // console.log(`\n <<<<<<<<<< RECEIVING MESSAGE: Parcial msg and msgContact info: msgContact.name: ${msgContact.name} @@ -497,15 +488,14 @@ const handleMessage = async ( msg.body: ${msg.body} msg.type: ${msg.type} msg.from: ${msg.from} - msg.to: ${msg.to}\n`) - + msg.to: ${msg.to}\n`); } // const chat = await msg.getChat(); - const chat = wbot.chat + const chat = wbot.chat; // if(chat.isGroup){ - + // console.log('This message is from a Group and will be ignored!') // return // } @@ -524,8 +514,6 @@ const handleMessage = async ( // groupContact = await verifyContact(msgGroupContact); // } - - const whatsapp = await ShowWhatsAppService(wbot.id!); // const whatsapp = await ShowWhatsAppService(46); @@ -536,47 +524,55 @@ const handleMessage = async ( // console.log('----------> contact: ', JSON.parse(JSON.stringify(contact))) - - - if (unreadMessages === 0 && whatsapp.farewellMessage && whatsapp.farewellMessage === msg.body) return; + if ( + unreadMessages === 0 && + whatsapp.farewellMessage && + whatsapp.farewellMessage === msg.body + ) + return; const ticket = await FindOrCreateTicketService( contact, wbot.id!, - unreadMessages, + unreadMessages // groupContact ); - // + // // await updateTicketCacheByTicketId(ticket.id, {'contact.profilePicUrl': ticket.contact.profilePicUrl}) - // Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen - if (wbot.id != ticket.whatsappId) { + if (getSettingValue("oneContactChatWithManyWhats")?.value == "disabled") { + // Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen + if (wbot.id != ticket.whatsappId) { + // console.log('PARA RESPONDER PELO MEMOS WHATSAPP wbot.id: ', wbot.id, ' | wbot.status: ', wbot.status) + // console.log('WHATSAPP STATUS ticket.whatsappId: ', ticket.whatsappId) - // console.log('PARA RESPONDER PELO MEMOS WHATSAPP wbot.id: ', wbot.id, ' | wbot.status: ', wbot.status) - // console.log('WHATSAPP STATUS ticket.whatsappId: ', ticket.whatsappId) - - try { - await ticket.update({ whatsappId: wbot.id }); - } catch (error: any) { - console.error('===> Error on wbotMessageListener.ts into handleMessage fuction file: \n', error) - throw new AppError(error.message); + try { + await ticket.update({ whatsappId: wbot.id }); + } catch (error: any) { + console.error( + "===> Error on wbotMessageListener.ts into handleMessage fuction file: \n", + error + ); + throw new AppError(error.message); + } } - - - + // } - // if (msg.hasMedia) { - await verifyMediaMessage(msg, ticket, contact, wbot.media, wbot.quotedMsg); + await verifyMediaMessage( + msg, + ticket, + contact, + wbot.media, + wbot.quotedMsg + ); } else { - // console.log('>>>>>>> msg.fromMe: ',msg.fromMe ) await verifyMessage(msg, ticket, contact, wbot.quotedMsg); } - if ( !ticket.queue && !chat.isGroup && @@ -587,324 +583,352 @@ const handleMessage = async ( await verifyQueue(wbot, msg, ticket, contact); } - - // O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 } - - if (botInfo.isOnQueue && !msg.fromMe && ticket.userId == botInfo.userIdBot) { - - - if (msg.body === '0') { + const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; + if ( + botInfo.isOnQueue && + !msg.fromMe && + ticket.userId == botInfo.userIdBot + ) { + if (msg.body === "0") { const queue = await ShowQueueService(ticket.queue.id); const greetingMessage = `\u200e${queue.greetingMessage}`; let options = ""; - data_ura.forEach((s, index) => { options += `*${index + 1}* - ${s.option}\n` }); - - botSendMessage(ticket, contact, wbot, `${greetingMessage}\n\n${options}\n${final_message.msg}`) - - } - else { - + data_ura.forEach((s, index) => { + options += `*${index + 1}* - ${s.option}\n`; + }); + botSendMessage( + ticket, + contact, + wbot, + `${greetingMessage}\n\n${options}\n${final_message.msg}` + ); + } else { // Pega as ultimas 9 opções numericas digitadas pelo cliente em orde DESC // Consulta apenas mensagens do usuári + let lastOption = ""; - let lastOption = '' + let ura_length = data_ura.length; - let ura_length = data_ura.length + let indexAttendant = data_ura.findIndex(u => u.atendente); - let indexAttendant = data_ura.findIndex((u) => u.atendente) - - let opt_user_attendant = '-1' + let opt_user_attendant = "-1"; if (indexAttendant != -1) { - opt_user_attendant = data_ura[indexAttendant].id + opt_user_attendant = data_ura[indexAttendant].id; } - // + // - let ticket_message = await ShowTicketMessage(ticket.id, true, ura_length, `^[0-${ura_length}}]$`); + let ticket_message = await ShowTicketMessage( + ticket.id, + true, + ura_length, + `^[0-${ura_length}}]$` + ); if (ticket_message.length > 1) { + lastOption = ticket_message[1].body; - lastOption = ticket_message[1].body + const queuesWhatsGreetingMessage = await queuesOutBot( + wbot, + botInfo.botQueueId + ); - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues + const queues = queuesWhatsGreetingMessage.queues; if (queues.length > 1) { - - const index_opt_user_attendant = ticket_message.findIndex((q) => q.body == opt_user_attendant) - const index0 = ticket_message.findIndex((q) => q.body == '0') + const index_opt_user_attendant = ticket_message.findIndex( + q => q.body == opt_user_attendant + ); + const index0 = ticket_message.findIndex(q => q.body == "0"); if (index_opt_user_attendant != -1) { - if (index0 > -1 && index0 < index_opt_user_attendant) { - lastOption = '' - } - else { - lastOption = opt_user_attendant + lastOption = ""; + } else { + lastOption = opt_user_attendant; } } - } - } - - - - // + // // // È numero - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= data_ura.length)) { - - const indexUra = data_ura.findIndex((ura) => ura.id == msg.body.trim()) - - + if ( + !Number.isNaN(Number(msg.body.trim())) && + +msg.body >= 0 && + +msg.body <= data_ura.length + ) { + const indexUra = data_ura.findIndex(ura => ura.id == msg.body.trim()); if (indexUra != -1) { - - if (data_ura[indexUra].id != opt_user_attendant && lastOption != opt_user_attendant) { - - - - - + if ( + data_ura[indexUra].id != opt_user_attendant && + lastOption != opt_user_attendant + ) { // test del - let next = true + let next = true; - let indexAux = ticket_message.findIndex((e) => e.body == '0') + let indexAux = ticket_message.findIndex(e => e.body == "0"); - let listMessage = null + let listMessage = null; if (indexAux != -1) { - - listMessage = ticket_message.slice(0, indexAux) - } - else { - - listMessage = ticket_message - + listMessage = ticket_message.slice(0, indexAux); + } else { + listMessage = ticket_message; } - let id = '' - let subUra = null + let id = ""; + let subUra = null; if (listMessage.length > 1) { + id = listMessage[listMessage.length - 1].body; + subUra = data_ura.filter(e => e.id == id)[0]; - id = listMessage[listMessage.length - 1].body - subUra = data_ura.filter((e) => e.id == id)[0] - - if (subUra && (!subUra.subOptions || subUra.subOptions.length == 0)) { - - listMessage.pop() - + if ( + subUra && + (!subUra.subOptions || subUra.subOptions.length == 0) + ) { + listMessage.pop(); } - } - if (listMessage.length > 1) { - - id = listMessage[listMessage.length - 1].body - subUra = data_ura.filter((e) => e.id == id)[0] + id = listMessage[listMessage.length - 1].body; + subUra = data_ura.filter(e => e.id == id)[0]; if (subUra.subOptions && subUra.subOptions.length > 0) { - - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= subUra.subOptions?.length) && subUra.subOptions) { - - + if ( + !Number.isNaN(Number(msg.body.trim())) && + +msg.body >= 0 && + +msg.body <= subUra.subOptions?.length && + subUra.subOptions + ) { if (subUra.subOptions[+msg.body - 1].responseToClient) { - - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\n${subUra.subOptions[+msg.body - 1].responseToClient}`) - - } - else { - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\n${subUra.subOptions[+msg.body - 1].subOpt}`) + botSendMessage( + ticket, + contact, + wbot, + `*${subUra.option}*\n\n${ + subUra.subOptions[+msg.body - 1].responseToClient + }` + ); + } else { + botSendMessage( + ticket, + contact, + wbot, + `*${subUra.option}*\n\n${ + subUra.subOptions[+msg.body - 1].subOpt + }` + ); } - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) + const queuesWhatsGreetingMessage = await queuesOutBot( + wbot, + botInfo.botQueueId + ); - const queues = queuesWhatsGreetingMessage.queues + const queues = queuesWhatsGreetingMessage.queues; if (queues.length > 0) { - await botTransferTicket(queues[0], ticket, contact, wbot) + await botTransferTicket(queues[0], ticket, contact, wbot); + } else { + console.log("NO QUEUE!"); } - else { - console.log('NO QUEUE!') - } - - } - else { - + } else { let options = ""; - let subOptions: any[] = subUra.subOptions + let subOptions: any[] = subUra.subOptions; - subOptions?.forEach((s, index) => { options += `*${index + 1}* - ${s.subOpt}\n` }); - - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\nDigite um número válido disponível no menu de opções de atendimento abaixo: \n${options}\n\n*0* - Voltar ao menu principal`) + subOptions?.forEach((s, index) => { + options += `*${index + 1}* - ${s.subOpt}\n`; + }); + botSendMessage( + ticket, + contact, + wbot, + `*${subUra.option}*\n\nDigite um número válido disponível no menu de opções de atendimento abaixo: \n${options}\n\n*0* - Voltar ao menu principal` + ); } - next = false - + next = false; } - } - // if (next) { - if (data_ura[indexUra].subOptions && data_ura[indexUra].subOptions.length > 0) { - + if ( + data_ura[indexUra].subOptions && + data_ura[indexUra].subOptions.length > 0 + ) { let options = ""; - let option = data_ura[indexUra].option - let subOptions: any[] = data_ura[indexUra].subOptions - let description = data_ura[indexUra].description + let option = data_ura[indexUra].option; + let subOptions: any[] = data_ura[indexUra].subOptions; + let description = data_ura[indexUra].description; - subOptions?.forEach((s, index) => { options += `*${index + 1}* - ${s.subOpt}\n` }); + subOptions?.forEach((s, index) => { + options += `*${index + 1}* - ${s.subOpt}\n`; + }); - const body = `\u200e${description}:\n${options}` - - botSendMessage(ticket, contact, wbot, `*${option}*\n\n${body}\n\n *0* - Voltar ao menu principal`) - - } - else { + const body = `\u200e${description}:\n${options}`; + botSendMessage( + ticket, + contact, + wbot, + `*${option}*\n\n${body}\n\n *0* - Voltar ao menu principal` + ); + } else { //test del deletar isso (Usar somente na hit) if (data_ura[indexUra].closeChat) { - - const { ticket: res } = await UpdateTicketService({ - ticketData: { 'status': 'closed', 'userId': botInfo.userIdBot }, ticketId: ticket.id + ticketData: { + status: "closed", + userId: botInfo.userIdBot + }, + ticketId: ticket.id }); /////////////////////////////// - const whatsapp = await ShowWhatsAppService(ticket.whatsappId); + const whatsapp = await ShowWhatsAppService( + ticket.whatsappId + ); const { farewellMessage } = whatsapp; if (farewellMessage) { - await SendWhatsAppMessage({ body: farewellMessage, ticket: res }); + await SendWhatsAppMessage({ + body: farewellMessage, + ticket: res + }); } /////////////////////////////// - - } - else { - botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) + } else { + botSendMessage( + ticket, + contact, + wbot, + `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal` + ); } // - - // botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) - + // botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) } } + } else if (data_ura[indexUra].id == opt_user_attendant) { + const queuesWhatsGreetingMessage = await queuesOutBot( + wbot, + botInfo.botQueueId + ); - } - else if (data_ura[indexUra].id == opt_user_attendant) { - - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues + const queues = queuesWhatsGreetingMessage.queues; // Se fila for maior que 1 exibi as opções fila para atendimento humano if (queues.length > 1) { - let options = ""; queues.forEach((queue, index) => { - options += `*${index + 1}* - ${queue.name}\n`; - }); const body = `\u200eSelecione uma das opções de atendimento abaixo:\n${options}`; - botSendMessage(ticket, contact, wbot, body) - + botSendMessage(ticket, contact, wbot, body); } // Para situações onde há apenas uma fila com exclusão da fila do bot, já direciona o cliente para essa fila de atendimento humano else if (queues.length == 1) { + await botTransferTicket(queues[0], ticket, contact, wbot); - await botTransferTicket(queues[0], ticket, contact, wbot) - - botSendMessage(ticket, contact, wbot, `${msg_client_transfer.msg}`) - + botSendMessage( + ticket, + contact, + wbot, + `${msg_client_transfer.msg}` + ); } - } - else if (lastOption == opt_user_attendant) { + } else if (lastOption == opt_user_attendant) { + const queuesWhatsGreetingMessage = await queuesOutBot( + wbot, + botInfo.botQueueId + ); - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues + const queues = queuesWhatsGreetingMessage.queues; // É numero - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= queues.length)) { - - await botTransferTicket(queues[+msg.body - 1], ticket, contact, wbot) - - botSendMessage(ticket, contact, wbot, `${msg_client_transfer.msg}`) - } - else { - - botSendMessage(ticket, contact, wbot, `Digite um número válido disponível no menu de opções de atendimento\n\n*0* - Voltar ao menu principal`) + if ( + !Number.isNaN(Number(msg.body.trim())) && + +msg.body >= 0 && + +msg.body <= queues.length + ) { + await botTransferTicket( + queues[+msg.body - 1], + ticket, + contact, + wbot + ); + botSendMessage( + ticket, + contact, + wbot, + `${msg_client_transfer.msg}` + ); + } else { + botSendMessage( + ticket, + contact, + wbot, + `Digite um número válido disponível no menu de opções de atendimento\n\n*0* - Voltar ao menu principal` + ); } } - - } - - } - else { - + } else { // É numero if (!Number.isNaN(Number(msg.body.trim()))) { - - botSendMessage(ticket, contact, wbot, `Opção numérica inválida!\nDigite um dos números mostrados no menu de opções\n\n*0* - Voltar ao menu principal`) - + botSendMessage( + ticket, + contact, + wbot, + `Opção numérica inválida!\nDigite um dos números mostrados no menu de opções\n\n*0* - Voltar ao menu principal` + ); + } else { + botSendMessage( + ticket, + contact, + wbot, + `Digite um número válido disponível no menu de opções\n\n*0* - Voltar ao menu principal` + ); } - else { - - botSendMessage(ticket, contact, wbot, `Digite um número válido disponível no menu de opções\n\n*0* - Voltar ao menu principal`) - - } - } - } - - - } - - - if (msg && !msg.fromMe && ticket.status == 'pending') { - - await setMessageAsRead(ticket) - } + if (msg && !msg.fromMe && ticket.status == "pending") { + await setMessageAsRead(ticket); + } } catch (err) { Sentry.captureException(err); - logger.error(`Error handling whatsapp message: Err: ${err}`); + logger.error(`Error handling whatsapp message: Err: ${err}`); } }; const handleMsgAck = async (msg_id: any, ack: any) => { - await new Promise(r => setTimeout(r, 4000)); const io = getIO(); @@ -921,16 +945,17 @@ const handleMsgAck = async (msg_id: any, ack: any) => { ] }); if (!messageToUpdate) { - console.log(`Not found the MESSAGE ID ${msg_id}to change the ACK into the Message table`) + console.log( + `Not found the MESSAGE ID ${msg_id}to change the ACK into the Message table` + ); return; } await messageToUpdate.update({ ack }); - + io.to(messageToUpdate.ticketId.toString()).emit("appMessage", { action: "update", message: messageToUpdate }); - } catch (err) { Sentry.captureException(err); logger.error(`Error handling message ack. Err: ${err}`); @@ -938,7 +963,6 @@ const handleMsgAck = async (msg_id: any, ack: any) => { }; const wbotMessageListener = (wbot: Session): void => { - wbot.on("message_create", async msg => { handleMessage(msg, wbot); }); diff --git a/frontend/src/pages/Settings/index.js b/frontend/src/pages/Settings/index.js index ab79873..459e11d 100644 --- a/frontend/src/pages/Settings/index.js +++ b/frontend/src/pages/Settings/index.js @@ -198,6 +198,34 @@ const Settings = () => { + +
+ + + + Contato conversar com whatsapps distintos no omnihit + + + + + +
)} /> From ff0d2c3630dc7c562f947e1fc658fe7d7a40b128 Mon Sep 17 00:00:00 2001 From: adriano Date: Fri, 4 Aug 2023 16:16:19 -0300 Subject: [PATCH 05/19] updante do modulo campanha em andamento --- .../src/components/CampaignModal/index.js | 346 +++++++++ frontend/src/layout/MainListItems.js | 138 ++-- frontend/src/pages/Campaign/index.js | 696 ++++++++++++++++++ frontend/src/pages/Contacts/index.js | 292 ++++---- frontend/src/routes/index.js | 76 +- 5 files changed, 1316 insertions(+), 232 deletions(-) create mode 100644 frontend/src/components/CampaignModal/index.js create mode 100644 frontend/src/pages/Campaign/index.js diff --git a/frontend/src/components/CampaignModal/index.js b/frontend/src/components/CampaignModal/index.js new file mode 100644 index 0000000..ba15420 --- /dev/null +++ b/frontend/src/components/CampaignModal/index.js @@ -0,0 +1,346 @@ +import React, { useState, useEffect, useContext, createContext } from 'react' +import * as Yup from 'yup' +import { Formik, Form, Field } from 'formik' +import { toast } from 'react-toastify' + +import { makeStyles } from '@material-ui/core/styles' +import { green } from '@material-ui/core/colors' + +import { AuthContext } from '../../context/Auth/AuthContext' +import { Can } from '../../components/Can' + +import apiBroker from '../../services/apiBroker' + +import Select from "@material-ui/core/Select" +import MenuItem from "@material-ui/core/MenuItem"; + +import SelectField from "../../components/Report/SelectField" + +import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext"; + +import { + Dialog, + DialogContent, + DialogTitle, + Button, + DialogActions, + CircularProgress, + TextField, + Switch, + FormControlLabel, +} from '@material-ui/core' + +import api from '../../services/api' +import { i18n } from '../../translate/i18n' +import toastError from '../../errors/toastError' +import QueueSelect from '../QueueSelect' + +const useStyles = makeStyles((theme) => ({ + root: { + display: 'flex', + flexWrap: 'wrap', + }, + + multFieldLine: { + display: 'flex', + '& > *:not(:last-child)': { + marginRight: theme.spacing(1), + }, + }, + + btnWrapper: { + position: 'relative', + }, + + buttonProgress: { + color: green[500], + position: 'absolute', + top: '50%', + left: '50%', + marginTop: -12, + marginLeft: -12, + }, +})) + +const SessionSchema = Yup.object().shape({ + name: Yup.string() + .min(2, 'Too Short!') + .max(100, 'Too Long!') + .required('Required'), +}) + +const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { + const classes = useStyles() + const initialState = { + name: '', + message: '', + whatsapp_sender: '', + csv_original_file_name: '', + } + + const { user } = useContext(AuthContext) + + const { whatsApps } = useContext(WhatsAppsContext); + + console.log('------------> whatsApps: ', whatsApps) + + const [campaign, setCampaign] = useState(initialState) + // const [selectedQueueIds, setSelectedQueueIds] = useState([]) + const [file, setFile] = useState() + + const [selectedNumber, setSelectedNumber] = useState(''); + + const [itemHover, setItemHover] = useState(-1) + + useEffect(() => { + console.log('selectedNumber: ', selectedNumber) + }, [selectedNumber]) + + + + useEffect(() => { + const fetchSession = async () => { + if (!campaignId) return + + try { + + const { data } = await apiBroker.get('/campaign', { + params: { + adminId: user.id, + baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, + identifier: 'campaign', + id: campaignId + } + }) + + setCampaign(data.campaign) + setSelectedNumber(data.campaign.whatsapp_sender) + + } catch (err) { + toastError(err) + } + } + fetchSession() + }, [campaignId]) + + const handleSaveCampaign = async (values) => { + let response = null + + const formData = new FormData() + formData.append('adminId', user.id) + formData.append('baseURL', process.env.REACT_APP_BACKEND_URL_PRIVATE) + formData.append('frontURL', process.env.REACT_APP_FRONTEND_URL) + formData.append('identifier', 'campaign') + formData.append('file', file) + formData.append('name', values.name) + formData.append('whatsapp_sender', selectedNumber) + formData.append('message', values.message) + formData.append('csv_original_file_name', file?.name) + + + const config = { + headers: { + 'content-type': 'multipart/form-data', + }, + } + + try { + if (campaignId) { + + response = await apiBroker.patch(`/campaign/${campaignId}`, + formData, + config + ) + toast.success('Campanha atualizada com sucesso!') + + } else { + + response = await apiBroker.post('/campaign', + formData, + config + ) + toast.success('Campanha criada com sucesso!') + } + + dispatch({ type: "UPDATE_CAMPAIGNS", payload: response.data.campaign }) + + handleClose() + + } catch (err) { + toastError(err) + } + } + + const handleClose = () => { + onClose() + setCampaign(initialState) + setSelectedNumber('') + } + + async function handleChange(event) { + try { + if (event.target.files[0].size > 1024 * 1024 * 4) { + alert('Arquivo não pode ser maior que 4 MB!') + return + } + + console.log('event.target.files[0]: ', event.target.files[0]) + setFile(event.target.files[0]) + + } catch (err) { + toastError(err) + } + } + + return ( +
+ + + {campaignId ? 'Editar campanha' : 'Adicionar campanha'} + + { + setTimeout(() => { + handleSaveCampaign(values) + actions.setSubmitting(false) + }, 400) + }} + > + {({ values, touched, errors, isSubmitting }) => ( + +
+ + ( + <> +
+
+ + + +
+ +
+ +
+
+ + )} + /> + +
+ +
+ +
+ + + + +

{file?.name || campaign?.csv_original_file_name}

+
+
+ + + + +
+ )} +
+
+
+ ) +} + +export default React.memo(CampaignModal) diff --git a/frontend/src/layout/MainListItems.js b/frontend/src/layout/MainListItems.js index 1455c45..0795b9a 100644 --- a/frontend/src/layout/MainListItems.js +++ b/frontend/src/layout/MainListItems.js @@ -1,40 +1,42 @@ -import React, { useContext, useEffect, useState } from "react"; -import { Link as RouterLink } from "react-router-dom"; +import React, { useContext, useEffect, useState } from 'react' +import { Link as RouterLink } from 'react-router-dom' -import ListItem from "@material-ui/core/ListItem"; -import ListItemIcon from "@material-ui/core/ListItemIcon"; -import ListItemText from "@material-ui/core/ListItemText"; -import ListSubheader from "@material-ui/core/ListSubheader"; -import Divider from "@material-ui/core/Divider"; -import { Badge } from "@material-ui/core"; -import DashboardOutlinedIcon from "@material-ui/icons/DashboardOutlined"; +import ListItem from '@material-ui/core/ListItem' +import ListItemIcon from '@material-ui/core/ListItemIcon' +import ListItemText from '@material-ui/core/ListItemText' +import ListSubheader from '@material-ui/core/ListSubheader' +import Divider from '@material-ui/core/Divider' +import { Badge } from '@material-ui/core' +import DashboardOutlinedIcon from '@material-ui/icons/DashboardOutlined' -import ReportOutlinedIcon from "@material-ui/icons/ReportOutlined"; -import SendOutlined from "@material-ui/icons/SendOutlined"; +import ReportOutlinedIcon from '@material-ui/icons/ReportOutlined' +import SendOutlined from '@material-ui/icons/SendOutlined' //import ReportOutlined from "@bit/mui-org.material-ui-icons.report-outlined"; +import WhatsAppIcon from '@material-ui/icons/WhatsApp' +import SyncAltIcon from '@material-ui/icons/SyncAlt' +import SettingsOutlinedIcon from '@material-ui/icons/SettingsOutlined' +import PeopleAltOutlinedIcon from '@material-ui/icons/PeopleAltOutlined' +import ContactPhoneOutlinedIcon from '@material-ui/icons/ContactPhoneOutlined' +import AccountTreeOutlinedIcon from '@material-ui/icons/AccountTreeOutlined' +import QuestionAnswerOutlinedIcon from '@material-ui/icons/QuestionAnswerOutlined' -import WhatsAppIcon from "@material-ui/icons/WhatsApp"; -import SyncAltIcon from "@material-ui/icons/SyncAlt"; -import SettingsOutlinedIcon from "@material-ui/icons/SettingsOutlined"; -import PeopleAltOutlinedIcon from "@material-ui/icons/PeopleAltOutlined"; -import ContactPhoneOutlinedIcon from "@material-ui/icons/ContactPhoneOutlined"; -import AccountTreeOutlinedIcon from "@material-ui/icons/AccountTreeOutlined"; -import QuestionAnswerOutlinedIcon from "@material-ui/icons/QuestionAnswerOutlined"; - -import { i18n } from "../translate/i18n"; -import { WhatsAppsContext } from "../context/WhatsApp/WhatsAppsContext"; -import { AuthContext } from "../context/Auth/AuthContext"; -import { Can } from "../components/Can"; +import { i18n } from '../translate/i18n' +import { WhatsAppsContext } from '../context/WhatsApp/WhatsAppsContext' +import { AuthContext } from '../context/Auth/AuthContext' +import { Can } from '../components/Can' function ListItemLink(props) { - const { icon, primary, to, className } = props; + const { icon, primary, to, className } = props const renderLink = React.useMemo( - () => React.forwardRef((itemProps, ref) => ), + () => + React.forwardRef((itemProps, ref) => ( + + )), [to] - ); + ) return (
  • @@ -43,55 +45,59 @@ function ListItemLink(props) {
  • - ); + ) } const MainListItems = (props) => { - const { setDrawerOpen } = props; - const { whatsApps } = useContext(WhatsAppsContext); - const { user } = useContext(AuthContext); - const [connectionWarning, setConnectionWarning] = useState(false); + const { setDrawerOpen } = props + const { whatsApps } = useContext(WhatsAppsContext) + const { user } = useContext(AuthContext) + const [connectionWarning, setConnectionWarning] = useState(false) useEffect(() => { const delayDebounceFn = setTimeout(() => { if (whatsApps.length > 0) { const offlineWhats = whatsApps.filter((whats) => { return ( - whats.status === "qrcode" || - whats.status === "PAIRING" || - whats.status === "DISCONNECTED" || - whats.status === "TIMEOUT" || - whats.status === "OPENING" - ); - }); + whats.status === 'qrcode' || + whats.status === 'PAIRING' || + whats.status === 'DISCONNECTED' || + whats.status === 'TIMEOUT' || + whats.status === 'OPENING' + ) + }) if (offlineWhats.length > 0) { - setConnectionWarning(true); + setConnectionWarning(true) } else { - setConnectionWarning(false); + setConnectionWarning(false) } } - }, 2000); - return () => clearTimeout(delayDebounceFn); - }, [whatsApps]); + }, 2000) + return () => clearTimeout(delayDebounceFn) + }, [whatsApps]) return ( //Solicitado pelo Adriano: Click no LinkItem e fechar o menu!
    setDrawerOpen(false)}> } /> } /> - } /> + } + /> } /> { yes={() => ( <> - {i18n.t("mainDrawer.listItems.administration")} + + {i18n.t('mainDrawer.listItems.administration')} + } /> } /> + } /> - } /> + } + /> - } /> + } + /> + + } + /> { yes={() => ( } /> )} @@ -141,7 +163,7 @@ const MainListItems = (props) => { )} />
    - ); -}; + ) +} -export default MainListItems; +export default MainListItems diff --git a/frontend/src/pages/Campaign/index.js b/frontend/src/pages/Campaign/index.js new file mode 100644 index 0000000..54e5e42 --- /dev/null +++ b/frontend/src/pages/Campaign/index.js @@ -0,0 +1,696 @@ +import React, { useState, useCallback, useEffect, useReducer, useContext } from 'react' +import { toast } from 'react-toastify' +import { format, parseISO } from 'date-fns' + +import openSocket from 'socket.io-client' + +import { makeStyles } from '@material-ui/core/styles' +import { green } from '@material-ui/core/colors' +import { + Button, + TableBody, + TableRow, + TableCell, + IconButton, + Table, + TableHead, + Paper, + Tooltip, + Typography, + CircularProgress, +} from '@material-ui/core' +import { + Edit, + CheckCircle, + SignalCellularConnectedNoInternet2Bar, + SignalCellularConnectedNoInternet0Bar, + SignalCellular4Bar, + CropFree, + DeleteOutline, + // Restore +} from '@material-ui/icons' + +import MainContainer from '../../components/MainContainer' +import MainHeader from '../../components/MainHeader' +import MainHeaderButtonsWrapper from '../../components/MainHeaderButtonsWrapper' +import Title from '../../components/Title' +import TableRowSkeleton from '../../components/TableRowSkeleton' + +import api from '../../services/api' +import CampaignModal from '../../components/CampaignModal' +import ConfirmationModal from '../../components/ConfirmationModal' +import QrcodeModal from '../../components/QrcodeModal' +import { i18n } from '../../translate/i18n' +// import { WhatsAppsContext } from '../../context/WhatsApp/WhatsAppsContext' +import toastError from '../../errors/toastError' + +//-------- +import { AuthContext } from '../../context/Auth/AuthContext' +import { Can } from '../../components/Can' + +import apiBroker from '../../services/apiBroker' + + + + +const reducer = (state, action) => { + + + if (action.type === "LOAD_CAMPAIGNS") { + + const campaigns = action.payload + return [...state, ...campaigns] + } + if (action.type === "UPDATE_CAMPAIGNS") { + + console.log('STATE: ', state) + + const campaign = action.payload + const campaignIndex = state.findIndex((c) => c.id === campaign.id) + + if (campaignIndex !== -1) { + state[campaignIndex] = campaign + return [...state] + } else { + return [campaign, ...state] + } + } + if (action.type === "DELETE_CAMPAIGN") { + const campaignId = action.payload + + const campaignIndex = state.findIndex((c) => c.id === campaignId) + if (campaignIndex !== -1) { + state.splice(campaignIndex, 1) + } + return [...state] + } + + if (action.type === "RESET") { + return [] + } +} + +const useStyles = makeStyles((theme) => ({ + mainPaper: { + flex: 1, + padding: theme.spacing(1), + overflowY: 'scroll', + ...theme.scrollbarStyles, + }, + customTableCell: { + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + }, + tooltip: { + backgroundColor: '#f5f5f9', + color: 'rgba(0, 0, 0, 0.87)', + fontSize: theme.typography.pxToRem(14), + border: '1px solid #dadde9', + maxWidth: 450, + }, + tooltipPopper: { + textAlign: 'center', + }, + buttonProgress: { + color: green[500], + }, +})) + +const CustomToolTip = ({ title, content, children }) => { + const classes = useStyles() + + return ( + + + {title} + + {content && {content}} + + } + > + {children} + + ) +} + +const Campaign = () => { + //-------- + const { user } = useContext(AuthContext) + + const classes = useStyles() + + // const { whatsApps } = useContext(WhatsAppsContext) + + // console.log('------------> whatsApps: ', whatsApps) + + // const { campaigns, loading } = useContext(WhatsAppsContext) + const [campaignModalOpen, setCampaignModalOpen] = useState(false) + const [qrModalOpen, setQrModalOpen] = useState(false) + const [selectedCampaign, setSelectedCampaign] = useState(null) + const [confirmModalOpen, setConfirmModalOpen] = useState(false) + + const [diskSpaceInfo, setDiskSpaceInfo] = useState({}) + + const [disabled, setDisabled] = useState(true) + + const [settings, setSettings] = useState([]) + + const [buttons, setClicks] = useState([]) + + const [campaigns, dispatch] = useReducer(reducer, []) + + const [loading, setLoading] = useState(true) + + const confirmationModalInitialState = { + action: '', + title: '', + message: '', + campaignId: '', + csv_original_file_name:'', + open: false, + } + const [confirmModalInfo, setConfirmModalInfo] = useState( + confirmationModalInitialState + ) + + + useEffect(() => { + dispatch({ type: "RESET" }) + }, []) + + useEffect(() => { + setLoading(true) + + const delayDebounceFn = setTimeout(() => { + const fetchContacts = async () => { + + try { + console.log('process.env.REACT_APP_BACKEND_URL_PRIVATE: ', process.env.REACT_APP_BACKEND_URL_PRIVATE) + + const { data } = await apiBroker.get('/campaign', { + params: { + adminId: user.id, + baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, + identifier: 'campaign' + } + }) + + dispatch({ type: "LOAD_CAMPAIGNS", payload: data.campaign }) + setLoading(false) + + } catch (err) { + toastError(err) + } + + } + fetchContacts() + }, 500) + return () => clearTimeout(delayDebounceFn) + }, []) + + useEffect(() => { + const fetchSession = async () => { + try { + // const test = await apiBroker.get('/contacts/status/insert/onqueue', { + // params: { + // adminId: user.id, + // baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, + // identifier: 'campaign', + // }, + // }) + + // console.log('-------------------> test: ', test) + + // const { data } = await api.get('/settings') + // setSettings(data) + + } catch (err) { + toastError(err) + } + } + fetchSession() + }, []) + + const getSettingValue = (key) => { + const { value } = settings.find((s) => s.key === key) + + return value + } + + const handleStartWhatsAppSession = async (campaignId) => { + try { + await api.post(`/whatsappsession/${campaignId}`) + } catch (err) { + toastError(err) + } + } + + // useEffect(() => { + // for (let i = 0; i < campaigns.length; i++) { + // if (buttons.includes(campaigns[i].id)) { + // campaigns[i].disabled = true + // } + // } + // }, [campaigns, buttons]) + + const handleRequestNewQrCode = async (campaignId) => { + try { + await api.put(`/whatsappsession/${campaignId}`) + } catch (err) { + toastError(err) + } + } + + const handleOpenCampaignModal = () => { + setSelectedCampaign(null) + setCampaignModalOpen(true) + } + + const handleCloseCampaignModal = useCallback(() => { + setCampaignModalOpen(false) + setSelectedCampaign(null) + }, [setSelectedCampaign, setCampaignModalOpen]) + + const handleOpenQrModal = (campaign) => { + setSelectedCampaign(campaign) + setQrModalOpen(true) + } + + const handleCloseQrModal = useCallback(() => { + setSelectedCampaign(null) + setQrModalOpen(false) + }, [setQrModalOpen, setSelectedCampaign]) + + const handleEditCampaign = (campaign) => { + setSelectedCampaign(campaign) + setCampaignModalOpen(true) + } + + const handleOpenConfirmationModal = (action, campaignId) => { + if (action === 'disconnect') { + setConfirmModalInfo({ + action: action, + title: i18n.t('connections.confirmationModal.disconnectTitle'), + message: i18n.t('connections.confirmationModal.disconnectMessage'), + campaignId: campaignId, + }) + } + + if (action === 'delete') { + setConfirmModalInfo({ + action: action, + title: i18n.t('connections.confirmationModal.deleteTitle'), + message: i18n.t('connections.confirmationModal.deleteMessage'), + campaignId: campaignId, + }) + } + setConfirmModalOpen(true) + } + + const handleSubmitConfirmationModal = async () => { + if (confirmModalInfo.action === 'disconnect') { + try { + await api.delete(`/whatsappsession/${confirmModalInfo.campaignId}`) + } catch (err) { + toastError(err) + } + } + + if (confirmModalInfo.action === 'delete') { + try { + await apiBroker.delete(`/campaign/${confirmModalInfo.campaignId}`, { + params: { + adminId: user.id, + baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, + identifier: 'campaign', + }, + }) + + dispatch({ type: "DELETE_CAMPAIGN", payload: confirmModalInfo.campaignId }) + + toast.success('Campanha deletada com sucesso') + } catch (err) { + toastError(err) + } + } + + setConfirmModalInfo(confirmationModalInitialState) + } + + const renderActionButtons = (campaign) => { + return ( + ( + <> + {campaign.status === 'qrcode' && ( + + )} + {campaign.status === 'DISCONNECTED' && ( + <> + {' '} + + + )} + {(campaign.status === 'CONNECTED' || + campaign.status === 'PAIRING' || + campaign.status === 'TIMEOUT') && ( + + )} + {campaign.status === 'OPENING' && ( + + )} + + )} + /> + ) + } + + const renderStatusToolTips = (campaign) => { + return ( +
    + {campaign.status === 'DISCONNECTED' && ( + + + + )} + {campaign.status === 'OPENING' && ( + + )} + {campaign.status === 'qrcode' && ( + + + + )} + {campaign.status === 'CONNECTED' && ( + + + + )} + {(campaign.status === 'TIMEOUT' || campaign.status === 'PAIRING') && ( + + + + )} + + {/* {campaign.status === "RESTORING" && ( + + + + )} */} +
    + ) + } + + useEffect(() => { + const delayDebounceFn = setTimeout(() => { + const fetchQueries = async () => { + try { + await api.post(`/restartwhatsappsession/0`, { + params: { status: 'status' }, + }) + + setDisabled(false) + + setClicks((buttons) => + buttons.map((e) => { + return { id: e.id, disabled: false } + }) + ) + } catch (err) { + console.log(err) + } + } + + fetchQueries() + }, 500) + return () => clearTimeout(delayDebounceFn) + }, []) + + useEffect(() => { + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + + socket.on('diskSpaceMonit', (data) => { + if (data.action === 'update') { + setDiskSpaceInfo(data.diskSpace) + } + }) + + socket.on('settings', (data) => { + if (data.action === 'update') { + setSettings((prevState) => { + const aux = [...prevState] + const settingIndex = aux.findIndex((s) => s.key === data.setting.key) + aux[settingIndex].value = data.setting.value + return aux + }) + } + }) + + return () => { + socket.disconnect() + } + }, []) + + return ( + ( + + + {confirmModalInfo.message} + + + + + + + + Campanhas + + + ( + + )} + /> + + + + + <> + + + + + Nome + + + + Status + + + ( + + {i18n.t('connections.table.session')} + + )} + /> + + + Whatsapp sender + + + + + Mensagem + + + + {i18n.t('connections.table.actions')} + + + + + {loading ? ( + + ) : ( + <> + {campaigns?.length > 0 && + campaigns.map((campaign) => ( + + + {campaign.name} + + + + Status + + + ( + + {renderActionButtons(campaign)} + + )} + /> + + + {campaign.whatsapp_sender} + + + + {campaign.message} + + + + ( +
    + {(settings && + settings.length > 0 && + getSettingValue('editURA') && + getSettingValue('editURA') === + 'enabled') | + (user.profile === 'master') ? ( + + handleEditCampaign(campaign) + } + > + + + ) : ( +
    + )} +
    + )} + /> + + ( + { + handleOpenConfirmationModal( + 'delete', + campaign.id + ) + }} + > + + + )} + /> +
    + + +
    + ))} + + )} +
    +
    + +
    +
    + )} + /> + ) +} + +export default Campaign diff --git a/frontend/src/pages/Contacts/index.js b/frontend/src/pages/Contacts/index.js index d67298b..ab8a653 100644 --- a/frontend/src/pages/Contacts/index.js +++ b/frontend/src/pages/Contacts/index.js @@ -1,43 +1,43 @@ -import React, { useState, useEffect, useReducer, useContext } from "react"; -import openSocket from "socket.io-client"; -import { toast } from "react-toastify"; -import { useHistory } from "react-router-dom"; +import React, { useState, useEffect, useReducer, useContext } from "react" +import openSocket from "socket.io-client" +import { toast } from "react-toastify" +import { useHistory } from "react-router-dom" -import { makeStyles } from "@material-ui/core/styles"; -import Table from "@material-ui/core/Table"; -import TableBody from "@material-ui/core/TableBody"; -import TableCell from "@material-ui/core/TableCell"; -import TableHead from "@material-ui/core/TableHead"; -import TableRow from "@material-ui/core/TableRow"; -import Paper from "@material-ui/core/Paper"; -import Button from "@material-ui/core/Button"; -import Avatar from "@material-ui/core/Avatar"; -import WhatsAppIcon from "@material-ui/icons/WhatsApp"; -import SearchIcon from "@material-ui/icons/Search"; -import TextField from "@material-ui/core/TextField"; -import InputAdornment from "@material-ui/core/InputAdornment"; +import { makeStyles } from "@material-ui/core/styles" +import Table from "@material-ui/core/Table" +import TableBody from "@material-ui/core/TableBody" +import TableCell from "@material-ui/core/TableCell" +import TableHead from "@material-ui/core/TableHead" +import TableRow from "@material-ui/core/TableRow" +import Paper from "@material-ui/core/Paper" +import Button from "@material-ui/core/Button" +import Avatar from "@material-ui/core/Avatar" +import WhatsAppIcon from "@material-ui/icons/WhatsApp" +import SearchIcon from "@material-ui/icons/Search" +import TextField from "@material-ui/core/TextField" +import InputAdornment from "@material-ui/core/InputAdornment" -import IconButton from "@material-ui/core/IconButton"; -import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline"; -import EditIcon from "@material-ui/icons/Edit"; +import IconButton from "@material-ui/core/IconButton" +import DeleteOutlineIcon from "@material-ui/icons/DeleteOutline" +import EditIcon from "@material-ui/icons/Edit" -import api from "../../services/api"; -import TableRowSkeleton from "../../components/TableRowSkeleton"; -import ContactModal from "../../components/ContactModal"; -import ConfirmationModal from "../../components/ConfirmationModal/"; +import api from "../../services/api" +import TableRowSkeleton from "../../components/TableRowSkeleton" +import ContactModal from "../../components/ContactModal" +import ConfirmationModal from "../../components/ConfirmationModal/" -import { i18n } from "../../translate/i18n"; -import MainHeader from "../../components/MainHeader"; -import Title from "../../components/Title"; -import MainHeaderButtonsWrapper from "../../components/MainHeaderButtonsWrapper"; -import MainContainer from "../../components/MainContainer"; -import toastError from "../../errors/toastError"; -import { AuthContext } from "../../context/Auth/AuthContext"; -import { Can } from "../../components/Can"; +import { i18n } from "../../translate/i18n" +import MainHeader from "../../components/MainHeader" +import Title from "../../components/Title" +import MainHeaderButtonsWrapper from "../../components/MainHeaderButtonsWrapper" +import MainContainer from "../../components/MainContainer" +import toastError from "../../errors/toastError" +import { AuthContext } from "../../context/Auth/AuthContext" +import { Can } from "../../components/Can" -import apiBroker from "../../services/apiBroker"; +import apiBroker from "../../services/apiBroker" import fileDownload from 'js-file-download' -import ContactCreateTicketModal from "../../components/ContactCreateTicketModal"; +import ContactCreateTicketModal from "../../components/ContactCreateTicketModal" @@ -46,50 +46,50 @@ const reducer = (state, action) => { if (action.type === "LOAD_CONTACTS") { - const contacts = action.payload; - const newContacts = []; + const contacts = action.payload + const newContacts = [] contacts.forEach((contact) => { - const contactIndex = state.findIndex((c) => +c.id === +contact.id); + const contactIndex = state.findIndex((c) => +c.id === +contact.id) if (contactIndex !== -1) { - state[contactIndex] = contact; + state[contactIndex] = contact } else { - newContacts.push(contact); + newContacts.push(contact) } - }); + }) - return [...state, ...newContacts]; + return [...state, ...newContacts] } if (action.type === "UPDATE_CONTACTS") { - const contact = action.payload; - const contactIndex = state.findIndex((c) => +c.id === +contact.id); + const contact = action.payload + const contactIndex = state.findIndex((c) => +c.id === +contact.id) if (contactIndex !== -1) { - state[contactIndex] = contact; - return [...state]; + state[contactIndex] = contact + return [...state] } else { - return [contact, ...state]; + return [contact, ...state] } } if (action.type === "DELETE_CONTACT") { - const contactId = action.payload; + const contactId = action.payload - const contactIndex = state.findIndex((c) => +c.id === +contactId); + const contactIndex = state.findIndex((c) => +c.id === +contactId) if (contactIndex !== -1) { - state.splice(contactIndex, 1); + state.splice(contactIndex, 1) } - return [...state]; + return [...state] } if (action.type === "RESET") { - return []; + return [] } -}; +} const useStyles = makeStyles((theme) => ({ mainPaper: { @@ -98,24 +98,24 @@ const useStyles = makeStyles((theme) => ({ overflowY: "scroll", ...theme.scrollbarStyles, }, -})); +})) const Contacts = () => { - const classes = useStyles(); - const history = useHistory(); + const classes = useStyles() + const history = useHistory() - const { user } = useContext(AuthContext); + const { user } = useContext(AuthContext) - const [loading, setLoading] = useState(false); - const [pageNumber, setPageNumber] = useState(1); - const [searchParam, setSearchParam] = useState(""); - const [contacts, dispatch] = useReducer(reducer, []); - const [selectedContactId, setSelectedContactId] = useState(null); - const [contactModalOpen, setContactModalOpen] = useState(false); + const [loading, setLoading] = useState(false) + const [pageNumber, setPageNumber] = useState(1) + const [searchParam, setSearchParam] = useState("") + const [contacts, dispatch] = useReducer(reducer, []) + const [selectedContactId, setSelectedContactId] = useState(null) + const [contactModalOpen, setContactModalOpen] = useState(false) const [isCreateTicketModalOpen, setIsCreateTicketModalOpen] = useState(false) - const [deletingContact, setDeletingContact] = useState(null); - const [confirmOpen, setConfirmOpen] = useState(false); - const [hasMore, setHasMore] = useState(false); + const [deletingContact, setDeletingContact] = useState(null) + const [confirmOpen, setConfirmOpen] = useState(false) + const [hasMore, setHasMore] = useState(false) const [onQueueStatus, setOnQueueProcessStatus] = useState(undefined) @@ -132,20 +132,20 @@ const Contacts = () => { return } - const formData = new FormData(); - formData.append("adminId", user.id); - formData.append("baseURL", process.env.REACT_APP_BACKEND_URL_PRIVATE,); - formData.append("frontURL", process.env.REACT_APP_FRONTEND_URL); - formData.append("identifier", 'contacts_insert_csv'); - formData.append("file", event.target.files[0]); + const formData = new FormData() + formData.append("adminId", user.id) + formData.append("baseURL", process.env.REACT_APP_BACKEND_URL_PRIVATE,) + formData.append("frontURL", process.env.REACT_APP_FRONTEND_URL) + formData.append("identifier", 'contacts_insert_csv') + formData.append("file", event.target.files[0]) const config = { headers: { 'content-type': 'multipart/form-data', }, - }; + } - const bulk_contact_insert = await apiBroker.post("/contacts/bulk/insert", formData, config); + const bulk_contact_insert = await apiBroker.post("/contacts/bulk/insert", formData, config) console.log(bulk_contact_insert.data) @@ -156,7 +156,7 @@ const Contacts = () => { // history.go(0); } catch (err) { - toastError(err); + toastError(err) } } @@ -177,7 +177,7 @@ const Contacts = () => { baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, identifier: 'contacts_insert_csv' } - }); + }) if (insertOnQueue && insertOnQueue.data) { @@ -193,23 +193,23 @@ const Contacts = () => { } catch (err) { - console.log(err); + console.log(err) } - }; + } - fetchReportOnQueue(); + fetchReportOnQueue() - }, 500); - return () => clearTimeout(delayDebounceFn); + }, 500) + return () => clearTimeout(delayDebounceFn) }, [user]) useEffect(() => { - dispatch({ type: "RESET" }); - setPageNumber(1); - }, [searchParam]); + dispatch({ type: "RESET" }) + setPageNumber(1) + }, [searchParam]) useEffect(() => { @@ -220,7 +220,7 @@ const Contacts = () => { - setLoading(true); + setLoading(true) const delayDebounceFn = setTimeout(() => { const fetchContacts = async () => { @@ -230,25 +230,25 @@ const Contacts = () => { return } - const { data } = await api.get("/contacts/", { params: { searchParam, pageNumber }, }); + const { data } = await api.get("/contacts/", { params: { searchParam, pageNumber }, }) - dispatch({ type: "LOAD_CONTACTS", payload: data.contacts }); - setHasMore(data.hasMore); - setLoading(false); + dispatch({ type: "LOAD_CONTACTS", payload: data.contacts }) + setHasMore(data.hasMore) + setLoading(false) } catch (err) { - toastError(err); + toastError(err) } - }; - fetchContacts(); - }, 500); - return () => clearTimeout(delayDebounceFn); - }, [searchParam, pageNumber]); + } + fetchContacts() + }, 500) + return () => clearTimeout(delayDebounceFn) + }, [searchParam, pageNumber]) useEffect(() => { - const socket = openSocket(process.env.REACT_APP_BACKEND_URL); + const socket = openSocket(process.env.REACT_APP_BACKEND_URL) socket.on("contactsBulkInsertOnQueueStatus", (data) => { if (data.action === 'update') { @@ -261,7 +261,7 @@ const Contacts = () => { setOnQueueProcessStatus(data.insertOnQueue.queueStatus) if (data.insertOnQueue.queueStatus === "success") { - history.go(0); + history.go(0) } } @@ -270,18 +270,18 @@ const Contacts = () => { socket.on("contact", (data) => { if (data.action === "update" || data.action === "create") { - dispatch({ type: "UPDATE_CONTACTS", payload: data.contact }); + dispatch({ type: "UPDATE_CONTACTS", payload: data.contact }) } if (data.action === "delete") { - dispatch({ type: "DELETE_CONTACT", payload: +data.contactId }); + dispatch({ type: "DELETE_CONTACT", payload: +data.contactId }) } - }); + }) return () => { - socket.disconnect(); - }; - }, [user, history]); + socket.disconnect() + } + }, [user, history]) const removeExtraSpace = (str) => { @@ -291,18 +291,18 @@ const Contacts = () => { } const handleSearch = (event) => { - setSearchParam(removeExtraSpace(event.target.value.toLowerCase())); - }; + setSearchParam(removeExtraSpace(event.target.value.toLowerCase())) + } const handleOpenContactModal = () => { - setSelectedContactId(null); - setContactModalOpen(true); - }; + setSelectedContactId(null) + setContactModalOpen(true) + } const handleCloseContactModal = () => { - setSelectedContactId(null); - setContactModalOpen(false); - }; + setSelectedContactId(null) + setContactModalOpen(false) + } const handleOpenCreateTicketModal = (contactId) => { setSelectedContactId(contactId) @@ -330,46 +330,46 @@ const Contacts = () => { // }; const hadleEditContact = (contactId) => { - setSelectedContactId(contactId); - setContactModalOpen(true); - }; + setSelectedContactId(contactId) + setContactModalOpen(true) + } const handleDeleteContact = async (contactId) => { try { - await api.delete(`/contacts/${contactId}`); - toast.success(i18n.t("contacts.toasts.deleted")); + await api.delete(`/contacts/${contactId}`) + toast.success(i18n.t("contacts.toasts.deleted")) } catch (err) { - toastError(err); + toastError(err) } - setDeletingContact(null); - setSearchParam(""); - setPageNumber(1); - }; + setDeletingContact(null) + setSearchParam("") + setPageNumber(1) + } const handleimportContact = async () => { try { - await api.post("/contacts/import"); - history.go(0); + await api.post("/contacts/import") + history.go(0) } catch (err) { - toastError(err); + toastError(err) } - }; + } const loadMore = () => { - setPageNumber((prevState) => prevState + 1); - }; + setPageNumber((prevState) => prevState + 1) + } const handleScroll = (e) => { - if (!hasMore || loading) return; - const { scrollTop, scrollHeight, clientHeight } = e.currentTarget; + if (!hasMore || loading) return + const { scrollTop, scrollHeight, clientHeight } = e.currentTarget if (scrollHeight - (scrollTop + 100) < clientHeight) { - loadMore(); + loadMore() } - }; + } const handleDownload = async () => { @@ -378,16 +378,16 @@ const Contacts = () => { try { - let res = await apiBroker.get(`/contacts/download/${zipfile}`, { responseType: 'blob' }); + let res = await apiBroker.get(`/contacts/download/${zipfile}`, { responseType: 'blob' }) if (res) { - fileDownload(res.data, `${zipfile}`); + fileDownload(res.data, `${zipfile}`) setOnQueueProcessStatus('empty') } } catch (err) { - console.log(err); + console.log(err) } @@ -406,7 +406,7 @@ const Contacts = () => { baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, identifier: 'contacts_insert_csv' } - }); + }) if (res) { setOnQueueProcessStatus('empty') @@ -414,7 +414,7 @@ const Contacts = () => { } catch (err) { - console.log(err); + console.log(err) } @@ -452,13 +452,13 @@ const Contacts = () => { > {"CSV ALL"} */} - ); + ) case 'pending' || 'processing': return ( <> PROCESSING... - ); + ) case 'success': return ( @@ -472,7 +472,7 @@ const Contacts = () => { > {'DOWNLOAD'} - ); + ) case 'error': return ( <> @@ -485,16 +485,16 @@ const Contacts = () => { > {'ERROR'} - ); + ) case 'downloading': return ( <> DOWNLOADING... - ); + ) default: - return (<>WAITING...); + return (<>WAITING...) } } @@ -642,8 +642,8 @@ const Contacts = () => { { - setConfirmOpen(true); - setDeletingContact(contact); + setConfirmOpen(true) + setDeletingContact(contact) }} > @@ -659,7 +659,7 @@ const Contacts = () => { - ); -}; + ) +} -export default Contacts; \ No newline at end of file +export default Contacts \ No newline at end of file diff --git a/frontend/src/routes/index.js b/frontend/src/routes/index.js index 1043761..ba35368 100644 --- a/frontend/src/routes/index.js +++ b/frontend/src/routes/index.js @@ -1,27 +1,26 @@ -import React from "react"; -import { BrowserRouter, Switch } from "react-router-dom"; -import { ToastContainer } from "react-toastify"; +import React from 'react' +import { BrowserRouter, Switch } from 'react-router-dom' +import { ToastContainer } from 'react-toastify' -import LoggedInLayout from "../layout"; -import Dashboard from "../pages/Dashboard/"; - -import Report from "../pages/Report/"; -import SchedulesReminder from "../pages/SchedulesReminder/"; - -import Tickets from "../pages/Tickets/"; -import Signup from "../pages/Signup/"; -import Login from "../pages/Login/"; -import Connections from "../pages/Connections/"; -import Settings from "../pages/Settings/"; -import Users from "../pages/Users"; -import Contacts from "../pages/Contacts/"; -import QuickAnswers from "../pages/QuickAnswers/"; -import Queues from "../pages/Queues/"; -import { AuthProvider } from "../context/Auth/AuthContext"; -import { WhatsAppsProvider } from "../context/WhatsApp/WhatsAppsContext"; -import Route from "./Route"; +import LoggedInLayout from '../layout' +import Dashboard from '../pages/Dashboard/' +import Report from '../pages/Report/' +import SchedulesReminder from '../pages/SchedulesReminder/' +import Tickets from '../pages/Tickets/' +import Signup from '../pages/Signup/' +import Login from '../pages/Login/' +import Connections from '../pages/Connections/' +import Campaign from '../pages/Campaign' +import Settings from '../pages/Settings/' +import Users from '../pages/Users' +import Contacts from '../pages/Contacts/' +import QuickAnswers from '../pages/QuickAnswers/' +import Queues from '../pages/Queues/' +import { AuthProvider } from '../context/Auth/AuthContext' +import { WhatsAppsProvider } from '../context/WhatsApp/WhatsAppsContext' +import Route from './Route' const Routes = () => { return ( @@ -33,27 +32,48 @@ const Routes = () => { - + - + - + - + + - ); -}; + ) +} -export default Routes; +export default Routes From c8ea53a4bcf299da25a638c0641f22a879e6acee Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 8 Aug 2023 12:09:03 -0300 Subject: [PATCH 06/19] =?UTF-8?q?finaliza=C3=A7=C3=A3o=20do=20recurso=20de?= =?UTF-8?q?=20encerramento=20de=20ticket=20automatico=20e=20expira=C3=A7?= =?UTF-8?q?=C3=A3o=20de=20ticket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/controllers/SettingController.ts | 33 +- backend/src/database/index.ts | 4 +- .../20230807152412-setting-tickets.ts | 46 + .../20230807154146-add-setting-tickets.ts | 34 + backend/src/helpers/AutoCloseTickets.ts | 84 ++ backend/src/models/SettingTicket.ts | 40 + backend/src/routes/settingRoutes.ts | 10 +- backend/src/server.ts | 1 + .../SettingServices/UpdateSettingTicket.ts | 35 + .../TicketServices/ListTicketTimeLife.ts | 47 + .../TicketServices/UpdateTicketService.ts | 2 +- .../WbotServices/wbotMessageListener.ts | 1044 +++++++++-------- frontend/package.json | 1 + frontend/src/components/ConfigModal/index.js | 304 +++++ frontend/src/hooks/useAuth.js/index.js | 2 +- frontend/src/pages/Connections/index.js | 54 +- frontend/src/pages/Queues/index.js | 2 +- frontend/src/pages/Settings/index.js | 2 +- 18 files changed, 1257 insertions(+), 488 deletions(-) create mode 100644 backend/src/database/migrations/20230807152412-setting-tickets.ts create mode 100644 backend/src/database/seeds/20230807154146-add-setting-tickets.ts create mode 100644 backend/src/helpers/AutoCloseTickets.ts create mode 100644 backend/src/models/SettingTicket.ts create mode 100644 backend/src/services/SettingServices/UpdateSettingTicket.ts create mode 100644 backend/src/services/TicketServices/ListTicketTimeLife.ts create mode 100644 frontend/src/components/ConfigModal/index.js diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts index 7144a89..c8cb940 100644 --- a/backend/src/controllers/SettingController.ts +++ b/backend/src/controllers/SettingController.ts @@ -5,6 +5,8 @@ import AppError from "../errors/AppError"; import UpdateSettingService from "../services/SettingServices/UpdateSettingService"; import ListSettingsService from "../services/SettingServices/ListSettingsService"; +import updateSettingTicket from "../services/SettingServices/UpdateSettingTicket"; +import SettingTicket from "../models/SettingTicket"; export const index = async (req: Request, res: Response): Promise => { // if (req.user.profile !== "master") { @@ -12,8 +14,37 @@ export const index = async (req: Request, res: Response): Promise => { // } const settings = await ListSettingsService(); + const outBusinessHours = await SettingTicket.findOne({ + where: { key: "outBusinessHours" } + }); + const ticketExpiration = await SettingTicket.findOne({ + where: { key: "ticketExpiration" } + }); - return res.status(200).json(settings); + return res.status(200).json({ settings, outBusinessHours, ticketExpiration }); +}; + +export const updateTicketSettings = async ( + req: Request, + res: Response +): Promise => { + const { outBusinessHours, ticketExpiration } = req.body; + + if (outBusinessHours && Object.keys(outBusinessHours).length > 0) { + await updateSettingTicket({ + ...outBusinessHours, + key: "outBusinessHours" + }); + } + + if (ticketExpiration && Object.keys(ticketExpiration).length > 0) { + await updateSettingTicket({ + ...ticketExpiration, + key: "ticketExpiration" + }); + } + + return res.status(200).json({ outBusinessHours, ticketExpiration }); }; export const update = async ( diff --git a/backend/src/database/index.ts b/backend/src/database/index.ts index 9749831..f5bf45d 100644 --- a/backend/src/database/index.ts +++ b/backend/src/database/index.ts @@ -14,6 +14,7 @@ import QuickAnswer from "../models/QuickAnswer"; import SchedulingNotify from "../models/SchedulingNotify"; import StatusChatEnd from "../models/StatusChatEnd"; import UserOnlineTime from "../models/UserOnlineTime"; +import SettingTicket from "../models/SettingTicket"; // eslint-disable-next-line const dbConfig = require("../config/database"); // import dbConfig from "../config/database"; @@ -35,7 +36,8 @@ const models = [ SchedulingNotify, StatusChatEnd, - UserOnlineTime, + UserOnlineTime, + SettingTicket ]; sequelize.addModels(models); diff --git a/backend/src/database/migrations/20230807152412-setting-tickets.ts b/backend/src/database/migrations/20230807152412-setting-tickets.ts new file mode 100644 index 0000000..b2581c8 --- /dev/null +++ b/backend/src/database/migrations/20230807152412-setting-tickets.ts @@ -0,0 +1,46 @@ +import { QueryInterface, DataTypes } from "sequelize" + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.createTable("SettingTickets", { + id: { + type: DataTypes.INTEGER, + autoIncrement: true, + primaryKey: true, + allowNull: false + }, + message: { + type: DataTypes.STRING, + allowNull: true + }, + startTime: { + type: DataTypes.DATE, + allowNull: true + }, + endTime: { + type: DataTypes.DATE, + allowNull: true + }, + value: { + type: DataTypes.STRING, + allowNull: false + }, + key: { + type: DataTypes.STRING, + allowNull: false + }, + createdAt: { + type: DataTypes.DATE, + allowNull: false + }, + updatedAt: { + type: DataTypes.DATE, + allowNull: false + } + }); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.dropTable("SettingTickets"); + } +} diff --git a/backend/src/database/seeds/20230807154146-add-setting-tickets.ts b/backend/src/database/seeds/20230807154146-add-setting-tickets.ts new file mode 100644 index 0000000..9d40d31 --- /dev/null +++ b/backend/src/database/seeds/20230807154146-add-setting-tickets.ts @@ -0,0 +1,34 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "SettingTickets", + [ + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "outBusinessHours", + createdAt: new Date(), + updatedAt: new Date() + }, + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "ticketExpiration", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("SettingTickets", {}); + } +}; diff --git a/backend/src/helpers/AutoCloseTickets.ts b/backend/src/helpers/AutoCloseTickets.ts new file mode 100644 index 0000000..2948035 --- /dev/null +++ b/backend/src/helpers/AutoCloseTickets.ts @@ -0,0 +1,84 @@ +import SettingTicket from "../models/SettingTicket"; +import ListTicketTimeLife from "../services/TicketServices/ListTicketTimeLife"; +import UpdateTicketService from "../services/TicketServices/UpdateTicketService"; +import BotIsOnQueue from "./BotIsOnQueue"; + +import { + format as _format, + isWithinInterval, + parse, + subMinutes +} from "date-fns"; + +import ptBR from "date-fns/locale/pt-BR"; +import { splitDateTime } from "./SplitDateTime"; + +const fsPromises = require("fs/promises"); +const fs = require("fs"); + +let timer: any; + +const AutoCloseTickets = async () => { + try { + // const botInfo = await BotIsOnQueue('botqueue') + + // if (!botInfo.userIdBot) return + + const ticketExpiration = await SettingTicket.findOne({ + where: { key: "ticketExpiration" } + }); + + if (ticketExpiration && ticketExpiration.value == "enabled") { + const startTime = splitDateTime( + new Date( + _format(new Date(ticketExpiration.startTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const seconds = timeStringToSeconds(startTime.fullTime); + + console.log("Ticket seconds: ", seconds); + + let tickets: any = await ListTicketTimeLife({ + timeseconds: seconds, + status: "open" + }); + + console.log("tickets: ", tickets); + + for (let i = 0; i < tickets.length; i++) { + + await UpdateTicketService({ + ticketData: { status: "closed", statusChatEnd: "FINALIZADO" }, + ticketId: tickets[i].ticket_id, + msg: ticketExpiration.message + }); + } + } + } catch (error) { + console.log("There was an error on try close the bot tickets: ", error); + } +}; + +function timeStringToSeconds(timeString: any) { + const [hours, minutes, seconds] = timeString.split(":").map(Number); + return hours * 3600 + minutes * 60 + seconds; +} + +const schedule = async () => { + try { + clearInterval(timer); + + await AutoCloseTickets(); + } catch (error) { + console.log("error on schedule: ", error); + } finally { + timer = setInterval(schedule, 60000); + } +}; + +timer = setInterval(schedule, 60000); + +export default schedule; diff --git a/backend/src/models/SettingTicket.ts b/backend/src/models/SettingTicket.ts new file mode 100644 index 0000000..10ef6c2 --- /dev/null +++ b/backend/src/models/SettingTicket.ts @@ -0,0 +1,40 @@ +import { + Table, + Column, + CreatedAt, + UpdatedAt, + Model, + PrimaryKey, + AutoIncrement +} from "sequelize-typescript"; + +@Table +class SettingTicket extends Model { + @PrimaryKey + @AutoIncrement + @Column + id: number; + + @Column + message: string; + + @Column + startTime: Date; + + @Column + endTime: Date; + + @Column + value: string; + + @Column + key: string; + + @CreatedAt + createdAt: Date; + + @UpdatedAt + updatedAt: Date; +} + +export default SettingTicket; diff --git a/backend/src/routes/settingRoutes.ts b/backend/src/routes/settingRoutes.ts index 7047a63..dc361fb 100644 --- a/backend/src/routes/settingRoutes.ts +++ b/backend/src/routes/settingRoutes.ts @@ -3,13 +3,21 @@ import isAuth from "../middleware/isAuth"; import * as SettingController from "../controllers/SettingController"; -const settingRoutes = Router(); +const settingRoutes = Router(); settingRoutes.get("/settings", SettingController.index); // routes.get("/settings/:settingKey", isAuth, SettingsController.show); +settingRoutes.put( + "/settings/ticket", + isAuth, + SettingController.updateTicketSettings +); + + // change setting key to key in future settingRoutes.put("/settings/:settingKey", isAuth, SettingController.update); + export default settingRoutes; diff --git a/backend/src/server.ts b/backend/src/server.ts index 2ab92c0..3e7b7ac 100644 --- a/backend/src/server.ts +++ b/backend/src/server.ts @@ -10,6 +10,7 @@ import { cacheSize, flushCache, loadTicketsCache } from "./helpers/TicketCache"; import { loadContactsCache } from "./helpers/ContactsCache"; import { loadSchedulesCache } from "./helpers/SchedulingNotifyCache"; import { delRestoreControllFile } from "./helpers/RestoreControll"; +import "./helpers/AutoCloseTickets"; import "./helpers/SchedulingNotifySendMessage" import axios from "axios"; diff --git a/backend/src/services/SettingServices/UpdateSettingTicket.ts b/backend/src/services/SettingServices/UpdateSettingTicket.ts new file mode 100644 index 0000000..5319c10 --- /dev/null +++ b/backend/src/services/SettingServices/UpdateSettingTicket.ts @@ -0,0 +1,35 @@ +import AppError from "../../errors/AppError"; +import SettingTicket from "../../models/SettingTicket"; + +interface Request { + key: string; + startTime: string; + endTime: string; + value: string; + message: string; +} + +const updateSettingTicket = async ({ + key, + startTime, + endTime, + value, + message +}: Request): Promise => { + try { + const businessHours = await SettingTicket.findOne({ where: { key } }); + + if (!businessHours) { + throw new AppError("ERR_NO_SETTING_FOUND", 404); + } + + await businessHours.update({ startTime, endTime, message, value }); + + return businessHours; + } catch (error: any) { + console.error("===> Error on UpdateSettingService.ts file: \n", error); + throw new AppError(error.message); + } +}; + +export default updateSettingTicket; diff --git a/backend/src/services/TicketServices/ListTicketTimeLife.ts b/backend/src/services/TicketServices/ListTicketTimeLife.ts new file mode 100644 index 0000000..bcaa0c8 --- /dev/null +++ b/backend/src/services/TicketServices/ListTicketTimeLife.ts @@ -0,0 +1,47 @@ + +import { Sequelize, } from "sequelize"; + +const dbConfig = require("../../config/database"); +const sequelize = new Sequelize(dbConfig); +const { QueryTypes } = require('sequelize'); + +import { splitDateTime } from "../../helpers/SplitDateTime"; +import format from 'date-fns/format'; +import ptBR from 'date-fns/locale/pt-BR'; + + +interface Request { + timeseconds: string | number; + status: string; + userId?: string | number; +} + +const ListTicketTimeLife = async ({timeseconds, status, userId }: Request): Promise => { + + let tickets = [] + + let currentDate = format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }) + + // console.log('------------------> currentDate: ', currentDate) + + if (userId) { + // CONSULTANDO FILAS PELO ID DO USUARIO + tickets = await sequelize.query(`select user.id as user_id, user.name as user_name, t.id as ticket_id from Tickets as t inner join Users as user on + t.userId = user.id and user.name = 'botqueue' and t.status='${status}' and (TIMESTAMPDIFF(SECOND, t.updatedAt, '${currentDate}')) >= ${timeseconds};`, { type: QueryTypes.SELECT }); + + } else { + + // CONSULTANDO FILAS PELO USUARIO + tickets = await sequelize.query(`select id as ticket_id from Tickets where status='${status}' and + (TIMESTAMPDIFF(SECOND, updatedAt, '${currentDate}')) >= ${timeseconds};`, { type: QueryTypes.SELECT }); + + } + + return tickets; +}; + +export default ListTicketTimeLife; + + + + diff --git a/backend/src/services/TicketServices/UpdateTicketService.ts b/backend/src/services/TicketServices/UpdateTicketService.ts index eed34da..b4181d5 100644 --- a/backend/src/services/TicketServices/UpdateTicketService.ts +++ b/backend/src/services/TicketServices/UpdateTicketService.ts @@ -63,7 +63,7 @@ const UpdateTicketService = async ({ await ticket.reload(); - if (msg.length > 0) { + if (msg?.trim().length > 0) { setTimeout(async () => { diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 053b625..c85e2ab 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -5,12 +5,15 @@ import * as Sentry from "@sentry/node"; import { copyFolder } from "../../helpers/CopyFolder"; import { removeDir } from "../../helpers/DeleteDirectory"; -import path from 'path'; - -import { format } from "date-fns"; -import ptBR from 'date-fns/locale/pt-BR'; - +import path from "path"; +import { + format as _format, + isWithinInterval, + parse, + subMinutes +} from "date-fns"; +import ptBR from "date-fns/locale/pt-BR"; import { Contact as WbotContact, @@ -34,38 +37,42 @@ import UpdateTicketService from "../TicketServices/UpdateTicketService"; import { date } from "faker"; import ShowQueueService from "../QueueService/ShowQueueService"; -import ShowTicketMessage from "../TicketServices/ShowTicketMessage" -import BotIsOnQueue from "../../helpers/BotIsOnQueue" +import ShowTicketMessage from "../TicketServices/ShowTicketMessage"; +import BotIsOnQueue from "../../helpers/BotIsOnQueue"; import Queue from "../../models/Queue"; -import fs from 'fs'; +import fs from "fs"; import { StartWhatsAppSession } from "../../services/WbotServices/StartWhatsAppSession"; -import { removeWbot } from '../../libs/wbot' +import { removeWbot } from "../../libs/wbot"; import { restartWhatsSession } from "../../helpers/RestartWhatsSession"; -// test del -import data_ura from './ura' -import msg_client_transfer from './ura_msg_transfer' +// test del +import data_ura from "./ura"; +import msg_client_transfer from "./ura_msg_transfer"; import final_message from "./ura_final_message"; import SendWhatsAppMessage from "./SendWhatsAppMessage"; import Whatsapp from "../../models/Whatsapp"; import { splitDateTime } from "../../helpers/SplitDateTime"; -// +// -import { updateTicketCacheByTicketId } from '../../helpers/TicketCache' -import { insertMessageContactCache, getLastId } from '../../helpers/LastMessageIdByContactCache' +import { updateTicketCacheByTicketId } from "../../helpers/TicketCache"; +import { + insertMessageContactCache, + getLastId +} from "../../helpers/LastMessageIdByContactCache"; import autoRestore from "../../helpers/AutoRestore"; import { _restore } from "../../helpers/RestoreControll"; import sendWhatsAppMessageSocket from "../../helpers/SendWhatsappMessageSocket"; -import { getWhatsappIds, setWhatsappId } from "../../helpers/WhatsappIdMultiSessionControl"; +import { + getWhatsappIds, + setWhatsappId +} from "../../helpers/WhatsappIdMultiSessionControl"; import AppError from "../../errors/AppError"; import { setMessageAsRead } from "../../helpers/SetMessageAsRead"; +import SettingTicket from "../../models/SettingTicket"; - - -var lst: any[] = getWhatsappIds() - +var lst: any[] = getWhatsappIds(); interface Session extends Client { id?: number; @@ -113,7 +120,7 @@ const verifyMediaMessage = async ( ticket: Ticket, contact: Contact, media: any, - quotedMsg?: any, + quotedMsg?: any ): Promise => { // const quotedMsg = await verifyQuotedMessage(msg); @@ -123,12 +130,15 @@ const verifyMediaMessage = async ( throw new Error("ERR_WAPP_DOWNLOAD_MEDIA"); } - console.log('MEDIA.FILENAME: ', media.fileName, ' | msg.fromMe: ', msg.fromMe) + console.log( + "MEDIA.FILENAME: ", + media.fileName, + " | msg.fromMe: ", + msg.fromMe + ); if (!media.filename) { - - console.log('No file name -----------------------------------------') - + console.log("No file name -----------------------------------------"); const ext = media.mimetype.split("/")[1].split(";")[0]; media.filename = `${new Date().getTime()}.${ext}`; @@ -141,15 +151,13 @@ const verifyMediaMessage = async ( // "base64" // ); - console.log('FROM wbotMessageListener.ts media.filename: ', media.filename) - + console.log("FROM wbotMessageListener.ts media.filename: ", media.filename); await writeFileAsync( join(__dirname, "..", "..", "..", "..", "..", "public", media.filename), media.data, "base64" ); - } catch (err) { Sentry.captureException(err); logger.error(`There was an error: wbotMessageLitener.ts: ${err}`); @@ -178,11 +186,8 @@ const verifyMessage = async ( msg: WbotMessage, ticket: Ticket, contact: Contact, - quotedMsg?: any, + quotedMsg?: any ) => { - - - // const quotedMsg = await verifyQuotedMessage(msg); // const quotedMsg = await verifyQuotedMessage(msg); @@ -199,21 +204,17 @@ const verifyMessage = async ( // quotedMsgId: quotedMsg?.id }; - await ticket.update({ lastMessage: msg.body }); await CreateMessageService({ messageData }); }; - - const verifyQueue = async ( wbot: Session, msg: WbotMessage, ticket: Ticket, contact: Contact ) => { - const { queues, greetingMessage } = await ShowWhatsAppService(wbot.id!); /*if (queues.length === 1) { @@ -224,45 +225,32 @@ const verifyQueue = async ( return; }*/ - - let selectedOption = null; - let choosenQueue = null + let choosenQueue = null; //Habilitar esse caso queira usar o bot - // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 } + // const botInfo = await BotIsOnQueue('botqueue') + const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; if (botInfo.isOnQueue) { - choosenQueue = await ShowQueueService(botInfo.botQueueId); - - } - - else if (queues.length === 1) { + } else if (queues.length === 1) { selectedOption = 1; choosenQueue = queues[+selectedOption - 1]; - } - else { - + } else { selectedOption = msg.body; //////////////// EXTRAIR APENAS O NÚMERO /////////////////// - selectedOption = selectedOption.replace(/[^1-9]/g, '') + selectedOption = selectedOption.replace(/[^1-9]/g, ""); /////////////////////////////////// choosenQueue = queues[+selectedOption - 1]; } - - if (choosenQueue) { - // Atualizando o status do ticket para mostrar notificação para o atendente da fila escolhida pelo usuário. De queueChoice para pending if (queues.length > 1 && !botInfo.isOnQueue) { - await ticket.update({ status: "pending" }); - } // @@ -271,48 +259,42 @@ const verifyQueue = async ( ticketId: ticket.id }); - - let botOptions = '' + let botOptions = ""; // O bot abre a mensagem na fila para atender o usuario if (botInfo.isOnQueue) { - await UpdateTicketService({ - ticketData: { status: 'open', userId: botInfo.userIdBot }, + ticketData: { status: "open", userId: botInfo.userIdBot }, ticketId: ticket.id }); - data_ura.forEach((s, index) => { botOptions += `*${index + 1}* - ${s.option}\n` }); + data_ura.forEach((s, index) => { + botOptions += `*${index + 1}* - ${s.option}\n`; + }); } // - let body = '' + let body = ""; if (botOptions.length > 0) { body = `\u200e${choosenQueue.greetingMessage}\n\n${botOptions}\n${final_message.msg}`; - } - else { + } else { body = `\u200e${choosenQueue.greetingMessage}`; } - // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); - // await verifyMessage(sentMessage, ticket, contact); + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // await verifyMessage(sentMessage, ticket, contact); - sendWhatsAppMessageSocket(ticket, body) - - } - else { - - - //test del transfere o atendimento se entrar na ura infinita + sendWhatsAppMessageSocket(ticket, body); + } else { + //test del transfere o atendimento se entrar na ura infinita let ticket_message = await ShowTicketMessage(ticket.id, false); if (ticket_message.length > 10) { - - await UpdateTicketService({ ticketData: { status: 'pending', queueId: queues[0].id }, ticketId: ticket.id }); - - } - else { - + await UpdateTicketService({ + ticketData: { status: "pending", queueId: queues[0].id }, + ticketId: ticket.id + }); + } else { let options = ""; queues.forEach((queue, index) => { @@ -323,24 +305,17 @@ const verifyQueue = async ( const debouncedSentMessage = debounce( async () => { - - // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, body); // verifyMessage(sentMessage, ticket, contact); - sendWhatsAppMessageSocket(ticket, body) - - + sendWhatsAppMessageSocket(ticket, body); }, 3000, ticket.id ); debouncedSentMessage(); - } - - - } }; @@ -360,106 +335,123 @@ const isValidMsg = (msg: WbotMessage): boolean => { return false; }; - const queuesOutBot = async (wbot: Session, botId: string | number) => { - const { queues, greetingMessage } = await ShowWhatsAppService(wbot.id!); - const indexQueue = queues.findIndex((q) => q.id == botId) + const indexQueue = queues.findIndex(q => q.id == botId); if (indexQueue != -1) { - queues.splice(indexQueue, 1) + queues.splice(indexQueue, 1); } - return { queues, greetingMessage } - -} - -const botTransferTicket = async (queues: Queue, ticket: Ticket, contact: Contact, wbot: Session) => { + return { queues, greetingMessage }; +}; +const botTransferTicket = async ( + queues: Queue, + ticket: Ticket, + contact: Contact, + wbot: Session +) => { await ticket.update({ userId: null }); - await UpdateTicketService({ ticketData: { status: 'pending', queueId: queues.id }, ticketId: ticket.id }); - -} - - -const botSendMessage = (ticket: Ticket, contact: Contact, wbot: Session, msg: string) => { + await UpdateTicketService({ + ticketData: { status: "pending", queueId: queues.id }, + ticketId: ticket.id + }); +}; +const botSendMessage = (ticket: Ticket, msg: string) => { const debouncedSentMessage = debounce( - async () => { - const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, `${msg}`); - verifyMessage(sentMessage, ticket, contact); + //OLD + // const sentMessage = await wbot.sendMessage(`${contact.number}@c.us`, `${msg}`); + // verifyMessage(sentMessage, ticket, contact); + + //NEW + await SendWhatsAppMessage({ body: msg, ticket }); }, 3000, ticket.id ); debouncedSentMessage(); +}; -} +// const botSendMessage = ( +// ticket: Ticket, +// contact: Contact, +// wbot: Session, +// msg: string +// ) => { +// const debouncedSentMessage = debounce( +// async () => { +// const sentMessage = await wbot.sendMessage( +// `${contact.number}@c.us`, +// `${msg}` +// ); +// verifyMessage(sentMessage, ticket, contact); +// }, +// 3000, +// ticket.id +// ); + +// debouncedSentMessage(); +// }; const _clear_lst = () => { + console.log("THE lst.length: ", lst.length); - console.log('THE lst.length: ', lst.length) + if (lst.length <= 199) return; - if (lst.length <= 199) return - - const chunk: any = Math.floor((lst.length / 2)) + const chunk: any = Math.floor(lst.length / 2); lst = lst.slice(chunk, chunk + lst.length); - let whatsappIdsSplited = lst.map((e) => `${e.id}`).toString() + let whatsappIdsSplited = lst.map(e => `${e.id}`).toString(); - setWhatsappId(whatsappIdsSplited, true) - -} - -const handleMessage = async ( - msg: any, - wbot: any -): Promise => { + setWhatsappId(whatsappIdsSplited, true); +}; +const handleMessage = async (msg: any, wbot: any): Promise => { if (!msg.fromMe) { + _clear_lst(); - _clear_lst() + let index = lst.findIndex((x: any) => x.id == msg.id.id); - let index = lst.findIndex((x: any) => x.id == msg.id.id) - - console.log('INDEX: ', index) + console.log("INDEX: ", index); if (index == -1) { - // console.log('-----------------> LST: ', lst):q - lst.push({ id: msg.id.id }) + lst.push({ id: msg.id.id }); - setWhatsappId(msg.id.id) + setWhatsappId(msg.id.id); + } else { + console.log("IGNORED ID: ", msg.id.id); - } - else { - console.log('IGNORED ID: ', msg.id.id) - - return + return; } // console.log('LIST OF ID MESSAGE lst: ', lst) - console.log('PASSOU.................................FROM: ', msg.from.split("@")[0], ' | ID: ', msg.id.id) + console.log( + "PASSOU.................................FROM: ", + msg.from.split("@")[0], + " | ID: ", + msg.id.id + ); } - if (!isValidMsg(msg)) { return; } try { - let msgContact: any = wbot.msgContact + let msgContact: any = wbot.msgContact; // let groupContact: Contact | undefined; if (msg.fromMe) { - // console.log('FROM ME: ', msg.fromMe, ' | /\u200e/.test(msg.body[0]: ', (/\u200e/.test(msg.body[0]))) // messages sent automatically by wbot have a special character in front of it @@ -479,14 +471,12 @@ const handleMessage = async ( // console.log('1 --------------> msgContat: ', JSON.parse(JSON.stringify(msgContact))) // console.log(' # msg.type: ', msg.type ) - } else { - // msgContact = await msg.getContact(); // console.log('2 --------------> msgContat: ', JSON.parse(JSON.stringify(msgContact))) - // + // console.log(`\n <<<<<<<<<< RECEIVING MESSAGE: Parcial msg and msgContact info: msgContact.name: ${msgContact.name} @@ -497,15 +487,13 @@ const handleMessage = async ( msg.body: ${msg.body} msg.type: ${msg.type} msg.from: ${msg.from} - msg.to: ${msg.to}\n`) - + msg.to: ${msg.to}\n`); } - // const chat = await msg.getChat(); - const chat = wbot.chat + const chat = wbot.chat; // if(chat.isGroup){ - + // console.log('This message is from a Group and will be ignored!') // return // } @@ -524,8 +512,6 @@ const handleMessage = async ( // groupContact = await verifyContact(msgGroupContact); // } - - const whatsapp = await ShowWhatsAppService(wbot.id!); // const whatsapp = await ShowWhatsAppService(46); @@ -536,47 +522,53 @@ const handleMessage = async ( // console.log('----------> contact: ', JSON.parse(JSON.stringify(contact))) - - - if (unreadMessages === 0 && whatsapp.farewellMessage && whatsapp.farewellMessage === msg.body) return; + if ( + unreadMessages === 0 && + whatsapp.farewellMessage && + whatsapp.farewellMessage === msg.body + ) + return; const ticket = await FindOrCreateTicketService( contact, wbot.id!, - unreadMessages, + unreadMessages // groupContact ); - // + // // await updateTicketCacheByTicketId(ticket.id, {'contact.profilePicUrl': ticket.contact.profilePicUrl}) // Para responder para o cliente pelo mesmo whatsapp que ele enviou a mensagen if (wbot.id != ticket.whatsappId) { - // console.log('PARA RESPONDER PELO MEMOS WHATSAPP wbot.id: ', wbot.id, ' | wbot.status: ', wbot.status) // console.log('WHATSAPP STATUS ticket.whatsappId: ', ticket.whatsappId) try { await ticket.update({ whatsappId: wbot.id }); } catch (error: any) { - console.error('===> Error on wbotMessageListener.ts into handleMessage fuction file: \n', error) + console.error( + "===> Error on wbotMessageListener.ts into handleMessage fuction file: \n", + error + ); throw new AppError(error.message); } - - - } - // + // if (msg.hasMedia) { - await verifyMediaMessage(msg, ticket, contact, wbot.media, wbot.quotedMsg); + await verifyMediaMessage( + msg, + ticket, + contact, + wbot.media, + wbot.quotedMsg + ); } else { - // console.log('>>>>>>> msg.fromMe: ',msg.fromMe ) await verifyMessage(msg, ticket, contact, wbot.quotedMsg); } - if ( !ticket.queue && !chat.isGroup && @@ -587,324 +579,442 @@ const handleMessage = async ( await verifyQueue(wbot, msg, ticket, contact); } + if (msg.fromMe) { + const ticketExpiration = await SettingTicket.findOne({ + where: { key: "ticketExpiration" } + }); + if ( + ticketExpiration && + ticketExpiration.value == "enabled" && + ticketExpiration?.message.trim() == msg.body.trim() + ) { + console.log("*********** TICKET EXPIRATION"); + return; + } + } // O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 } - - if (botInfo.isOnQueue && !msg.fromMe && ticket.userId == botInfo.userIdBot) { - - - if (msg.body === '0') { - - const queue = await ShowQueueService(ticket.queue.id); - - const greetingMessage = `\u200e${queue.greetingMessage}`; - - let options = ""; - - data_ura.forEach((s, index) => { options += `*${index + 1}* - ${s.option}\n` }); - - botSendMessage(ticket, contact, wbot, `${greetingMessage}\n\n${options}\n${final_message.msg}`) - - } - else { - - - // Pega as ultimas 9 opções numericas digitadas pelo cliente em orde DESC - // Consulta apenas mensagens do usuári - - - let lastOption = '' - - let ura_length = data_ura.length - - let indexAttendant = data_ura.findIndex((u) => u.atendente) - - let opt_user_attendant = '-1' - - if (indexAttendant != -1) { - opt_user_attendant = data_ura[indexAttendant].id - } - - // - - let ticket_message = await ShowTicketMessage(ticket.id, true, ura_length, `^[0-${ura_length}}]$`); - - if (ticket_message.length > 1) { - - lastOption = ticket_message[1].body - - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues - - if (queues.length > 1) { - - const index_opt_user_attendant = ticket_message.findIndex((q) => q.body == opt_user_attendant) - const index0 = ticket_message.findIndex((q) => q.body == '0') - - if (index_opt_user_attendant != -1) { - - if (index0 > -1 && index0 < index_opt_user_attendant) { - lastOption = '' - } - else { - lastOption = opt_user_attendant - } - } - - } - - } - - - - - // - - // - - // È numero - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= data_ura.length)) { - - const indexUra = data_ura.findIndex((ura) => ura.id == msg.body.trim()) - - - - if (indexUra != -1) { - - if (data_ura[indexUra].id != opt_user_attendant && lastOption != opt_user_attendant) { - - - - - - // test del - let next = true - - let indexAux = ticket_message.findIndex((e) => e.body == '0') - - let listMessage = null - - if (indexAux != -1) { - - listMessage = ticket_message.slice(0, indexAux) - } - else { - - listMessage = ticket_message - - } - - let id = '' - let subUra = null - - if (listMessage.length > 1) { - - id = listMessage[listMessage.length - 1].body - subUra = data_ura.filter((e) => e.id == id)[0] - - if (subUra && (!subUra.subOptions || subUra.subOptions.length == 0)) { - - listMessage.pop() - - } - - } - - - if (listMessage.length > 1) { - - id = listMessage[listMessage.length - 1].body - subUra = data_ura.filter((e) => e.id == id)[0] - - if (subUra.subOptions && subUra.subOptions.length > 0) { - - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= subUra.subOptions?.length) && subUra.subOptions) { - - - if (subUra.subOptions[+msg.body - 1].responseToClient) { - - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\n${subUra.subOptions[+msg.body - 1].responseToClient}`) - - } - else { - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\n${subUra.subOptions[+msg.body - 1].subOpt}`) - } - - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues - - if (queues.length > 0) { - await botTransferTicket(queues[0], ticket, contact, wbot) - } - else { - console.log('NO QUEUE!') - } - - } - else { - - let options = ""; - let subOptions: any[] = subUra.subOptions - - subOptions?.forEach((s, index) => { options += `*${index + 1}* - ${s.subOpt}\n` }); - - botSendMessage(ticket, contact, wbot, `*${subUra.option}*\n\nDigite um número válido disponível no menu de opções de atendimento abaixo: \n${options}\n\n*0* - Voltar ao menu principal`) - - } - - next = false - - } - - } - - - // - if (next) { - if (data_ura[indexUra].subOptions && data_ura[indexUra].subOptions.length > 0) { - - let options = ""; - let option = data_ura[indexUra].option - let subOptions: any[] = data_ura[indexUra].subOptions - let description = data_ura[indexUra].description - - subOptions?.forEach((s, index) => { options += `*${index + 1}* - ${s.subOpt}\n` }); - - const body = `\u200e${description}:\n${options}` - - botSendMessage(ticket, contact, wbot, `*${option}*\n\n${body}\n\n *0* - Voltar ao menu principal`) - - } - else { - - //test del deletar isso (Usar somente na hit) - if (data_ura[indexUra].closeChat) { - - - const { ticket: res } = await UpdateTicketService({ - ticketData: { 'status': 'closed', 'userId': botInfo.userIdBot }, ticketId: ticket.id - }); - - /////////////////////////////// - const whatsapp = await ShowWhatsAppService(ticket.whatsappId); - - const { farewellMessage } = whatsapp; - - if (farewellMessage) { - await SendWhatsAppMessage({ body: farewellMessage, ticket: res }); - } - /////////////////////////////// - - } - else { - botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) - } - // - - - // botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) - - } - } - - } - else if (data_ura[indexUra].id == opt_user_attendant) { - - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues - - // Se fila for maior que 1 exibi as opções fila para atendimento humano - if (queues.length > 1) { - - let options = ""; - - queues.forEach((queue, index) => { - - options += `*${index + 1}* - ${queue.name}\n`; - - }); - - const body = `\u200eSelecione uma das opções de atendimento abaixo:\n${options}`; - - botSendMessage(ticket, contact, wbot, body) - - } // Para situações onde há apenas uma fila com exclusão da fila do bot, já direciona o cliente para essa fila de atendimento humano - else if (queues.length == 1) { - - await botTransferTicket(queues[0], ticket, contact, wbot) - - botSendMessage(ticket, contact, wbot, `${msg_client_transfer.msg}`) - - } - } - else if (lastOption == opt_user_attendant) { - - const queuesWhatsGreetingMessage = await queuesOutBot(wbot, botInfo.botQueueId) - - const queues = queuesWhatsGreetingMessage.queues - - // É numero - if (!Number.isNaN(Number(msg.body.trim())) && (+msg.body >= 0 && +msg.body <= queues.length)) { - - await botTransferTicket(queues[+msg.body - 1], ticket, contact, wbot) - - botSendMessage(ticket, contact, wbot, `${msg_client_transfer.msg}`) - } - else { - - botSendMessage(ticket, contact, wbot, `Digite um número válido disponível no menu de opções de atendimento\n\n*0* - Voltar ao menu principal`) - - } - } - - - } - - } - else { - - // É numero - if (!Number.isNaN(Number(msg.body.trim()))) { - - botSendMessage(ticket, contact, wbot, `Opção numérica inválida!\nDigite um dos números mostrados no menu de opções\n\n*0* - Voltar ao menu principal`) - - } - else { - - botSendMessage(ticket, contact, wbot, `Digite um número válido disponível no menu de opções\n\n*0* - Voltar ao menu principal`) - - } - - } - - } - - - } - - - if (msg && !msg.fromMe && ticket.status == 'pending') { - - await setMessageAsRead(ticket) - + const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; + + // if ( + // botInfo.isOnQueue && + // !msg.fromMe && + // ticket.userId == botInfo.userIdBot + // ) { + // if (msg.body === "0") { + // const queue = await ShowQueueService(ticket.queue.id); + + // const greetingMessage = `\u200e${queue.greetingMessage}`; + + // let options = ""; + + // data_ura.forEach((s, index) => { + // options += `*${index + 1}* - ${s.option}\n`; + // }); + + // botSendMessage( + // ticket, + // contact, + // wbot, + // `${greetingMessage}\n\n${options}\n${final_message.msg}` + // ); + // } else { + // // Pega as ultimas 9 opções numericas digitadas pelo cliente em orde DESC + // // Consulta apenas mensagens do usuári + + // let lastOption = ""; + + // let ura_length = data_ura.length; + + // let indexAttendant = data_ura.findIndex(u => u.atendente); + + // let opt_user_attendant = "-1"; + + // if (indexAttendant != -1) { + // opt_user_attendant = data_ura[indexAttendant].id; + // } + + // // + + // let ticket_message = await ShowTicketMessage( + // ticket.id, + // true, + // ura_length, + // `^[0-${ura_length}}]$` + // ); + + // if (ticket_message.length > 1) { + // lastOption = ticket_message[1].body; + + // const queuesWhatsGreetingMessage = await queuesOutBot( + // wbot, + // botInfo.botQueueId + // ); + + // const queues = queuesWhatsGreetingMessage.queues; + + // if (queues.length > 1) { + // const index_opt_user_attendant = ticket_message.findIndex( + // q => q.body == opt_user_attendant + // ); + // const index0 = ticket_message.findIndex(q => q.body == "0"); + + // if (index_opt_user_attendant != -1) { + // if (index0 > -1 && index0 < index_opt_user_attendant) { + // lastOption = ""; + // } else { + // lastOption = opt_user_attendant; + // } + // } + // } + // } + + // // + + // // + + // // È numero + // if ( + // !Number.isNaN(Number(msg.body.trim())) && + // +msg.body >= 0 && + // +msg.body <= data_ura.length + // ) { + // const indexUra = data_ura.findIndex(ura => ura.id == msg.body.trim()); + + // if (indexUra != -1) { + // if ( + // data_ura[indexUra].id != opt_user_attendant && + // lastOption != opt_user_attendant + // ) { + // // test del + // let next = true; + + // let indexAux = ticket_message.findIndex(e => e.body == "0"); + + // let listMessage = null; + + // if (indexAux != -1) { + // listMessage = ticket_message.slice(0, indexAux); + // } else { + // listMessage = ticket_message; + // } + + // let id = ""; + // let subUra = null; + + // if (listMessage.length > 1) { + // id = listMessage[listMessage.length - 1].body; + // subUra = data_ura.filter(e => e.id == id)[0]; + + // if ( + // subUra && + // (!subUra.subOptions || subUra.subOptions.length == 0) + // ) { + // listMessage.pop(); + // } + // } + + // if (listMessage.length > 1) { + // id = listMessage[listMessage.length - 1].body; + // subUra = data_ura.filter(e => e.id == id)[0]; + + // if (subUra.subOptions && subUra.subOptions.length > 0) { + // if ( + // !Number.isNaN(Number(msg.body.trim())) && + // +msg.body >= 0 && + // +msg.body <= subUra.subOptions?.length && + // subUra.subOptions + // ) { + // if (subUra.subOptions[+msg.body - 1].responseToClient) { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `*${subUra.option}*\n\n${ + // subUra.subOptions[+msg.body - 1].responseToClient + // }` + // ); + // } else { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `*${subUra.option}*\n\n${ + // subUra.subOptions[+msg.body - 1].subOpt + // }` + // ); + // } + + // const queuesWhatsGreetingMessage = await queuesOutBot( + // wbot, + // botInfo.botQueueId + // ); + + // const queues = queuesWhatsGreetingMessage.queues; + + // if (queues.length > 0) { + // await botTransferTicket(queues[0], ticket, contact, wbot); + // } else { + // console.log("NO QUEUE!"); + // } + // } else { + // let options = ""; + // let subOptions: any[] = subUra.subOptions; + + // subOptions?.forEach((s, index) => { + // options += `*${index + 1}* - ${s.subOpt}\n`; + // }); + + // botSendMessage( + // ticket, + // contact, + // wbot, + // `*${subUra.option}*\n\nDigite um número válido disponível no menu de opções de atendimento abaixo: \n${options}\n\n*0* - Voltar ao menu principal` + // ); + // } + + // next = false; + // } + // } + + // // + // if (next) { + // if ( + // data_ura[indexUra].subOptions && + // data_ura[indexUra].subOptions.length > 0 + // ) { + // let options = ""; + // let option = data_ura[indexUra].option; + // let subOptions: any[] = data_ura[indexUra].subOptions; + // let description = data_ura[indexUra].description; + + // subOptions?.forEach((s, index) => { + // options += `*${index + 1}* - ${s.subOpt}\n`; + // }); + + // const body = `\u200e${description}:\n${options}`; + + // botSendMessage( + // ticket, + // contact, + // wbot, + // `*${option}*\n\n${body}\n\n *0* - Voltar ao menu principal` + // ); + // } else { + // //test del deletar isso (Usar somente na hit) + // if (data_ura[indexUra].closeChat) { + // const { ticket: res } = await UpdateTicketService({ + // ticketData: { + // status: "closed", + // userId: botInfo.userIdBot + // }, + // ticketId: ticket.id + // }); + + // /////////////////////////////// + // const whatsapp = await ShowWhatsAppService( + // ticket.whatsappId + // ); + + // const { farewellMessage } = whatsapp; + + // if (farewellMessage) { + // await SendWhatsAppMessage({ + // body: farewellMessage, + // ticket: res + // }); + // } + // /////////////////////////////// + // } else { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal` + // ); + // } + // // + + // // botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) + // } + // } + // } else if (data_ura[indexUra].id == opt_user_attendant) { + // const queuesWhatsGreetingMessage = await queuesOutBot( + // wbot, + // botInfo.botQueueId + // ); + + // const queues = queuesWhatsGreetingMessage.queues; + + // // Se fila for maior que 1 exibi as opções fila para atendimento humano + // if (queues.length > 1) { + // let options = ""; + + // queues.forEach((queue, index) => { + // options += `*${index + 1}* - ${queue.name}\n`; + // }); + + // const body = `\u200eSelecione uma das opções de atendimento abaixo:\n${options}`; + + // botSendMessage(ticket, contact, wbot, body); + // } // Para situações onde há apenas uma fila com exclusão da fila do bot, já direciona o cliente para essa fila de atendimento humano + // else if (queues.length == 1) { + // await botTransferTicket(queues[0], ticket, contact, wbot); + + // botSendMessage( + // ticket, + // contact, + // wbot, + // `${msg_client_transfer.msg}` + // ); + // } + // } else if (lastOption == opt_user_attendant) { + // const queuesWhatsGreetingMessage = await queuesOutBot( + // wbot, + // botInfo.botQueueId + // ); + + // const queues = queuesWhatsGreetingMessage.queues; + + // // É numero + // if ( + // !Number.isNaN(Number(msg.body.trim())) && + // +msg.body >= 0 && + // +msg.body <= queues.length + // ) { + // await botTransferTicket( + // queues[+msg.body - 1], + // ticket, + // contact, + // wbot + // ); + + // botSendMessage( + // ticket, + // contact, + // wbot, + // `${msg_client_transfer.msg}` + // ); + // } else { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `Digite um número válido disponível no menu de opções de atendimento\n\n*0* - Voltar ao menu principal` + // ); + // } + // } + // } + // } else { + // // É numero + // if (!Number.isNaN(Number(msg.body.trim()))) { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `Opção numérica inválida!\nDigite um dos números mostrados no menu de opções\n\n*0* - Voltar ao menu principal` + // ); + // } else { + // botSendMessage( + // ticket, + // contact, + // wbot, + // `Digite um número válido disponível no menu de opções\n\n*0* - Voltar ao menu principal` + // ); + // } + // } + // } + // } + + if (msg && !msg.fromMe && ticket.status == "pending") { + await setMessageAsRead(ticket); } + const businessTime: any = await BusinessTime(); + + if ( + msg.fromMe && + businessTime && + !businessTime.isWithinRange && + businessTime.message.trim() == msg.body.trim() + ) { + console.log("BUSINESS TIME OUT"); + return; + } + + if (!businessTime.isWithinRange && businessTime.message.trim().length > 0) { + botSendMessage(ticket, businessTime.message); + } } catch (err) { Sentry.captureException(err); - logger.error(`Error handling whatsapp message: Err: ${err}`); + console.log("Error handling whatsapp message: Err: ", err); + logger.error(`Error handling whatsapp message: Err: ${err}`); + } + + async function BusinessTime() { + const outBusinessHours = await SettingTicket.findOne({ + where: { key: "outBusinessHours" } + }); + + let isWithinRange = false; + + if (outBusinessHours && outBusinessHours.value == "enabled") { + const ticketDateTimeUpdate = splitDateTime( + new Date( + _format(new Date(), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const startTime = splitDateTime( + new Date( + _format(new Date(outBusinessHours.startTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const endTime = splitDateTime( + new Date( + _format(new Date(outBusinessHours.endTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const format = "HH:mm:ss"; + const parsedStartTime = parse( + ticketDateTimeUpdate.fullTime, + format, + new Date() + ); + const parsedEndTime = parse(startTime.fullTime, format, new Date()); + const parsedTimeToCheck = parse(endTime.fullTime, format, new Date()); + + const timeInterval = { start: parsedStartTime, end: parsedEndTime }; + + // If the time range spans across different days, handle the date part + if (parsedEndTime < parsedStartTime) { + const nextDay = new Date(parsedStartTime); + nextDay.setDate(nextDay.getDate() + 1); + timeInterval.end = nextDay; + } + + isWithinRange = isWithinInterval(parsedTimeToCheck, timeInterval); + + console.log("Is the time within the range?", isWithinRange); + + return { isWithinRange, message: outBusinessHours.message }; + } } }; const handleMsgAck = async (msg_id: any, ack: any) => { - await new Promise(r => setTimeout(r, 4000)); const io = getIO(); @@ -921,16 +1031,17 @@ const handleMsgAck = async (msg_id: any, ack: any) => { ] }); if (!messageToUpdate) { - console.log(`Not found the MESSAGE ID ${msg_id}to change the ACK into the Message table`) + console.log( + `Not found the MESSAGE ID ${msg_id}to change the ACK into the Message table` + ); return; } await messageToUpdate.update({ ack }); - + io.to(messageToUpdate.ticketId.toString()).emit("appMessage", { action: "update", message: messageToUpdate }); - } catch (err) { Sentry.captureException(err); logger.error(`Error handling message ack. Err: ${err}`); @@ -938,7 +1049,6 @@ const handleMsgAck = async (msg_id: any, ack: any) => { }; const wbotMessageListener = (wbot: Session): void => { - wbot.on("message_create", async msg => { handleMessage(msg, wbot); }); diff --git a/frontend/package.json b/frontend/package.json index a077e60..50b81dc 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -20,6 +20,7 @@ "dotenv": "^16.0.1", "emoji-mart": "^3.0.1", "formik": "^2.2.0", + "formik-material-ui-pickers": "^1.0.0-alpha.1", "i18next": "^19.8.2", "i18next-browser-languagedetector": "^6.0.1", "js-file-download": "^0.4.12", diff --git a/frontend/src/components/ConfigModal/index.js b/frontend/src/components/ConfigModal/index.js new file mode 100644 index 0000000..7c08118 --- /dev/null +++ b/frontend/src/components/ConfigModal/index.js @@ -0,0 +1,304 @@ +import React, { useState, useEffect, } from 'react' +// import * as Yup from 'yup' +import { Formik, Form, Field, } from 'formik' +import { toast } from 'react-toastify' + +import { makeStyles } from '@material-ui/core/styles' +import { green } from '@material-ui/core/colors' + +import { TimePicker } from 'formik-material-ui-pickers' + +import DateFnsUtils from '@date-io/date-fns' + +import ptBrLocale from "date-fns/locale/pt-BR" + + +import { + MuiPickersUtilsProvider, +} from '@material-ui/pickers' + +import { + Dialog, + DialogContent, + DialogTitle, + Button, + DialogActions, + CircularProgress, + TextField, + Switch, + FormControlLabel, +} from '@material-ui/core' + +import api from '../../services/api' +import { i18n } from '../../translate/i18n' +import toastError from '../../errors/toastError' + +const useStyles = makeStyles((theme) => ({ + root: { + display: 'flex', + flexWrap: 'wrap', + }, + + multFieldLine: { + display: 'flex', + '& > *:not(:last-child)': { + marginRight: theme.spacing(1), + }, + }, + + btnWrapper: { + position: 'relative', + }, + + buttonProgress: { + color: green[500], + position: 'absolute', + top: '50%', + left: '50%', + marginTop: -12, + marginLeft: -12, + }, +})) + +// const SessionSchema = Yup.object().shape({ +// name: Yup.string() +// .min(2, 'Too Short!') +// .max(100, 'Too Long!') +// .required('Required'), +// }) + +const ConfigModal = ({ open, onClose, change }) => { + const classes = useStyles() + const initialState = { + startTimeBus: new Date(), + endTimeBus: new Date(), + messageBus: '', + businessTimeEnalbe: false, + ticketTimeExpiration: new Date(), + ticketExpirationMsg: '', + ticketExpirationEnable: false, + } + + const [config, setConfig] = useState(initialState) + + useEffect(() => { + const fetchSession = async () => { + + try { + const { data } = await api.get('/settings') + + setConfig({ + startTimeBus: data.outBusinessHours.startTime, + endTimeBus: data.outBusinessHours.endTime, + messageBus: data.outBusinessHours.message, + businessTimeEnalbe: data.outBusinessHours.value === 'enabled' ? true : false, + ticketTimeExpiration: data.ticketExpiration.startTime, + ticketExpirationMsg: data.ticketExpiration.message, + ticketExpirationEnable: data.ticketExpiration.value === 'enabled' ? true : false + }) + + } catch (err) { + toastError(err) + } + } + fetchSession() + }, [change]) + + const handleSaveConfig = async (values) => { + + values = { + outBusinessHours: { + startTime: values.startTimeBus, + endTime: values.endTimeBus, + message: values.messageBus, + value: values.businessTimeEnalbe ? 'enabled' : 'disabled' + }, + ticketExpiration: { + startTime: values.ticketTimeExpiration, + message: values.ticketExpirationMsg, + value: values.ticketExpirationEnable ? 'enabled' : 'disabled' + } + } + + + try { + + await api.put(`/settings/ticket`, values) + + toast.success('Atualização realizada com sucesso!') + handleClose() + + } catch (err) { + toastError(err) + } + } + + const handleClose = () => { + onClose() + // setConfig(initialState) + } + + return ( +
    + + + Configurações + + + + { + + setTimeout(() => { + handleSaveConfig(values) + actions.setSubmitting(false) + }, 100) + }} + > + {({ values, touched, errors, isSubmitting }) => ( + +
    + + + +
    + + {' '} + + + + } + label={'Ativar/Desativar'} /> +
    + +
    + +
    + +
    +
    + + + + } + label={'Ativar/Desativar'} + /> +
    +
    + +
    + +
    + + + + +
    +
    + )} +
    +
    +
    + ) +} + +export default React.memo(ConfigModal) diff --git a/frontend/src/hooks/useAuth.js/index.js b/frontend/src/hooks/useAuth.js/index.js index 70ffe21..6e26b05 100644 --- a/frontend/src/hooks/useAuth.js/index.js +++ b/frontend/src/hooks/useAuth.js/index.js @@ -76,7 +76,7 @@ const useAuth = () => { const fetchSession = async () => { try { const { data } = await api.get('/settings') - setSetting(data) + setSetting(data.settings) } catch (err) { toastError(err) } diff --git a/frontend/src/pages/Connections/index.js b/frontend/src/pages/Connections/index.js index a8c5fe4..3e188ee 100644 --- a/frontend/src/pages/Connections/index.js +++ b/frontend/src/pages/Connections/index.js @@ -6,6 +6,9 @@ import openSocket from 'socket.io-client' import { makeStyles } from '@material-ui/core/styles' import { green } from '@material-ui/core/colors' + +import Settings from "@material-ui/icons/Settings"; + import { Button, TableBody, @@ -47,6 +50,7 @@ import toastError from '../../errors/toastError' //-------- import { AuthContext } from '../../context/Auth/AuthContext' import { Can } from '../../components/Can' +import ConfigModal from '../../components/ConfigModal' const useStyles = makeStyles((theme) => ({ mainPaper: { @@ -107,6 +111,7 @@ const Connections = () => { const { whatsApps, loading } = useContext(WhatsAppsContext) const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false) + const [configModalOpen, setConfigModalOpen] = useState(false) const [qrModalOpen, setQrModalOpen] = useState(false) const [selectedWhatsApp, setSelectedWhatsApp] = useState(null) const [confirmModalOpen, setConfirmModalOpen] = useState(false) @@ -134,7 +139,7 @@ const Connections = () => { const fetchSession = async () => { try { const { data } = await api.get('/settings') - setSettings(data) + setSettings(data.settings) } catch (err) { toastError(err) } @@ -205,6 +210,13 @@ const Connections = () => { setWhatsAppModalOpen(true) } + const handleOpenConfigModal = () => { + setConfigModalOpen(true) + } + + const handleCloseConfigModal = () => { + setConfigModalOpen(false) + } const handleCloseWhatsAppModal = useCallback(() => { setWhatsAppModalOpen(false) setSelectedWhatsApp(null) @@ -307,17 +319,17 @@ const Connections = () => { {(whatsApp.status === 'CONNECTED' || whatsApp.status === 'PAIRING' || whatsApp.status === 'TIMEOUT') && ( - - )} + + )} {whatsApp.status === 'OPENING' && ( { settings.length > 0 && getSettingValue('editURA') && getSettingValue('editURA') === - 'enabled') | - (user.profile === 'master') ? ( + 'enabled') | + (user.profile === 'master') ? ( diff --git a/frontend/src/pages/Queues/index.js b/frontend/src/pages/Queues/index.js index 99b6eab..85144e2 100644 --- a/frontend/src/pages/Queues/index.js +++ b/frontend/src/pages/Queues/index.js @@ -121,7 +121,7 @@ const Queues = () => { const fetchSession = async () => { try { const { data } = await api.get('/settings') - setSettings(data) + setSettings(data.settings) } catch (err) { toastError(err) } diff --git a/frontend/src/pages/Settings/index.js b/frontend/src/pages/Settings/index.js index ab79873..2dc8891 100644 --- a/frontend/src/pages/Settings/index.js +++ b/frontend/src/pages/Settings/index.js @@ -52,7 +52,7 @@ const Settings = () => { const fetchSession = async () => { try { const { data } = await api.get('/settings') - setSettings(data) + setSettings(data.settings) } catch (err) { toastError(err) } From f778a928c815e499ccb2d32e9fc52b4370c415f6 Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 8 Aug 2023 12:31:25 -0300 Subject: [PATCH 07/19] =?UTF-8?q?Corre=C3=A7=C3=A3o=20para=20evitar=20que?= =?UTF-8?q?=20o=20ticket=20expiration=20gere=20um=20novo=20ticket?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WbotServices/wbotMessageListener.ts | 28 +++++++++---------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index c85e2ab..b6b0a8e 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -452,6 +452,19 @@ const handleMessage = async (msg: any, wbot: any): Promise => { // let groupContact: Contact | undefined; if (msg.fromMe) { + const ticketExpiration = await SettingTicket.findOne({ + where: { key: "ticketExpiration" } + }); + + if ( + ticketExpiration && + ticketExpiration.value == "enabled" && + ticketExpiration?.message.trim() == msg.body.trim() + ) { + console.log("*********** TICKET EXPIRATION"); + return; + } + // console.log('FROM ME: ', msg.fromMe, ' | /\u200e/.test(msg.body[0]: ', (/\u200e/.test(msg.body[0]))) // messages sent automatically by wbot have a special character in front of it @@ -579,21 +592,6 @@ const handleMessage = async (msg: any, wbot: any): Promise => { await verifyQueue(wbot, msg, ticket, contact); } - if (msg.fromMe) { - const ticketExpiration = await SettingTicket.findOne({ - where: { key: "ticketExpiration" } - }); - - if ( - ticketExpiration && - ticketExpiration.value == "enabled" && - ticketExpiration?.message.trim() == msg.body.trim() - ) { - console.log("*********** TICKET EXPIRATION"); - return; - } - } - // O bot interage com o cliente e encaminha o atendimento para fila de atendende quando o usuário escolhe a opção falar com atendente //Habilitar esse caso queira usar o bot From 4ee662f4ff1004a1a841b45ec21f08ff23c58e0d Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 8 Aug 2023 14:01:02 -0300 Subject: [PATCH 08/19] =?UTF-8?q?remo=C3=A7=C3=A3o=20de=20codigo=20desativ?= =?UTF-8?q?ado=20de=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../WbotServices/wbotMessageListener.ts | 333 +----------------- 1 file changed, 2 insertions(+), 331 deletions(-) diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index b6b0a8e..e6bd9de 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -596,337 +596,8 @@ const handleMessage = async (msg: any, wbot: any): Promise => { //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; - - // if ( - // botInfo.isOnQueue && - // !msg.fromMe && - // ticket.userId == botInfo.userIdBot - // ) { - // if (msg.body === "0") { - // const queue = await ShowQueueService(ticket.queue.id); - - // const greetingMessage = `\u200e${queue.greetingMessage}`; - - // let options = ""; - - // data_ura.forEach((s, index) => { - // options += `*${index + 1}* - ${s.option}\n`; - // }); - - // botSendMessage( - // ticket, - // contact, - // wbot, - // `${greetingMessage}\n\n${options}\n${final_message.msg}` - // ); - // } else { - // // Pega as ultimas 9 opções numericas digitadas pelo cliente em orde DESC - // // Consulta apenas mensagens do usuári - - // let lastOption = ""; - - // let ura_length = data_ura.length; - - // let indexAttendant = data_ura.findIndex(u => u.atendente); - - // let opt_user_attendant = "-1"; - - // if (indexAttendant != -1) { - // opt_user_attendant = data_ura[indexAttendant].id; - // } - - // // - - // let ticket_message = await ShowTicketMessage( - // ticket.id, - // true, - // ura_length, - // `^[0-${ura_length}}]$` - // ); - - // if (ticket_message.length > 1) { - // lastOption = ticket_message[1].body; - - // const queuesWhatsGreetingMessage = await queuesOutBot( - // wbot, - // botInfo.botQueueId - // ); - - // const queues = queuesWhatsGreetingMessage.queues; - - // if (queues.length > 1) { - // const index_opt_user_attendant = ticket_message.findIndex( - // q => q.body == opt_user_attendant - // ); - // const index0 = ticket_message.findIndex(q => q.body == "0"); - - // if (index_opt_user_attendant != -1) { - // if (index0 > -1 && index0 < index_opt_user_attendant) { - // lastOption = ""; - // } else { - // lastOption = opt_user_attendant; - // } - // } - // } - // } - - // // - - // // - - // // È numero - // if ( - // !Number.isNaN(Number(msg.body.trim())) && - // +msg.body >= 0 && - // +msg.body <= data_ura.length - // ) { - // const indexUra = data_ura.findIndex(ura => ura.id == msg.body.trim()); - - // if (indexUra != -1) { - // if ( - // data_ura[indexUra].id != opt_user_attendant && - // lastOption != opt_user_attendant - // ) { - // // test del - // let next = true; - - // let indexAux = ticket_message.findIndex(e => e.body == "0"); - - // let listMessage = null; - - // if (indexAux != -1) { - // listMessage = ticket_message.slice(0, indexAux); - // } else { - // listMessage = ticket_message; - // } - - // let id = ""; - // let subUra = null; - - // if (listMessage.length > 1) { - // id = listMessage[listMessage.length - 1].body; - // subUra = data_ura.filter(e => e.id == id)[0]; - - // if ( - // subUra && - // (!subUra.subOptions || subUra.subOptions.length == 0) - // ) { - // listMessage.pop(); - // } - // } - - // if (listMessage.length > 1) { - // id = listMessage[listMessage.length - 1].body; - // subUra = data_ura.filter(e => e.id == id)[0]; - - // if (subUra.subOptions && subUra.subOptions.length > 0) { - // if ( - // !Number.isNaN(Number(msg.body.trim())) && - // +msg.body >= 0 && - // +msg.body <= subUra.subOptions?.length && - // subUra.subOptions - // ) { - // if (subUra.subOptions[+msg.body - 1].responseToClient) { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `*${subUra.option}*\n\n${ - // subUra.subOptions[+msg.body - 1].responseToClient - // }` - // ); - // } else { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `*${subUra.option}*\n\n${ - // subUra.subOptions[+msg.body - 1].subOpt - // }` - // ); - // } - - // const queuesWhatsGreetingMessage = await queuesOutBot( - // wbot, - // botInfo.botQueueId - // ); - - // const queues = queuesWhatsGreetingMessage.queues; - - // if (queues.length > 0) { - // await botTransferTicket(queues[0], ticket, contact, wbot); - // } else { - // console.log("NO QUEUE!"); - // } - // } else { - // let options = ""; - // let subOptions: any[] = subUra.subOptions; - - // subOptions?.forEach((s, index) => { - // options += `*${index + 1}* - ${s.subOpt}\n`; - // }); - - // botSendMessage( - // ticket, - // contact, - // wbot, - // `*${subUra.option}*\n\nDigite um número válido disponível no menu de opções de atendimento abaixo: \n${options}\n\n*0* - Voltar ao menu principal` - // ); - // } - - // next = false; - // } - // } - - // // - // if (next) { - // if ( - // data_ura[indexUra].subOptions && - // data_ura[indexUra].subOptions.length > 0 - // ) { - // let options = ""; - // let option = data_ura[indexUra].option; - // let subOptions: any[] = data_ura[indexUra].subOptions; - // let description = data_ura[indexUra].description; - - // subOptions?.forEach((s, index) => { - // options += `*${index + 1}* - ${s.subOpt}\n`; - // }); - - // const body = `\u200e${description}:\n${options}`; - - // botSendMessage( - // ticket, - // contact, - // wbot, - // `*${option}*\n\n${body}\n\n *0* - Voltar ao menu principal` - // ); - // } else { - // //test del deletar isso (Usar somente na hit) - // if (data_ura[indexUra].closeChat) { - // const { ticket: res } = await UpdateTicketService({ - // ticketData: { - // status: "closed", - // userId: botInfo.userIdBot - // }, - // ticketId: ticket.id - // }); - - // /////////////////////////////// - // const whatsapp = await ShowWhatsAppService( - // ticket.whatsappId - // ); - - // const { farewellMessage } = whatsapp; - - // if (farewellMessage) { - // await SendWhatsAppMessage({ - // body: farewellMessage, - // ticket: res - // }); - // } - // /////////////////////////////// - // } else { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal` - // ); - // } - // // - - // // botSendMessage(ticket, contact, wbot, `${data_ura[indexUra].description}\n\n *0* - Voltar ao menu principal`) - // } - // } - // } else if (data_ura[indexUra].id == opt_user_attendant) { - // const queuesWhatsGreetingMessage = await queuesOutBot( - // wbot, - // botInfo.botQueueId - // ); - - // const queues = queuesWhatsGreetingMessage.queues; - - // // Se fila for maior que 1 exibi as opções fila para atendimento humano - // if (queues.length > 1) { - // let options = ""; - - // queues.forEach((queue, index) => { - // options += `*${index + 1}* - ${queue.name}\n`; - // }); - - // const body = `\u200eSelecione uma das opções de atendimento abaixo:\n${options}`; - - // botSendMessage(ticket, contact, wbot, body); - // } // Para situações onde há apenas uma fila com exclusão da fila do bot, já direciona o cliente para essa fila de atendimento humano - // else if (queues.length == 1) { - // await botTransferTicket(queues[0], ticket, contact, wbot); - - // botSendMessage( - // ticket, - // contact, - // wbot, - // `${msg_client_transfer.msg}` - // ); - // } - // } else if (lastOption == opt_user_attendant) { - // const queuesWhatsGreetingMessage = await queuesOutBot( - // wbot, - // botInfo.botQueueId - // ); - - // const queues = queuesWhatsGreetingMessage.queues; - - // // É numero - // if ( - // !Number.isNaN(Number(msg.body.trim())) && - // +msg.body >= 0 && - // +msg.body <= queues.length - // ) { - // await botTransferTicket( - // queues[+msg.body - 1], - // ticket, - // contact, - // wbot - // ); - - // botSendMessage( - // ticket, - // contact, - // wbot, - // `${msg_client_transfer.msg}` - // ); - // } else { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `Digite um número válido disponível no menu de opções de atendimento\n\n*0* - Voltar ao menu principal` - // ); - // } - // } - // } - // } else { - // // É numero - // if (!Number.isNaN(Number(msg.body.trim()))) { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `Opção numérica inválida!\nDigite um dos números mostrados no menu de opções\n\n*0* - Voltar ao menu principal` - // ); - // } else { - // botSendMessage( - // ticket, - // contact, - // wbot, - // `Digite um número válido disponível no menu de opções\n\n*0* - Voltar ao menu principal` - // ); - // } - // } - // } - // } + const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; + if (msg && !msg.fromMe && ticket.status == "pending") { await setMessageAsRead(ticket); From 18db49c88cf3d726f7fa612ce62e06ceff544ab2 Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 8 Aug 2023 14:02:51 -0300 Subject: [PATCH 09/19] =?UTF-8?q?desativa=C3=A7ao=20de=20codigo=20de=20bot?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/services/WbotServices/wbotMessageListener.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index e6bd9de..426b119 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -596,7 +596,7 @@ const handleMessage = async (msg: any, wbot: any): Promise => { //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; + // const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; if (msg && !msg.fromMe && ticket.status == "pending") { From 9125be43def8b9d26b6ec7f9915577c415b284a5 Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 9 Aug 2023 08:30:03 -0300 Subject: [PATCH 10/19] =?UTF-8?q?finaliza=C3=A7=C3=A3o=20do=20recurso=20pa?= =?UTF-8?q?ra=20envio=20de=20mensagem=20em=20finais=20de=20semana=20e=20fe?= =?UTF-8?q?riados?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/package.json | 4 +- backend/src/controllers/SettingController.ts | 58 ++++- ...230808210411-add-setting-ticket-weekend.ts | 34 +++ ...230808210840-add-setting-ticket-holiday.ts | 25 +++ ...85716-add-setting-ticket-weekend-enable.ts | 25 +++ backend/src/helpers/AutoCloseTickets.ts | 4 +- .../WbotServices/wbotMessageListener.ts | 101 ++++++++- frontend/package.json | 7 +- frontend/src/components/ConfigModal/index.js | 210 ++++++++++++++++-- 9 files changed, 427 insertions(+), 41 deletions(-) create mode 100644 backend/src/database/seeds/20230808210411-add-setting-ticket-weekend.ts create mode 100644 backend/src/database/seeds/20230808210840-add-setting-ticket-holiday.ts create mode 100644 backend/src/database/seeds/20230809085716-add-setting-ticket-weekend-enable.ts diff --git a/backend/package.json b/backend/package.json index 1d55190..f9c9b6d 100644 --- a/backend/package.json +++ b/backend/package.json @@ -21,8 +21,8 @@ "bcryptjs": "^2.4.3", "cookie-parser": "^1.4.5", "cors": "^2.8.5", - "date-fns": "^2.16.1", - "date-fns-tz": "^1.3.4", + "date-fns": "^2.30.0", + "date-fns-tz": "^1.3.8", "dotenv": "^8.2.0", "express": "^4.17.1", "express-async-errors": "^3.1.1", diff --git a/backend/src/controllers/SettingController.ts b/backend/src/controllers/SettingController.ts index c8cb940..938acf8 100644 --- a/backend/src/controllers/SettingController.ts +++ b/backend/src/controllers/SettingController.ts @@ -14,21 +14,24 @@ export const index = async (req: Request, res: Response): Promise => { // } const settings = await ListSettingsService(); - const outBusinessHours = await SettingTicket.findOne({ - where: { key: "outBusinessHours" } - }); - const ticketExpiration = await SettingTicket.findOne({ - where: { key: "ticketExpiration" } - }); - return res.status(200).json({ settings, outBusinessHours, ticketExpiration }); + const config = await SettingTicket.findAll(); + + return res.status(200).json({ settings, config }); }; export const updateTicketSettings = async ( req: Request, res: Response ): Promise => { - const { outBusinessHours, ticketExpiration } = req.body; + const { + outBusinessHours, + ticketExpiration, + weekend, + saturday, + sunday, + holiday + } = req.body; if (outBusinessHours && Object.keys(outBusinessHours).length > 0) { await updateSettingTicket({ @@ -44,7 +47,44 @@ export const updateTicketSettings = async ( }); } - return res.status(200).json({ outBusinessHours, ticketExpiration }); + if (weekend && Object.keys(weekend).length > 0) { + await updateSettingTicket({ + ...weekend, + key: "weekend" + }); + } + + if (saturday && Object.keys(saturday).length > 0) { + await updateSettingTicket({ + ...saturday, + key: "saturday" + }); + } + + if (sunday && Object.keys(sunday).length > 0) { + await updateSettingTicket({ + ...sunday, + key: "sunday" + }); + } + + if (holiday && Object.keys(holiday).length > 0) { + await updateSettingTicket({ + ...holiday, + key: "holiday" + }); + } + + return res + .status(200) + .json({ + outBusinessHours, + ticketExpiration, + weekend, + saturday, + sunday, + holiday + }); }; export const update = async ( diff --git a/backend/src/database/seeds/20230808210411-add-setting-ticket-weekend.ts b/backend/src/database/seeds/20230808210411-add-setting-ticket-weekend.ts new file mode 100644 index 0000000..8ffa27d --- /dev/null +++ b/backend/src/database/seeds/20230808210411-add-setting-ticket-weekend.ts @@ -0,0 +1,34 @@ +import { QueryInterface } from "sequelize" + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "SettingTickets", + [ + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "saturday", + createdAt: new Date(), + updatedAt: new Date() + }, + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "sunday", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("SettingTickets", {}) + } +} diff --git a/backend/src/database/seeds/20230808210840-add-setting-ticket-holiday.ts b/backend/src/database/seeds/20230808210840-add-setting-ticket-holiday.ts new file mode 100644 index 0000000..efd73ce --- /dev/null +++ b/backend/src/database/seeds/20230808210840-add-setting-ticket-holiday.ts @@ -0,0 +1,25 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "SettingTickets", + [ + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "holiday", + createdAt: new Date(), + updatedAt: new Date() + }, + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("SettingTickets", {}); + } +}; diff --git a/backend/src/database/seeds/20230809085716-add-setting-ticket-weekend-enable.ts b/backend/src/database/seeds/20230809085716-add-setting-ticket-weekend-enable.ts new file mode 100644 index 0000000..48fd2db --- /dev/null +++ b/backend/src/database/seeds/20230809085716-add-setting-ticket-weekend-enable.ts @@ -0,0 +1,25 @@ +import { QueryInterface } from "sequelize"; + +module.exports = { + up: (queryInterface: QueryInterface) => { + return queryInterface.bulkInsert( + "SettingTickets", + [ + { + message: "", + startTime: new Date(), + endTime: new Date(), + value: "disabled", + key: "weekend", + createdAt: new Date(), + updatedAt: new Date() + } + ], + {} + ); + }, + + down: (queryInterface: QueryInterface) => { + return queryInterface.bulkDelete("SettingTickets", {}); + } +}; diff --git a/backend/src/helpers/AutoCloseTickets.ts b/backend/src/helpers/AutoCloseTickets.ts index 2948035..4074c37 100644 --- a/backend/src/helpers/AutoCloseTickets.ts +++ b/backend/src/helpers/AutoCloseTickets.ts @@ -39,14 +39,14 @@ const AutoCloseTickets = async () => { const seconds = timeStringToSeconds(startTime.fullTime); - console.log("Ticket seconds: ", seconds); + // console.log("Ticket seconds: ", seconds); let tickets: any = await ListTicketTimeLife({ timeseconds: seconds, status: "open" }); - console.log("tickets: ", tickets); + // console.log("tickets: ", tickets); for (let i = 0; i < tickets.length; i++) { diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 426b119..d5dfae9 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -11,10 +11,15 @@ import { format as _format, isWithinInterval, parse, - subMinutes + subMinutes, + isSaturday, + isSunday, + parseISO } from "date-fns"; import ptBR from "date-fns/locale/pt-BR"; +import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz"; + import { Contact as WbotContact, Message as WbotMessage, @@ -596,13 +601,103 @@ const handleMessage = async (msg: any, wbot: any): Promise => { //Habilitar esse caso queira usar o bot // const botInfo = await BotIsOnQueue('botqueue') - // const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; - + // const botInfo = { isOnQueue: false, botQueueId: 0, userIdBot: 0 }; if (msg && !msg.fromMe && ticket.status == "pending") { await setMessageAsRead(ticket); } + // MESSAGE TO HOLIDAY + const holiday = await SettingTicket.findOne({ + where: { key: "holiday" } + }); + + if ( + holiday && + holiday.value == "enabled" && + holiday.message?.trim()?.length > 0 + ) { + const startTime = splitDateTime( + new Date( + _format(new Date(holiday.startTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const currentDate = splitDateTime( + new Date( + _format(new Date(), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + if (msg.fromMe && holiday && holiday.message.trim() == msg.body.trim()) { + console.log("HOLIDAY DAY"); + return; + } + + if (currentDate.fullDate == startTime.fullDate) { + botSendMessage(ticket, holiday.message); + return; + } + } + + // MESSAGES TO SATURDAY OR SUNDAY + const weekend = await SettingTicket.findOne({ + where: { key: "weekend" } + }); + + if ( + weekend && + weekend.value == "enabled" && + weekend.message?.trim()?.length > 0 + ) { + if (msg.fromMe && weekend.message.trim() == msg.body.trim()) { + console.log("SATURDAY OR SUNDAY DATE"); + return; + } + + // Specify your desired timezone + const brazilTimeZone = "America/Sao_Paulo"; + + const currentDateUtc = new Date(); + + // Convert UTC date to Brazil time zone + const currentDate = utcToZonedTime(currentDateUtc, brazilTimeZone); + + // Format the date using the desired format + const formattedDate = _format(currentDate, "yyyy-MM-dd HH:mm:ssXXX"); + + const parsedDate = parseISO(formattedDate); + + // Convert parsed date to Brazil time zone + const localDate = utcToZonedTime(parsedDate, brazilTimeZone); + + // Check if it's Saturday or Sunday + if (isSaturday(localDate)) { + const saturday = await SettingTicket.findOne({ + where: { key: "saturday" } + }); + + if (saturday && saturday.value == "enabled") { + botSendMessage(ticket, weekend.message); + return; + } + } else if (isSunday(localDate)) { + const sunday = await SettingTicket.findOne({ + where: { key: "sunday" } + }); + + if (sunday && sunday.value == "enabled") { + botSendMessage(ticket, weekend.message); + return; + } + } + } + + // MESSAGE TO BUSINESS TIME const businessTime: any = await BusinessTime(); if ( diff --git a/frontend/package.json b/frontend/package.json index 50b81dc..681cd4b 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -4,13 +4,13 @@ "private": true, "dependencies": { "@date-io/date-fns": "^1.3.13", - "@emotion/react": "^11.7.1", - "@emotion/styled": "^11.6.0", + "@emotion/react": "^11.11.1", + "@emotion/styled": "^11.11.0", "@material-ui/core": "^4.12.1", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.56", "@material-ui/pickers": "^3.3.10", - "@mui/material": "^5.3.0", + "@mui/material": "^5.14.4", "@mui/x-data-grid": "^5.3.0", "@testing-library/jest-dom": "^5.11.4", "@testing-library/react": "^11.0.4", @@ -31,6 +31,7 @@ "react": "^17.0.2", "react-color": "^2.19.3", "react-csv": "^2.2.2", + "react-datepicker": "^4.16.0", "react-dom": "^17.0.2", "react-modal-image": "^2.5.0", "react-router-dom": "^5.2.0", diff --git a/frontend/src/components/ConfigModal/index.js b/frontend/src/components/ConfigModal/index.js index 7c08118..2187fdc 100644 --- a/frontend/src/components/ConfigModal/index.js +++ b/frontend/src/components/ConfigModal/index.js @@ -4,15 +4,16 @@ import { Formik, Form, Field, } from 'formik' import { toast } from 'react-toastify' import { makeStyles } from '@material-ui/core/styles' -import { green } from '@material-ui/core/colors' +import { green } from '@material-ui/core/colors' -import { TimePicker } from 'formik-material-ui-pickers' +import { TimePicker, DatePicker } from 'formik-material-ui-pickers' import DateFnsUtils from '@date-io/date-fns' import ptBrLocale from "date-fns/locale/pt-BR" + import { MuiPickersUtilsProvider, } from '@material-ui/pickers' @@ -73,10 +74,17 @@ const ConfigModal = ({ open, onClose, change }) => { startTimeBus: new Date(), endTimeBus: new Date(), messageBus: '', - businessTimeEnalbe: false, + businessTimeEnable: false, ticketTimeExpiration: new Date(), ticketExpirationMsg: '', ticketExpirationEnable: false, + holidayDate: new Date(), + holidayDateEnable: false, + holidayDateMessage: '', + checkboxSundayValue: false, + checkboxSaturdayValue: false, + weekendMessage: '', + enableWeekendMessage: false } const [config, setConfig] = useState(initialState) @@ -87,14 +95,35 @@ const ConfigModal = ({ open, onClose, change }) => { try { const { data } = await api.get('/settings') + console.log('data.config: ', data.config) + + const outBusinessHours = data.config.find((c) => c.key == "outBusinessHours") + const ticketExpiration = data.config.find((c) => c.key == "ticketExpiration") + const saturday = data.config.find((c) => c.key == "saturday") + const sunday = data.config.find((c) => c.key == "sunday") + const weekend = data.config.find((c) => c.key == "weekend") + + + const holiday = data.config.find((c) => c.key == "holiday") + setConfig({ - startTimeBus: data.outBusinessHours.startTime, - endTimeBus: data.outBusinessHours.endTime, - messageBus: data.outBusinessHours.message, - businessTimeEnalbe: data.outBusinessHours.value === 'enabled' ? true : false, - ticketTimeExpiration: data.ticketExpiration.startTime, - ticketExpirationMsg: data.ticketExpiration.message, - ticketExpirationEnable: data.ticketExpiration.value === 'enabled' ? true : false + startTimeBus: outBusinessHours.startTime, + endTimeBus: outBusinessHours.endTime, + messageBus: outBusinessHours.message, + businessTimeEnable: outBusinessHours.value === 'enabled' ? true : false, + + ticketTimeExpiration: ticketExpiration.startTime, + ticketExpirationMsg: ticketExpiration.message, + ticketExpirationEnable: ticketExpiration.value === 'enabled' ? true : false, + + checkboxSaturdayValue: saturday.value === 'enabled' ? true : false, + checkboxSundayValue: sunday.value === 'enabled' ? true : false, + weekendMessage: weekend.message, + enableWeekendMessage: weekend.value === 'enabled' ? true : false, + + holidayDate: holiday.startTime, + holidayDateMessage: holiday.message, + holidayDateEnable: holiday.value === 'enabled' ? true : false, }) } catch (err) { @@ -111,19 +140,35 @@ const ConfigModal = ({ open, onClose, change }) => { startTime: values.startTimeBus, endTime: values.endTimeBus, message: values.messageBus, - value: values.businessTimeEnalbe ? 'enabled' : 'disabled' + value: values.businessTimeEnable ? 'enabled' : 'disabled' }, ticketExpiration: { startTime: values.ticketTimeExpiration, message: values.ticketExpirationMsg, value: values.ticketExpirationEnable ? 'enabled' : 'disabled' + }, + weekend: { + message: values.weekendMessage, + value: values.enableWeekendMessage ? 'enabled' : 'disabled' + }, + saturday:{ + value: values.checkboxSaturdayValue ? 'enabled' : 'disabled' + }, + sunday: { + value: values.checkboxSundayValue ? 'enabled' : 'disabled' + }, + holiday: { + startTime: values.holidayDate, + message: values.holidayDateMessage, + value: values.holidayDateEnable ? 'enabled' : 'disabled' } + } - try { - - await api.put(`/settings/ticket`, values) + try { + + await api.put(`/settings/ticket`, values) toast.success('Atualização realizada com sucesso!') handleClose() @@ -157,10 +202,10 @@ const ConfigModal = ({ open, onClose, change }) => { enableReinitialize={true} // validationSchema={SessionSchema} onSubmit={(values, actions) => { - - setTimeout(() => { - handleSaveConfig(values) - actions.setSubmitting(false) + + setTimeout(() => { + handleSaveConfig(values) + actions.setSubmitting(false) }, 100) }} > @@ -196,8 +241,8 @@ const ConfigModal = ({ open, onClose, change }) => { } label={'Ativar/Desativar'} /> @@ -223,8 +268,108 @@ const ConfigModal = ({ open, onClose, change }) => { /> +
    -
    + + + {/* Saturday and Sunday date */} +
    +
    + + + +
    + + + } + label={'Ativar/Desativar'} + /> +
    +
    + +
    + +
    + + {/* Holiday date */} +
    + + + + + } + label={'Ativar/Desativar'} + /> +
    +
    + +
    + + + + + + +
    +
    { openTo="hours" views={['hours', 'minutes',]} format="HH:mm" - /> + /> { ) } + + +const TimePickerField = ({ field, form, ...other }) => { + const { name, value } = field + + const handleChange = (time) => { + form.setFieldValue(name, time, true) + } + + return ( + + ) +} + + export default React.memo(ConfigModal) From b3ac76e340e032ac3983960adbfa3fc97f44511d Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 9 Aug 2023 10:24:11 -0300 Subject: [PATCH 11/19] =?UTF-8?q?Refatora=C3=A7=C3=A3o=20do=20codigo=20de?= =?UTF-8?q?=20configura=C3=A7=C3=A3o=20de=20tickets?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/helpers/TicketConfig.ts | 183 ++++++++++++++++ .../WbotServices/wbotMessageListener.ts | 195 ++++-------------- frontend/src/components/ConfigModal/index.js | 8 +- 3 files changed, 224 insertions(+), 162 deletions(-) create mode 100644 backend/src/helpers/TicketConfig.ts diff --git a/backend/src/helpers/TicketConfig.ts b/backend/src/helpers/TicketConfig.ts new file mode 100644 index 0000000..830646a --- /dev/null +++ b/backend/src/helpers/TicketConfig.ts @@ -0,0 +1,183 @@ +import SettingTicket from "../models/SettingTicket"; +import { splitDateTime } from "./SplitDateTime"; +import { utcToZonedTime, zonedTimeToUtc } from "date-fns-tz"; + +import { + format as _format, + isWithinInterval, + parse, + subMinutes, + isSaturday, + isSunday, + parseISO +} from "date-fns"; +import ptBR from "date-fns/locale/pt-BR"; + +const isHoliday = async () => { + let obj = { set: false, msg: "" }; + + const holiday = await SettingTicket.findOne({ + where: { key: "holiday" } + }); + + if ( + holiday && + holiday.value == "enabled" && + holiday.message?.trim()?.length > 0 + ) { + const startTime = splitDateTime( + new Date( + _format(new Date(holiday.startTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const currentDate = splitDateTime( + new Date( + _format(new Date(), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + if (currentDate.fullDate == startTime.fullDate) { + obj.set = true; + obj.msg = holiday.message.trim(); + } + } + + return obj; +}; + +const isWeekend = async () => { + let obj = { set: false, msg: "" }; + + const weekend = await SettingTicket.findOne({ + where: { key: "weekend" } + }); + + if ( + weekend && + weekend.value == "enabled" && + weekend.message?.trim()?.length > 0 + ) { + + // Specify your desired timezone + const brazilTimeZone = "America/Sao_Paulo"; + + const currentDateUtc = new Date(); + + // Convert UTC date to Brazil time zone + const currentDate = utcToZonedTime(currentDateUtc, brazilTimeZone); + + // Format the date using the desired format + const formattedDate = _format(currentDate, "yyyy-MM-dd HH:mm:ssXXX"); + + const parsedDate = parseISO(formattedDate); + + // Convert parsed date to Brazil time zone + const localDate = utcToZonedTime(parsedDate, brazilTimeZone); + + // Check if it's Saturday or Sunday + if (isSaturday(localDate)) { + const saturday = await SettingTicket.findOne({ + where: { key: "saturday" } + }); + + if (saturday && saturday.value == "enabled") { + // botSendMessage(ticket, weekend.message); + obj.set = true; + obj.msg = weekend.message; + } + } else if (isSunday(localDate)) { + const sunday = await SettingTicket.findOne({ + where: { key: "sunday" } + }); + + if (sunday && sunday.value == "enabled") { + // botSendMessage(ticket, weekend.message); + obj.set = true; + obj.msg = weekend.message; + } + } + else{ + // obj.set = true; + // obj.msg = weekend.message; + } + + return obj; + } +}; + +async function isOutBusinessTime() { + let obj = { set: false, msg: "" }; + + const outBusinessHours = await SettingTicket.findOne({ + where: { key: "outBusinessHours" } + }); + + let isWithinRange = false; + + if ( + outBusinessHours && + outBusinessHours.value == "enabled" && + outBusinessHours?.message?.trim()?.length > 0 + ) { + const ticketDateTimeUpdate = splitDateTime( + new Date( + _format(new Date(), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const startTime = splitDateTime( + new Date( + _format(new Date(outBusinessHours.startTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const endTime = splitDateTime( + new Date( + _format(new Date(outBusinessHours.endTime), "yyyy-MM-dd HH:mm:ss", { + locale: ptBR + }) + ) + ); + + const format = "HH:mm:ss"; + const parsedStartTime = parse( + ticketDateTimeUpdate.fullTime, + format, + new Date() + ); + const parsedEndTime = parse(startTime.fullTime, format, new Date()); + const parsedTimeToCheck = parse(endTime.fullTime, format, new Date()); + const timeInterval = { start: parsedStartTime, end: parsedEndTime }; + + // If the time range spans across different days, handle the date part + if (parsedEndTime < parsedStartTime) { + const nextDay = new Date(parsedStartTime); + nextDay.setDate(nextDay.getDate() + 1); + timeInterval.end = nextDay; + } + + isWithinRange = isWithinInterval(parsedTimeToCheck, timeInterval); + + if (!isWithinRange) { + obj.set = true; + obj.msg = outBusinessHours.message; + } + } + + return obj; +} + +export { + isWeekend, + isHoliday, + isOutBusinessTime +}; diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index d5dfae9..7e812b6 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -7,6 +7,12 @@ import { copyFolder } from "../../helpers/CopyFolder"; import { removeDir } from "../../helpers/DeleteDirectory"; import path from "path"; +import { + isHoliday, + isOutBusinessTime, + isWeekend +} from "../../helpers/TicketConfig"; + import { format as _format, isWithinInterval, @@ -608,174 +614,51 @@ const handleMessage = async (msg: any, wbot: any): Promise => { } // MESSAGE TO HOLIDAY - const holiday = await SettingTicket.findOne({ - where: { key: "holiday" } - }); + const holiday: any = await isHoliday(); - if ( - holiday && - holiday.value == "enabled" && - holiday.message?.trim()?.length > 0 - ) { - const startTime = splitDateTime( - new Date( - _format(new Date(holiday.startTime), "yyyy-MM-dd HH:mm:ss", { - locale: ptBR - }) - ) - ); - - const currentDate = splitDateTime( - new Date( - _format(new Date(), "yyyy-MM-dd HH:mm:ss", { - locale: ptBR - }) - ) - ); - - if (msg.fromMe && holiday && holiday.message.trim() == msg.body.trim()) { - console.log("HOLIDAY DAY"); + if (holiday.set) { + if (msg.fromMe && holiday.msg == msg.body) { + console.log("HOLIDAY MESSAGE IGNORED"); return; } - if (currentDate.fullDate == startTime.fullDate) { - botSendMessage(ticket, holiday.message); - return; - } - } - - // MESSAGES TO SATURDAY OR SUNDAY - const weekend = await SettingTicket.findOne({ - where: { key: "weekend" } - }); - - if ( - weekend && - weekend.value == "enabled" && - weekend.message?.trim()?.length > 0 - ) { - if (msg.fromMe && weekend.message.trim() == msg.body.trim()) { - console.log("SATURDAY OR SUNDAY DATE"); - return; - } - - // Specify your desired timezone - const brazilTimeZone = "America/Sao_Paulo"; - - const currentDateUtc = new Date(); - - // Convert UTC date to Brazil time zone - const currentDate = utcToZonedTime(currentDateUtc, brazilTimeZone); - - // Format the date using the desired format - const formattedDate = _format(currentDate, "yyyy-MM-dd HH:mm:ssXXX"); - - const parsedDate = parseISO(formattedDate); - - // Convert parsed date to Brazil time zone - const localDate = utcToZonedTime(parsedDate, brazilTimeZone); - - // Check if it's Saturday or Sunday - if (isSaturday(localDate)) { - const saturday = await SettingTicket.findOne({ - where: { key: "saturday" } - }); - - if (saturday && saturday.value == "enabled") { - botSendMessage(ticket, weekend.message); - return; - } - } else if (isSunday(localDate)) { - const sunday = await SettingTicket.findOne({ - where: { key: "sunday" } - }); - - if (sunday && sunday.value == "enabled") { - botSendMessage(ticket, weekend.message); - return; - } - } - } - - // MESSAGE TO BUSINESS TIME - const businessTime: any = await BusinessTime(); - - if ( - msg.fromMe && - businessTime && - !businessTime.isWithinRange && - businessTime.message.trim() == msg.body.trim() - ) { - console.log("BUSINESS TIME OUT"); + botSendMessage(ticket, holiday.msg); return; } - if (!businessTime.isWithinRange && businessTime.message.trim().length > 0) { - botSendMessage(ticket, businessTime.message); + // MESSAGES TO SATURDAY OR SUNDAY + const weekend: any = await isWeekend(); + + if (weekend.set) { + if (msg.fromMe && weekend.msg == msg.body) { + console.log("WEEKEND MESSAGE IGNORED"); + return; + } + + botSendMessage(ticket, weekend.msg); + return; } + + // MESSAGE TO BUSINESS TIME + const businessTime = await isOutBusinessTime(); + + if (businessTime.set) { + if (msg.fromMe && businessTime.msg == msg.body) { + console.log("BUSINESS TIME MESSAGE IGNORED"); + return; + } + + botSendMessage(ticket, businessTime.msg); + return; + } + + } catch (err) { Sentry.captureException(err); console.log("Error handling whatsapp message: Err: ", err); logger.error(`Error handling whatsapp message: Err: ${err}`); - } - - async function BusinessTime() { - const outBusinessHours = await SettingTicket.findOne({ - where: { key: "outBusinessHours" } - }); - - let isWithinRange = false; - - if (outBusinessHours && outBusinessHours.value == "enabled") { - const ticketDateTimeUpdate = splitDateTime( - new Date( - _format(new Date(), "yyyy-MM-dd HH:mm:ss", { - locale: ptBR - }) - ) - ); - - const startTime = splitDateTime( - new Date( - _format(new Date(outBusinessHours.startTime), "yyyy-MM-dd HH:mm:ss", { - locale: ptBR - }) - ) - ); - - const endTime = splitDateTime( - new Date( - _format(new Date(outBusinessHours.endTime), "yyyy-MM-dd HH:mm:ss", { - locale: ptBR - }) - ) - ); - - const format = "HH:mm:ss"; - const parsedStartTime = parse( - ticketDateTimeUpdate.fullTime, - format, - new Date() - ); - const parsedEndTime = parse(startTime.fullTime, format, new Date()); - const parsedTimeToCheck = parse(endTime.fullTime, format, new Date()); - - const timeInterval = { start: parsedStartTime, end: parsedEndTime }; - - // If the time range spans across different days, handle the date part - if (parsedEndTime < parsedStartTime) { - const nextDay = new Date(parsedStartTime); - nextDay.setDate(nextDay.getDate() + 1); - timeInterval.end = nextDay; - } - - isWithinRange = isWithinInterval(parsedTimeToCheck, timeInterval); - - console.log("Is the time within the range?", isWithinRange); - - return { isWithinRange, message: outBusinessHours.message }; - } - } + } + }; const handleMsgAck = async (msg_id: any, ack: any) => { diff --git a/frontend/src/components/ConfigModal/index.js b/frontend/src/components/ConfigModal/index.js index 2187fdc..0f2ef88 100644 --- a/frontend/src/components/ConfigModal/index.js +++ b/frontend/src/components/ConfigModal/index.js @@ -93,17 +93,13 @@ const ConfigModal = ({ open, onClose, change }) => { const fetchSession = async () => { try { - const { data } = await api.get('/settings') - - console.log('data.config: ', data.config) + const { data } = await api.get('/settings') const outBusinessHours = data.config.find((c) => c.key == "outBusinessHours") const ticketExpiration = data.config.find((c) => c.key == "ticketExpiration") const saturday = data.config.find((c) => c.key == "saturday") const sunday = data.config.find((c) => c.key == "sunday") - const weekend = data.config.find((c) => c.key == "weekend") - - + const weekend = data.config.find((c) => c.key == "weekend") const holiday = data.config.find((c) => c.key == "holiday") setConfig({ From 7b1d2f2d2b4acce207a7d7b00ed4d025b82920ba Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 9 Aug 2023 10:26:54 -0300 Subject: [PATCH 12/19] =?UTF-8?q?refatora=C3=A7=C3=A3o=20de=20frontend?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- frontend/src/components/ConfigModal/index.js | 31 +++++--------------- 1 file changed, 7 insertions(+), 24 deletions(-) diff --git a/frontend/src/components/ConfigModal/index.js b/frontend/src/components/ConfigModal/index.js index 0f2ef88..c221455 100644 --- a/frontend/src/components/ConfigModal/index.js +++ b/frontend/src/components/ConfigModal/index.js @@ -95,12 +95,12 @@ const ConfigModal = ({ open, onClose, change }) => { try { const { data } = await api.get('/settings') - const outBusinessHours = data.config.find((c) => c.key == "outBusinessHours") - const ticketExpiration = data.config.find((c) => c.key == "ticketExpiration") - const saturday = data.config.find((c) => c.key == "saturday") - const sunday = data.config.find((c) => c.key == "sunday") - const weekend = data.config.find((c) => c.key == "weekend") - const holiday = data.config.find((c) => c.key == "holiday") + const outBusinessHours = data.config.find((c) => c.key === "outBusinessHours") + const ticketExpiration = data.config.find((c) => c.key === "ticketExpiration") + const saturday = data.config.find((c) => c.key === "saturday") + const sunday = data.config.find((c) => c.key === "sunday") + const weekend = data.config.find((c) => c.key === "weekend") + const holiday = data.config.find((c) => c.key === "holiday") setConfig({ startTimeBus: outBusinessHours.startTime, @@ -443,24 +443,7 @@ const ConfigModal = ({ open, onClose, change }) => { } - -const TimePickerField = ({ field, form, ...other }) => { - const { name, value } = field - - const handleChange = (time) => { - form.setFieldValue(name, time, true) - } - - return ( - - ) -} + export default React.memo(ConfigModal) From ee11b977ccb243edd30b1c6dd738410a8f1ea3a6 Mon Sep 17 00:00:00 2001 From: adriano Date: Thu, 10 Aug 2023 09:32:38 -0300 Subject: [PATCH 13/19] =?UTF-8?q?Adi=C3=A7=C3=A3o=20do=20recurso=20para=20?= =?UTF-8?q?transferir=20ticket=20quando=20entrar=20em=20loop=20infinito=20?= =?UTF-8?q?de=20ura?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/helpers/MostRepeatedPhrase.ts | 56 ++++++++++++++ .../WbotServices/wbotMessageListener.ts | 74 +++++++++++-------- 2 files changed, 100 insertions(+), 30 deletions(-) create mode 100644 backend/src/helpers/MostRepeatedPhrase.ts diff --git a/backend/src/helpers/MostRepeatedPhrase.ts b/backend/src/helpers/MostRepeatedPhrase.ts new file mode 100644 index 0000000..71ced82 --- /dev/null +++ b/backend/src/helpers/MostRepeatedPhrase.ts @@ -0,0 +1,56 @@ +import { subSeconds } from "date-fns"; +import Message from "../models/Message"; + +import { Op, Sequelize } from "sequelize"; + +const mostRepeatedPhrase = async ( + ticketId: number | string, + fromMe: boolean = false +) => { + let res: any = { body: "", occurrences: 0 }; + + try { + const mostRepeatedPhrase: any = await Message.findOne({ + where: { + ticketId: ticketId, + fromMe: fromMe ? fromMe : 0, + body: { + [Op.notRegexp]: "^[0-9]+$" + }, + updatedAt: { + [Op.between]: [+subSeconds(new Date(), 150), +new Date()] + } + }, + attributes: [ + "body", + [Sequelize.fn("COUNT", Sequelize.col("body")), "occurrences"] + ], + + group: ["body"], + order: [[Sequelize.literal("occurrences"), "DESC"]], + limit: 1 + }); + + if (mostRepeatedPhrase) { + const { body, occurrences } = mostRepeatedPhrase.get(); + + console.log( + `The most repeated phrase is "${body}" with ${occurrences} occurrences.` + ); + + const isNumber = /^\d+$/.test(body.trim()); + + if (!isNumber) { + return { body, occurrences }; + } + } else { + console.log("No phrases found."); + } + } catch (error) { + console.log("error on MostRepeatedPhrase: ", error); + } + + return { body: "", occurrences: 0 }; +}; + +export default mostRepeatedPhrase; diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index 7e812b6..8bef346 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -82,6 +82,7 @@ import { import AppError from "../../errors/AppError"; import { setMessageAsRead } from "../../helpers/SetMessageAsRead"; import SettingTicket from "../../models/SettingTicket"; +import mostRepeatedPhrase from "../../helpers/MostRepeatedPhrase"; var lst: any[] = getWhatsappIds(); @@ -299,12 +300,20 @@ const verifyQueue = async ( sendWhatsAppMessageSocket(ticket, body); } else { //test del transfere o atendimento se entrar na ura infinita - let ticket_message = await ShowTicketMessage(ticket.id, false); - if (ticket_message.length > 10) { + const repet: any = await mostRepeatedPhrase(ticket.id); + + if (repet.occurrences > 4) { await UpdateTicketService({ ticketData: { status: "pending", queueId: queues[0].id }, ticketId: ticket.id }); + + await SendWhatsAppMessage({ + body: `Seu atendimento foi transferido para um agente! + `, + ticket, + number: `${contact.number}@c.us` + }); } else { let options = ""; @@ -613,52 +622,57 @@ const handleMessage = async (msg: any, wbot: any): Promise => { await setMessageAsRead(ticket); } - // MESSAGE TO HOLIDAY - const holiday: any = await isHoliday(); + let ticketHasQueue = false; - if (holiday.set) { - if (msg.fromMe && holiday.msg == msg.body) { - console.log("HOLIDAY MESSAGE IGNORED"); + if (ticket?.queueId) { + ticketHasQueue = true; + } + + if (ticketHasQueue) { + // MESSAGE TO HOLIDAY + const holiday: any = await isHoliday(); + + if (holiday.set) { + if (msg.fromMe && holiday.msg == msg.body) { + console.log("HOLIDAY MESSAGE IGNORED"); + return; + } + + botSendMessage(ticket, holiday.msg); return; } - botSendMessage(ticket, holiday.msg); - return; - } + // MESSAGES TO SATURDAY OR SUNDAY + const weekend: any = await isWeekend(); - // MESSAGES TO SATURDAY OR SUNDAY - const weekend: any = await isWeekend(); + if (weekend.set) { + if (msg.fromMe && weekend.msg == msg.body) { + console.log("WEEKEND MESSAGE IGNORED"); + return; + } - if (weekend.set) { - if (msg.fromMe && weekend.msg == msg.body) { - console.log("WEEKEND MESSAGE IGNORED"); + botSendMessage(ticket, weekend.msg); return; } - botSendMessage(ticket, weekend.msg); - return; - } + // MESSAGE TO BUSINESS TIME + const businessTime = await isOutBusinessTime(); - // MESSAGE TO BUSINESS TIME - const businessTime = await isOutBusinessTime(); + if (businessTime.set) { + if (msg.fromMe && businessTime.msg == msg.body) { + console.log("BUSINESS TIME MESSAGE IGNORED"); + return; + } - if (businessTime.set) { - if (msg.fromMe && businessTime.msg == msg.body) { - console.log("BUSINESS TIME MESSAGE IGNORED"); + botSendMessage(ticket, businessTime.msg); return; } - - botSendMessage(ticket, businessTime.msg); - return; } - - } catch (err) { Sentry.captureException(err); console.log("Error handling whatsapp message: Err: ", err); logger.error(`Error handling whatsapp message: Err: ${err}`); - } - + } }; const handleMsgAck = async (msg_id: any, ack: any) => { From 75eb24fe62e58ea412b0a167b29182b937aa0776 Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 14 Aug 2023 06:48:39 -0300 Subject: [PATCH 14/19] Modulo campanha basico finalizado --- backend/src/controllers/ContactController.ts | 98 ++++--- backend/src/libs/socket.ts | 271 ++++++++---------- .../src/components/CampaignModal/index.js | 22 +- frontend/src/errors/toastError.js | 4 +- frontend/src/pages/Campaign/index.js | 271 +++++++++--------- 5 files changed, 334 insertions(+), 332 deletions(-) diff --git a/backend/src/controllers/ContactController.ts b/backend/src/controllers/ContactController.ts index c5099b0..15721e3 100644 --- a/backend/src/controllers/ContactController.ts +++ b/backend/src/controllers/ContactController.ts @@ -8,18 +8,19 @@ import ShowContactService from "../services/ContactServices/ShowContactService"; import UpdateContactService from "../services/ContactServices/UpdateContactService"; import DeleteContactService from "../services/ContactServices/DeleteContactService"; -import CheckContactNumber from "../services/WbotServices/CheckNumber" +import CheckContactNumber from "../services/WbotServices/CheckNumber"; import CheckIsValidContact from "../services/WbotServices/CheckIsValidContact"; import GetProfilePicUrl from "../services/WbotServices/GetProfilePicUrl"; import AppError from "../errors/AppError"; - -import { searchContactCache, insertContactsCache, escapeCharCache } from '../helpers/ContactsCache' +import { + searchContactCache, + insertContactsCache, + escapeCharCache +} from "../helpers/ContactsCache"; import { off } from "process"; - - type IndexQuery = { searchParam: string; pageNumber: string; @@ -39,42 +40,46 @@ interface ContactData { export const index = async (req: Request, res: Response): Promise => { let { searchParam, pageNumber } = req.query as IndexQuery; - console.log('PAGE NUMBER CONTACT: ', pageNumber) + console.log("PAGE NUMBER CONTACT: ", pageNumber); if (pageNumber === undefined || pageNumber.trim().length == 0) { - pageNumber = '1' + pageNumber = "1"; } - // TEST DEL + // TEST DEL if (searchParam && searchParam.trim().length > 0 && process.env.CACHE) { - try { - const offset = 20 * (+pageNumber - 1); - searchParam = searchParam.replace(/\s+/g, ' ').trim().toLowerCase(); + searchParam = searchParam.replace(/\s+/g, " ").trim().toLowerCase(); - const data = await searchContactCache(searchParam, offset, 20) + const data = await searchContactCache(searchParam, offset, 20); if (data) { + console.log("QUERY CONTACTS FROM CACHE SEARCH PARAM: ", searchParam); - console.log('QUERY CONTACTS FROM CACHE SEARCH PARAM: ', searchParam) + console.log("QUERY CONTACTS FROM CACHE QUERY LENGTH: ", data.length); - console.log('QUERY CONTACTS FROM CACHE QUERY LENGTH: ', data.length) - - return res.json({ contacts: data, count: data.length, hasMore: data.length > 0 ? true : false }); + return res.json({ + contacts: data, + count: data.length, + hasMore: data.length > 0 ? true : false + }); } - } catch (error) { - console.log('There was an error on search ContactController.ts search cache: ', error) + console.log( + "There was an error on search ContactController.ts search cache: ", + error + ); } - - } - console.log('QUERY CONTACTS FROM DATABASE SEARCH PARAM: ', searchParam) + console.log("QUERY CONTACTS FROM DATABASE SEARCH PARAM: ", searchParam); - const { contacts, count, hasMore } = await ListContactsService({ searchParam, pageNumber }); + const { contacts, count, hasMore } = await ListContactsService({ + searchParam, + pageNumber + }); return res.json({ contacts, count, hasMore }); }; @@ -99,33 +104,32 @@ export const store = async (req: Request, res: Response): Promise => { const validNumber = await CheckIsValidContact(newContact.number); - // const validNumber: any = await CheckContactNumber(newContact.number) + // const validNumber: any = await CheckContactNumber(newContact.number) - if(!validNumber){ + if (!validNumber) { throw new AppError("ERR_WAPP_CHECK_CONTACT"); } const profilePicUrl = await GetProfilePicUrl(validNumber); - console.log('xxxxxxxxxxx profilePicUrl: ',profilePicUrl) - + console.log("xxxxxxxxxxx profilePicUrl: ", profilePicUrl); // console.log(`newContact.name: ${newContact.name}\n // newContact.number: ${newContact.number}\n // newContact.email: ${newContact.email}\n // newContact.extraInfo: ${newContact.extraInfo}`) - let name = newContact.name - let number = validNumber - let email = newContact.email - let extraInfo = newContact.extraInfo + let name = newContact.name; + let number = validNumber; + let email = newContact.email; + let extraInfo = newContact.extraInfo; const contact = await CreateContactService({ name, number, email, profilePicUrl: profilePicUrl, - extraInfo, + extraInfo }); const io = getIO(); @@ -154,8 +158,8 @@ export const update = async ( const schema = Yup.object().shape({ name: Yup.string(), number: Yup.string() - .matches(/^\d+$/,"Invalid number format. Only numbers is allowed.") - .matches(/^55\d+$/, "The number must start with 55.") + .matches(/^\d+$/, "Invalid number format. Only numbers is allowed.") + .matches(/^55\d+$/, "The number must start with 55.") }); try { @@ -196,13 +200,20 @@ export const remove = async ( return res.status(200).json({ message: "Contact deleted" }); }; - - -export const contacsBulkInsertOnQueue = async (req: Request, res: Response): Promise => { - +export const contacsBulkInsertOnQueue = async ( + req: Request, + res: Response +): Promise => { // console.log('THE BODY: ', req.body) - const { adminId, identifier, queueStatus, file, contacts_inserted } = req.body + const { + adminId, + identifier, + queueStatus, + file, + contacts_inserted, + campaign + } = req.body; const io = getIO(); io.emit("contactsBulkInsertOnQueueStatus", { @@ -211,17 +222,14 @@ export const contacsBulkInsertOnQueue = async (req: Request, res: Response): Pro adminId: adminId, identifier: identifier, queueStatus: queueStatus, - file: file + file: file, + campaign } }); - if (process.env.CACHE && contacts_inserted) { - - await insertContactsCache(contacts_inserted) - + await insertContactsCache(contacts_inserted); } - return res.status(200).json({ message: 'ok' }) + return res.status(200).json({ message: "ok" }); }; - diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts index 8eb1464..43a7a5f 100644 --- a/backend/src/libs/socket.ts +++ b/backend/src/libs/socket.ts @@ -3,220 +3,204 @@ import { Server } from "http"; import AppError from "../errors/AppError"; import { logger } from "../utils/logger"; -import { v4 as uuidv4 } from 'uuid'; +import { v4 as uuidv4 } from "uuid"; import ListUserParamiterService from "../services/UserServices/ListUserParamiterService"; -import { addHours, addMinutes, addSeconds, intervalToDuration, add } from "date-fns"; +import { + addHours, + addMinutes, + addSeconds, + intervalToDuration, + add +} from "date-fns"; let io: SocketIO; //test del import createOrUpdateOnlineUserService from "../services/UserServices/CreateOrUpdateOnlineUserService"; import { splitDateTime } from "../helpers/SplitDateTime"; -import format from 'date-fns/format'; -import ptBR from 'date-fns/locale/pt-BR'; +import format from "date-fns/format"; +import ptBR from "date-fns/locale/pt-BR"; import ListUserOnlineOffline from "../services/UserServices/ListUsersOnlineOfflineService"; -import { handleMessage, handleMsgAck } from "../services/WbotServices/wbotMessageListener"; +import { + handleMessage, + handleMsgAck +} from "../services/WbotServices/wbotMessageListener"; import { join } from "path"; import Whatsapp from "../models/Whatsapp"; -let count: number = 0 -let listOnline: any[] = [] -let listOnlineAux: any[] = [] -let countOnline: number = 0 -let obj: any = { listOnline: [], uuid: null, listOnlineAux: [] } +let count: number = 0; +let listOnline: any[] = []; +let listOnlineAux: any[] = []; +let countOnline: number = 0; +let obj: any = { listOnline: [], uuid: null, listOnlineAux: [] }; +let lstOnline: any[] = []; +let lstOnlineAux: any[] = []; +let lstTry: any[] = []; - - -let lstOnline: any[] = [] -let lstOnlineAux: any[] = [] -let lstTry: any[] = [] - -let dateTime = splitDateTime(new Date(format(new Date(), 'yyyy-MM-dd HH:mm:ss', { locale: ptBR }))) - +let dateTime = splitDateTime( + new Date(format(new Date(), "yyyy-MM-dd HH:mm:ss", { locale: ptBR })) +); export const initIO = (httpServer: Server): SocketIO => { io = new SocketIO(httpServer, { cors: { origin: process.env.FRONTEND_URL - }, + }, maxHttpBufferSize: 1e8 }); - io.on("connection", socket => { logger.info("Client Connected"); - - - - - - socket.on("joinWhatsSession", (whatsappId: string) => { logger.info(`A client joined a joinWhatsSession channel: ${whatsappId}`); socket.join(`session_${whatsappId}`); }); socket.on("message_from_client", () => { - - socket.emit('message_from_server', 'Sent an event from the server!'); - }) - - socket.on("message_create", async (data: any) => { - - handleMessage(data.msg, data); - + socket.emit("message_from_server", "Sent an event from the server!"); }); - - socket.on("media_uploaded", async (data: any) => { - + socket.on("message_create", async (data: any) => { handleMessage(data.msg, data); + }); + socket.on("media_uploaded", async (data: any) => { + handleMessage(data.msg, data); }); socket.on("message_ack", async (data: any) => { - - handleMsgAck(data.id, data.ack) - + handleMsgAck(data.id, data.ack); }); + socket.on("campaign_message_sent", async (data: any) => { + console.log("campaign_message_sent: ", data); + const io = getIO(); + let campaign = {}; + if (data?.read) { + campaign = { + id: data.id, + read: data.read + }; + } else if (data?.sent) { + campaign = { + id: data.id, + sent: data.sent + }; + } else if (data?.status) { + campaign = { + id: data.id, + status: data.status + }; + } - - - - + io.emit("campaign", { + action: "update", + campaign + }); + }); socket.on("online", (userId: any) => { - // console.log('userId: ', userId) - obj.uuid = uuidv4() + obj.uuid = uuidv4(); if (userId.logoutUserId) { - - let index = lstOnline.findIndex((x: any) => x.id == userId.logoutUserId) + let index = lstOnline.findIndex( + (x: any) => x.id == userId.logoutUserId + ); if (index != -1) { - - lstOnline.splice(index, 1) - + lstOnline.splice(index, 1); } - - index = lstOnlineAux.findIndex((x: any) => x.id == userId.logoutUserId) + index = lstOnlineAux.findIndex((x: any) => x.id == userId.logoutUserId); if (index != -1) { - - lstOnlineAux.splice(index, 1) - + lstOnlineAux.splice(index, 1); } - return + return; } if (lstOnline.length == 0) { - - const index = listOnlineAux.findIndex((e: any) => e.id == userId) + const index = listOnlineAux.findIndex((e: any) => e.id == userId); if (index == -1) { - listOnlineAux.push({ 'id': userId }) - } - else { - return + listOnlineAux.push({ id: userId }); + } else { + return; } - lstOnline.push({ 'id': userId, 'status': 'online', 'try': 0 }) + lstOnline.push({ id: userId, status: "online", try: 0 }); - lstOnlineAux.push({ 'id': userId }) - console.log(' 1 PUSHED NEW USER ID 1: ', userId) + lstOnlineAux.push({ id: userId }); + console.log(" 1 PUSHED NEW USER ID 1: ", userId); - obj.listOnline = lstOnline - - } - else { - - const indexAux = lstOnlineAux.findIndex((e: any) => e.id == userId) + obj.listOnline = lstOnline; + } else { + const indexAux = lstOnlineAux.findIndex((e: any) => e.id == userId); if (indexAux == -1) { - lstOnlineAux.push({ 'id': userId }) + lstOnlineAux.push({ id: userId }); } - const index = lstOnline.findIndex((e: any) => e.id == userId) + const index = lstOnline.findIndex((e: any) => e.id == userId); if (index == -1) { + lstOnline.push({ id: userId, status: "online", try: 0 }); + console.log(" 2 PUSHED NEW USER ID: ", userId); - lstOnline.push({ 'id': userId, 'status': 'online', 'try': 0 }) - - - console.log(' 2 PUSHED NEW USER ID: ', userId) - - obj.listOnline = lstOnline - } - else { - - if (countOnline > (lstOnline.length - 1)) { - + obj.listOnline = lstOnline; + } else { + if (countOnline > lstOnline.length - 1) { lstOnline.forEach((x: any) => { if (lstOnlineAux.map((e: any) => e.id).includes(x.id)) { - x.try = 0 - x.status = 'online' + x.try = 0; + x.status = "online"; } - }) - - - var difference = lstOnline.filter((x: any) => !lstOnlineAux.map((e: any) => e.id).includes(x.id)); + }); + var difference = lstOnline.filter( + (x: any) => !lstOnlineAux.map((e: any) => e.id).includes(x.id) + ); if (difference.length > 0) { - - difference.forEach((e) => { - - e.try += 1 + difference.forEach(e => { + e.try += 1; if (e.try > 1) { - e.status = 'waiting...' + e.status = "waiting..."; } if (e.try > 3) { - - const index = lstOnline.findIndex((x: any) => x.id == e.id) + const index = lstOnline.findIndex((x: any) => x.id == e.id); if (index != -1) { - - lstOnline.splice(index, 1) - + lstOnline.splice(index, 1); } } - - }) - - + }); } - obj.listOnline = lstOnline - obj.listOnlineAux = lstOnlineAux + obj.listOnline = lstOnline; + obj.listOnlineAux = lstOnlineAux; + lstOnlineAux = []; + listOnlineAux = []; - lstOnlineAux = [] - listOnlineAux = [] - - countOnline = -1 + countOnline = -1; } - - countOnline++ + countOnline++; } - } - exports.ob = obj - - + exports.ob = obj; }); socket.on("joinChatBox", (ticketId: string) => { @@ -239,49 +223,51 @@ export const initIO = (httpServer: Server): SocketIO => { }); socket.on("disconnecting", async () => { - console.log('socket.rooms: ', socket.rooms); // the Set contains at least the socket ID + console.log("socket.rooms: ", socket.rooms); // the Set contains at least the socket ID - let rooms = socket.rooms + let rooms = socket.rooms; - console.log('rooms: ', rooms, ' | rooms.size: ', rooms.size) + console.log("rooms: ", rooms, " | rooms.size: ", rooms.size); - if(rooms && rooms.size==1) return - if(rooms && rooms.size==2 && !([...rooms][1].startsWith('session_'))) return + if (rooms && rooms.size == 1) return; + if (rooms && rooms.size == 2 && ![...rooms][1].startsWith("session_")) + return; - let whatsappIds: any = await Whatsapp.findAll({ attributes: ['id'], raw: true }) + let whatsappIds: any = await Whatsapp.findAll({ + attributes: ["id"], + raw: true + }); if (whatsappIds && whatsappIds.length > 0) { + whatsappIds = whatsappIds.map((e: any) => `${e.id}`); - whatsappIds = whatsappIds.map((e: any) => `${e.id}`) + console.log( + "whatsappIds whatsappIds whatsappIds whatsappIds whatsappIds: ", + whatsappIds + ); - console.log('whatsappIds whatsappIds whatsappIds whatsappIds whatsappIds: ',whatsappIds) + if ( + rooms && + rooms.size == 2 && + [...rooms][1].startsWith("session_") && + whatsappIds.includes([...rooms][1].replace("session_", "")) + ) { + console.log([...rooms][1]); - if (rooms && rooms.size == 2 && - [...rooms][1].startsWith('session_') && - whatsappIds.includes([...rooms][1].replace('session_', ''))) { + let whatsappId = [...rooms][1].replace("session_", ""); - console.log([...rooms][1]) - - let whatsappId = [...rooms][1].replace('session_', '') - - const whatsapp = await Whatsapp.findByPk(whatsappId, {}) + const whatsapp = await Whatsapp.findByPk(whatsappId, {}); if (whatsapp) { - - await whatsapp.update({ status: 'OPENING' }); + await whatsapp.update({ status: "OPENING" }); io.emit("whatsappSession", { action: "update", session: whatsapp }); - } - - } - } - }); }); return io; @@ -294,12 +280,9 @@ export const getIO = (): SocketIO => { return io; }; - - function writeFileAsync(arg0: any, data: any, arg2: string) { throw new Error("Function not implemented."); } // exports.listOnlineUsers = listUserId -// exports.listUserId - +// exports.listUserId diff --git a/frontend/src/components/CampaignModal/index.js b/frontend/src/components/CampaignModal/index.js index ba15420..2323aad 100644 --- a/frontend/src/components/CampaignModal/index.js +++ b/frontend/src/components/CampaignModal/index.js @@ -9,14 +9,14 @@ import { green } from '@material-ui/core/colors' import { AuthContext } from '../../context/Auth/AuthContext' import { Can } from '../../components/Can' -import apiBroker from '../../services/apiBroker' - -import Select from "@material-ui/core/Select" -import MenuItem from "@material-ui/core/MenuItem"; +import apiBroker from '../../services/apiBroker' + +import Select from "@material-ui/core/Select" +import MenuItem from "@material-ui/core/MenuItem" import SelectField from "../../components/Report/SelectField" -import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext"; +import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext" import { Dialog, @@ -74,13 +74,14 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { const initialState = { name: '', message: '', + status: 'pending', whatsapp_sender: '', csv_original_file_name: '', } - + const { user } = useContext(AuthContext) - const { whatsApps } = useContext(WhatsAppsContext); + const { whatsApps } = useContext(WhatsAppsContext) console.log('------------> whatsApps: ', whatsApps) @@ -88,7 +89,7 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { // const [selectedQueueIds, setSelectedQueueIds] = useState([]) const [file, setFile] = useState() - const [selectedNumber, setSelectedNumber] = useState(''); + const [selectedNumber, setSelectedNumber] = useState('') const [itemHover, setItemHover] = useState(-1) @@ -97,7 +98,7 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { }, [selectedNumber]) - + useEffect(() => { const fetchSession = async () => { if (!campaignId) return @@ -175,6 +176,7 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { onClose() setCampaign(initialState) setSelectedNumber('') + setFile(null) } async function handleChange(event) { @@ -258,7 +260,7 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => {
    - +
    diff --git a/frontend/src/errors/toastError.js b/frontend/src/errors/toastError.js index 9450764..e0ac073 100644 --- a/frontend/src/errors/toastError.js +++ b/frontend/src/errors/toastError.js @@ -1,8 +1,8 @@ import { toast } from "react-toastify"; import { i18n } from "../translate/i18n"; -const toastError = err => { - const errorMsg = err.response?.data?.message || err.response.data.error; +const toastError = err => { + const errorMsg = err.response?.data?.message || err?.response?.data?.error || `${err?.message}`; if (errorMsg) { if (i18n.exists(`backendErrors.${errorMsg}`)) { toast.error(i18n.t(`backendErrors.${errorMsg}`), { diff --git a/frontend/src/pages/Campaign/index.js b/frontend/src/pages/Campaign/index.js index 54e5e42..954c8b9 100644 --- a/frontend/src/pages/Campaign/index.js +++ b/frontend/src/pages/Campaign/index.js @@ -69,8 +69,14 @@ const reducer = (state, action) => { const campaignIndex = state.findIndex((c) => c.id === campaign.id) if (campaignIndex !== -1) { - state[campaignIndex] = campaign + + state[campaignIndex] = { ...state[campaignIndex], ...campaign } + return [...state] + + // state[campaignIndex] = campaign + + // return [...state] } else { return [campaign, ...state] } @@ -174,7 +180,7 @@ const Campaign = () => { title: '', message: '', campaignId: '', - csv_original_file_name:'', + csv_original_file_name: '', open: false, } const [confirmModalInfo, setConfirmModalInfo] = useState( @@ -203,6 +209,8 @@ const Campaign = () => { } }) + console.log('data.campaign : ', data.campaign) + dispatch({ type: "LOAD_CAMPAIGNS", payload: data.campaign }) setLoading(false) @@ -284,6 +292,40 @@ const Campaign = () => { setQrModalOpen(true) } + const handleStart = async (campaign) => { + console.log('start') + + try { + const { data } = await apiBroker.post(`/campaign/start/${campaign.id}`) + + console.log('==============> data.campaign: ', data.campaign) + + dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) + + toast.success('Campanha iniciada com sucesso') + + } catch (err) { + toastError(err) + } + } + + const handleStop = async (campaign) => { + console.log('stop') + + try { + const { data } = await apiBroker.post(`/campaign/stop/${campaign.id}`) + + console.log('==============> data.campaign: ', data.campaign) + + dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) + + toast.success('Campanha parada com sucesso') + + } catch (err) { + toastError(err) + } + } + const handleCloseQrModal = useCallback(() => { setSelectedCampaign(null) setQrModalOpen(false) @@ -325,7 +367,7 @@ const Campaign = () => { } if (confirmModalInfo.action === 'delete') { - try { + try { await apiBroker.delete(`/campaign/${confirmModalInfo.campaignId}`, { params: { adminId: user.id, @@ -334,7 +376,7 @@ const Campaign = () => { }, }) - dispatch({ type: "DELETE_CAMPAIGN", payload: confirmModalInfo.campaignId }) + dispatch({ type: "DELETE_CAMPAIGN", payload: confirmModalInfo.campaignId }) toast.success('Campanha deletada com sucesso') } catch (err) { @@ -347,63 +389,28 @@ const Campaign = () => { const renderActionButtons = (campaign) => { return ( - ( - <> - {campaign.status === 'qrcode' && ( - - )} - {campaign.status === 'DISCONNECTED' && ( - <> - {' '} - - - )} - {(campaign.status === 'CONNECTED' || - campaign.status === 'PAIRING' || - campaign.status === 'TIMEOUT') && ( - - )} - {campaign.status === 'OPENING' && ( - - )} - + <> + {campaign.status === 'stopped' && ( + )} - /> + {campaign.status === 'running' && ( + + )} + ) } @@ -483,6 +490,31 @@ const Campaign = () => { useEffect(() => { const socket = openSocket(process.env.REACT_APP_BACKEND_URL) + + socket.on("contactsBulkInsertOnQueueStatus", (data) => { + if (data.action === 'update') { + + if (String(data.insertOnQueue.adminId) === String(user.id)) { + + if (data?.insertOnQueue?.campaign?.status === "stopped") { + + dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.insertOnQueue.campaign }) + + } + } + + } + }) + + socket.on('campaign', (data) => { + + console.log('------------> CAMPAIGN: ', data) + + if (data.action === 'update') { + dispatch({ type: "UPDATE_CAMPAIGNS", payload: data.campaign }) + } + }) + socket.on('diskSpaceMonit', (data) => { if (data.action === 'update') { setDiskSpaceInfo(data.diskSpace) @@ -560,30 +592,32 @@ const Campaign = () => { - Nome + Name Status - ( - - {i18n.t('connections.table.session')} - - )} - /> + + Sent + - Whatsapp sender + Read + + + + Start/stop + + + + Sender - Mensagem + Message @@ -604,18 +638,20 @@ const Campaign = () => { - Status + {campaign.status} - ( - - {renderActionButtons(campaign)} - - )} - /> + + {campaign.status === 'stopped' || campaign.status === 'running' || campaign.status === 'success' ? `${campaign.sent}/${campaign.all}` : '0/0'} + + + + {campaign.status === 'stopped' || campaign.status === 'running' || campaign.status === 'success' ? `${campaign.read}` : '0'} + + + + {renderActionButtons(campaign)} + {campaign.whatsapp_sender} @@ -626,56 +662,29 @@ const Campaign = () => { - ( -
    - {(settings && - settings.length > 0 && - getSettingValue('editURA') && - getSettingValue('editURA') === - 'enabled') | - (user.profile === 'master') ? ( - - handleEditCampaign(campaign) - } - > - - - ) : ( -
    - )} -
    - )} - /> - ( - { - handleOpenConfirmationModal( - 'delete', - campaign.id - ) - }} - > - - - )} - /> + {campaign.status != 'success' && ( + + handleEditCampaign(campaign) + } + > + + )} + + + { + handleOpenConfirmationModal( + 'delete', + campaign.id + ) + }} + > + +
    From 5907fc6cb26a789993c9af0edc5d8dea6fb79e13 Mon Sep 17 00:00:00 2001 From: adriano Date: Mon, 14 Aug 2023 15:39:05 -0300 Subject: [PATCH 15/19] =?UTF-8?q?Finaliza=C3=A7=C3=A3o=20do=20modulo=20cam?= =?UTF-8?q?panha?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/libs/socket.ts | 2 +- .../src/components/CampaignModal/index.js | 171 ++++++----- frontend/src/layout/MainListItems.js | 7 +- frontend/src/pages/Campaign/index.js | 268 +++--------------- 4 files changed, 149 insertions(+), 299 deletions(-) diff --git a/backend/src/libs/socket.ts b/backend/src/libs/socket.ts index 43a7a5f..ccc554b 100644 --- a/backend/src/libs/socket.ts +++ b/backend/src/libs/socket.ts @@ -75,7 +75,7 @@ export const initIO = (httpServer: Server): SocketIO => { }); socket.on("campaign_message_sent", async (data: any) => { - console.log("campaign_message_sent: ", data); + // console.log("campaign_message_sent: ", data); const io = getIO(); diff --git a/frontend/src/components/CampaignModal/index.js b/frontend/src/components/CampaignModal/index.js index 2323aad..19ec342 100644 --- a/frontend/src/components/CampaignModal/index.js +++ b/frontend/src/components/CampaignModal/index.js @@ -1,21 +1,19 @@ -import React, { useState, useEffect, useContext, createContext } from 'react' +import React, { useState, useEffect, useContext, } from 'react' import * as Yup from 'yup' -import { Formik, Form, Field } from 'formik' +import { Formik, Form, Field, } from 'formik' import { toast } from 'react-toastify' import { makeStyles } from '@material-ui/core/styles' import { green } from '@material-ui/core/colors' import { AuthContext } from '../../context/Auth/AuthContext' -import { Can } from '../../components/Can' + import apiBroker from '../../services/apiBroker' import Select from "@material-ui/core/Select" import MenuItem from "@material-ui/core/MenuItem" - -import SelectField from "../../components/Report/SelectField" - + import { WhatsAppsContext } from "../../context/WhatsApp/WhatsAppsContext" import { @@ -25,15 +23,11 @@ import { Button, DialogActions, CircularProgress, - TextField, - Switch, - FormControlLabel, + TextField, } from '@material-ui/core' - -import api from '../../services/api' + import { i18n } from '../../translate/i18n' -import toastError from '../../errors/toastError' -import QueueSelect from '../QueueSelect' +import toastError from '../../errors/toastError' const useStyles = makeStyles((theme) => ({ root: { @@ -67,6 +61,23 @@ const SessionSchema = Yup.object().shape({ .min(2, 'Too Short!') .max(100, 'Too Long!') .required('Required'), + + secondStart: Yup.number() + .required('Min time is required') + .min(3, 'Min time must be 3') + .max(3600, 'Min must be less than 3600'), + + secondEnd: Yup.number() + .required('Max time is required') + .min(3, 'Min time must be 3') + .max(3600, 'Max must be less than 3600') + .test('higher-than-lower', 'Tempo final deve ser maior que tempo inicio!', function ( + secondEnd + ) { + const secondStart = this.resolve(Yup.ref('secondStart')) + return secondStart === undefined || secondEnd === undefined || secondEnd > secondStart + }), + }) const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { @@ -77,27 +88,21 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { status: 'pending', whatsapp_sender: '', csv_original_file_name: '', + secondStart: '3', + secondEnd: '15', + textToSeconds: true, } const { user } = useContext(AuthContext) - const { whatsApps } = useContext(WhatsAppsContext) - - console.log('------------> whatsApps: ', whatsApps) + const { whatsApps } = useContext(WhatsAppsContext) const [campaign, setCampaign] = useState(initialState) // const [selectedQueueIds, setSelectedQueueIds] = useState([]) const [file, setFile] = useState() const [selectedNumber, setSelectedNumber] = useState('') - - const [itemHover, setItemHover] = useState(-1) - - useEffect(() => { - console.log('selectedNumber: ', selectedNumber) - }, [selectedNumber]) - - + useEffect(() => { const fetchSession = async () => { @@ -122,7 +127,7 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { } } fetchSession() - }, [campaignId]) + }, [campaignId, user.id]) const handleSaveCampaign = async (values) => { let response = null @@ -135,6 +140,9 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { formData.append('file', file) formData.append('name', values.name) formData.append('whatsapp_sender', selectedNumber) + formData.append('secondStart', values.secondStart) + formData.append('secondEnd', values.secondEnd) + formData.append('textToSeconds', values.textToSeconds) formData.append('message', values.message) formData.append('csv_original_file_name', file?.name) @@ -185,15 +193,15 @@ const CampaignModal = ({ open, onClose, campaignId, dispatch }) => { alert('Arquivo não pode ser maior que 4 MB!') return } - - console.log('event.target.files[0]: ', event.target.files[0]) + setFile(event.target.files[0]) } catch (err) { toastError(err) } } - + + return (
    {
    - ( - <> -
    -
    - +
    +
    + - -
    + +
    -
    +
    -
    -
    - - )} - /> +
    +
    {

    {file?.name || campaign?.csv_original_file_name}

    + +
    + + + + + + +
    +
    - )} - /> + @@ -661,17 +476,17 @@ const Campaign = () => { {campaign.message} - + {campaign.status !== 'running' ? - {campaign.status != 'success' && ( - - handleEditCampaign(campaign) - } - > - - )} + {campaign.status !== 'success' && ( + + handleEditCampaign(campaign) + } + > + + )} { > - + : } + From 3acf2bb261bc0ca2048d58297bf2d52931ee26ea Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 15 Aug 2023 09:14:10 -0300 Subject: [PATCH 16/19] =?UTF-8?q?Atualiza=C3=A7=C3=A3o=20api=20de=20sess?= =?UTF-8?q?=C3=B5es=20para=20suportar=20o=20modulo=20campanha?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 5 + TEST_SERVER1.7z | 0 TEST_SERVER1/api/.env | 1 + TEST_SERVER1/api/app.js | 26 +- TEST_SERVER1/api/helpers/startPm2Process.js | 39 +- TEST_SERVER1/whats/.env | 17 +- TEST_SERVER1/whats/app.js | 628 ++++-- TEST_SERVER1/whats/funcs/mongoConn.js | 18 + TEST_SERVER1/whats/package-lock.json | 2219 ++----------------- TEST_SERVER1/whats/package.json | 5 +- frontend/src/pages/Campaign/index.js | 37 +- frontend/src/pages/Contacts/index.js | 5 +- 12 files changed, 728 insertions(+), 2272 deletions(-) delete mode 100644 TEST_SERVER1.7z create mode 100644 TEST_SERVER1/whats/funcs/mongoConn.js diff --git a/.gitignore b/.gitignore index e19e6cd..68cf144 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,11 @@ WWebJS */WWebJS/* **WWebJS +.wwebjs_auth +*/wwebjs_auth/* +.wwebjs_cache +*/wwebjs_cache/* + # testing /coverage diff --git a/TEST_SERVER1.7z b/TEST_SERVER1.7z deleted file mode 100644 index e69de29..0000000 diff --git a/TEST_SERVER1/api/.env b/TEST_SERVER1/api/.env index 8e97f45..98b5db3 100644 --- a/TEST_SERVER1/api/.env +++ b/TEST_SERVER1/api/.env @@ -4,4 +4,5 @@ BASE_URL=http://localhost PASS="strongpassword, strongpassword32" DB_MONGO_URL=mongodb://localhost:27017 DB_MONGO_NAME=session_out_omnihit_db +DB_MONGO_NAME_CAMPAIGN=broker_omnihit \ No newline at end of file diff --git a/TEST_SERVER1/api/app.js b/TEST_SERVER1/api/app.js index 540f988..dd4f9ef 100644 --- a/TEST_SERVER1/api/app.js +++ b/TEST_SERVER1/api/app.js @@ -233,7 +233,7 @@ app.post('/api/session', async function (req, res) { parseInt( e.name .split('->') - [e.name.split('->').length - 1].trim() + [e.name.split('->').length - 1].trim() .match(/\d+/)[0] ) ) @@ -326,9 +326,8 @@ app.post('/api/session', async function (req, res) { if (whatsapp.length > 0) { if (whatsapp[0]['name'].split(' ').length > 0) { - whatsappName = `${ - whatsapp[0]['name'].split(' ')[0] - } - S${numberSession}` + whatsappName = `${whatsapp[0]['name'].split(' ')[0] + } - S${numberSession}` } } @@ -361,7 +360,16 @@ app.post('/api/session', async function (req, res) { stream.write( `# WHATSAPP ID OF THE TABLE Whatsapps FROM THE OMNIHIT DATABASE\n` ) - stream.write(`WHATSAPP_ID=${whatsappId}`) + stream.write(`WHATSAPP_ID=${whatsappId}\n`) + stream.write('\n') + + stream.write('# MONGO CONNECTION\n') + stream.write(`DB_MONGO_URL=${process.env.DB_MONGO_URL}\n`) + stream.write('\n') + + stream.write('# MONGO COLLECTION\n') + stream.write(`DB_MONGO_NAME=${process.env.DB_MONGO_NAME_CAMPAIGN}\n`) + stream.write('\n') stream.end() }) @@ -380,7 +388,13 @@ app.post('/api/session', async function (req, res) { console.log(`stdout: ${stdout}`) }) - startPm2Process(dirSessionAppName, 'app.js', destDir, appPort) + const env = { + PORT: appPort, + DB_MONGO_URL: process.env.DB_MONGO_URL, + DB_MONGO_NAME: process.env.DB_MONGO_NAME_CAMPAIGN + } + + startPm2Process(dirSessionAppName, 'app.js', destDir, env) } res.send('OK') diff --git a/TEST_SERVER1/api/helpers/startPm2Process.js b/TEST_SERVER1/api/helpers/startPm2Process.js index 13bd3d6..5c27170 100644 --- a/TEST_SERVER1/api/helpers/startPm2Process.js +++ b/TEST_SERVER1/api/helpers/startPm2Process.js @@ -1,44 +1,49 @@ -const pm2 = require('pm2'); -const { execSync } = require("child_process"); +const pm2 = require('pm2') +const { execSync } = require("child_process") -function startPm2Process(process_name, file, path, port) { +function startPm2Process(process_name, file, path, env) { pm2.connect(function (err) { if (err) { - console.error(err); + console.error(err) // process.exit(2); } + console.log('ENV PM2: ', env) + pm2.start({ name: process_name, script: file, cwd: path, - env: { - PORT: port - } + env + // env: { + // NODE_ENV: 'production', + + // PORT: port, + // } // additional options here if needed }, function (err, apps) { if (err) { - console.error(err); + console.error(err) // process.exit(2); } else { execSync(`pm2 save --force`, { cwd: path }, (error, stdout, stderr) => { if (error) { - console.log(`error: ${error.message}`); - return; + console.log(`error: ${error.message}`) + return } if (stderr) { - console.log(`stderr: ${stderr}`); - return; + console.log(`stderr: ${stderr}`) + return } - console.log(`stdout: ${stdout}`); - }); + console.log(`stdout: ${stdout}`) + }) } - pm2.disconnect(); - }); - }); + pm2.disconnect() + }) + }) } diff --git a/TEST_SERVER1/whats/.env b/TEST_SERVER1/whats/.env index 87ff938..6349035 100644 --- a/TEST_SERVER1/whats/.env +++ b/TEST_SERVER1/whats/.env @@ -1,9 +1,9 @@ # NUMBER AND NAME THAT WILL BE DISPLAYED ON CONSOLE -MOBILEUID=5517988310949 -MOBILENAME=Numero de teste +MOBILEUID=5521995996701 +MOBILENAME=test - S1 # PORT NUMBER FOR THIS API -PORT=8020 +PORT=8029 # URL FROM THE OMNIHIT BACKEND API CLIENT_URL=http://localhost:8080 @@ -13,8 +13,13 @@ DB=whaticket DB_HOST=localhost DB_USER=whaticket DB_PASS=strongpassword -DB_PORT=3306 +DB_PORT=3306 # WHATSAPP ID OF THE TABLE Whatsapps FROM THE OMNIHIT DATABASE -WHATSAPP_ID=46 - \ No newline at end of file +WHATSAPP_ID=229 + +# MONGO CONNECTION +DB_MONGO_URL=mongodb://localhost:27017 + +# MONGO COLLECTION +DB_MONGO_NAME=broker_omnihit \ No newline at end of file diff --git a/TEST_SERVER1/whats/app.js b/TEST_SERVER1/whats/app.js index 4ccffe4..7bdc7de 100644 --- a/TEST_SERVER1/whats/app.js +++ b/TEST_SERVER1/whats/app.js @@ -1,64 +1,75 @@ -'use strict'; +'use strict' const { initIO } = require("./helpers/socket") -const backup_session = require('./helpers/backup_session'); -const restore = require('./helpers/restore'); +const { ObjectId } = require('mongodb') -const { Client, Location, List, Buttons, LocalAuth } = require('whatsapp-web.js/index'); +const backup_session = require('./helpers/backup_session') +const restore = require('./helpers/restore') + +const dbcloud = require('./funcs/dbcloud.js') + +const { Client, Location, List, Buttons, LocalAuth } = require('whatsapp-web.js/index') -const qrencode = require('qr-encode'); -const axios = require('axios').default; -const bodyparser = require('body-parser'); -const path = require('path'); -const fs = require('fs'); -const express = require('express'); -// const dbcloud = require('./funcs/dbcloud.js'); -const FormData = require('form-data'); +const qrencode = require('qr-encode') +const axios = require('axios').default +const bodyparser = require('body-parser') +const path = require('path') +const fs = require('fs') +const express = require('express') +const FormData = require('form-data') // const { MessageMedia } = require('./node_modules/whatsapp-web.js/src/structures'); -let whatsappWebGlobalPath = path.join(process.env.NODE_PATH, 'whatsapp-web.js', '/src/structures'); +let whatsappWebGlobalPath = path.join(process.env.NODE_PATH, 'whatsapp-web.js', '/src/structures') whatsappWebGlobalPath = whatsappWebGlobalPath.replace(':', '') console.log('whatsappWebGlobalPath: ', whatsappWebGlobalPath) console.log('process.env.NODE_PATH: ', process.env.NODE_PATH) -const { MessageMedia } = require(whatsappWebGlobalPath); +const { MessageMedia } = require(whatsappWebGlobalPath) const logger = require('logger') -const dotenv = require('dotenv'); -dotenv.config({ path: '.env' }); +const dotenv = require('dotenv') +dotenv.config({ path: '.env' }) -const mime = require('mime'); -const qrcode = require('qrcode-terminal'); -const omnihit = require('./funcs/omnihit.js'); -const { allowedNodeEnvironmentFlags } = require('process'); +const mime = require('mime') +const qrcode = require('qrcode-terminal') +const omnihit = require('./funcs/omnihit.js') +const { allowedNodeEnvironmentFlags } = require('process') + +const mongo = require('./funcs/mongoConn') + +const db = mongo.db(process.env.DB_MONGO_NAME) + +let auxCampaignMessage = '' -require("./funcs/tools.js")(); -let scheduler_messages_outbound; -let scheduler_monitor; -let scheduler_monitor_cell; -let client; +require("./funcs/tools.js")() +let scheduler_messages_outbound +let scheduler_monitor +let scheduler_monitor_cell +let scheduler_campaign_monitor + +let client // const PORT = 80; let sendSeen = false let unreadMessaesProcess const { imageUpload } = require('./helpers/image-uploader') -var QRCODE = "0"; -var mobileuid; -var destroy; +var QRCODE = "0" +var mobileuid +var destroy let asking_qrcode = false -const dbcc = require('./helpers/mysql_conn.js'); +const dbcc = require('./helpers/mysql_conn.js') -const removeDir = require('./helpers/remove_dir'); +const removeDir = require('./helpers/remove_dir') // (async()=>{ @@ -71,18 +82,20 @@ const removeDir = require('./helpers/remove_dir'); // Sleep const sleep = (ms) => { - return new Promise((resolve) => setTimeout(resolve, ms)); -}; + return new Promise((resolve) => setTimeout(resolve, ms)) +} +function getRandomNumber(min, max) { + return Math.floor(Math.random() * (max - min + 1)) + min +} +const app = express() -const app = express(); - -app.use(express.static(path.join(__dirname, 'public'))); +app.use(express.static(path.join(__dirname, 'public'))) //app.use(bodyparser.urlencoded({ extended: true })); -app.use(bodyparser.json()); +app.use(bodyparser.json()) -const sessionName = process.env.MOBILEUID; +const sessionName = process.env.MOBILEUID @@ -92,25 +105,24 @@ const sessionName = process.env.MOBILEUID; console.log('process.env.CLIENT_URL: ', process.env.CLIENT_URL) -console.log('1'); +console.log('1') // Connect to server -var io = require('socket.io-client'); +var io = require('socket.io-client') -// const socket = initIO('http://localhost:8024') +// const socket = initIO('http://localhost:8024') - -const socketIo = io(process.env.CLIENT_URL, { reconnect: true, maxHttpBufferSize: 1e8 }); +const socketIo = io(process.env.CLIENT_URL, { reconnect: true, maxHttpBufferSize: 1e8 }) socketIo.on('connect', async function () { - console.log('Made socket connection', socketIo.id); + console.log('Made socket connection', socketIo.id) console.log('process.env.WHATSAPP_ID: ', process.env.WHATSAPP_ID) - socketIo.emit('joinWhatsSession', process.env.WHATSAPP_ID); + socketIo.emit('joinWhatsSession', process.env.WHATSAPP_ID) sendSeen = true @@ -123,36 +135,48 @@ socketIo.on('connect', async function () { console.log('Entro no syncUnreadMessages ON CONNECTED SOCKET') await syncUnreadMessages(client) - client.sendPresenceAvailable(); + client.sendPresenceAvailable() }, 5000) } -}); +}) socketIo.on('message_from_server', function () { - console.log('message_from_server data: '); -}); + console.log('message_from_server data: ') +}) // socketIo.on('disconnect', function () { // console.log('disconnect'); // }); -// Send a message to the server 3 seconds after initial connection. +// var count = 0 + +// // Send a message to the server 3 seconds after initial connection. // setInterval(function () { -// socketIo.emit('message_from_client', 'Sent an event from the client!'); -// }, 3000); +// // socketIo.emit('message_from_client', 'Sent an event from the client!'); + +// const data = { +// id: "64d7fa0ce984e1cb781baee0", +// sent: count +// } + +// socketIo.emit("campaign_message_sent", data) + +// count++ + +// }, 3000) socketIo.on('connect_error', async function (err) { - console.log('connection errror', err); + console.log('connection errror', err) sendSeen = false if (mobileuid) { client.sendPresenceUnavailable() } -}); +}) // @@ -160,18 +184,18 @@ socketIo.on('connect_error', async function (err) { client = new Client({ authStrategy: new LocalAuth({ clientId: 'omnihit_sesssion' }), puppeteer: { args: ['--no-sandbox', '--disable-setuid-sandbox'], executablePath: process.env.CHROME_BIN || '/usr/bin/google-chrome-stable' }, -}); +}) -client.initialize(); +client.initialize() client.on("qr", async qr => { - console.log("Session:", sessionName); + console.log("Session:", sessionName) // Generate and scan this code with your phone - QRCODE = qr; + QRCODE = qr qrcode.generate(qr, { small: true }) - console.log('QR RECEIVED', qr); + console.log('QR RECEIVED', qr) // omnihit.qrcode(process.env.MOBILEUID, process.env.MOBILENAME, qr); // omnihit.monitor(process.env.MOBILEUID, process.env.MOBILENAME, "STARTUP"); @@ -185,13 +209,13 @@ client.on("qr", async qr => { function (err, result) { if (err) { - console.log("ERROR: " + err); + console.log("ERROR: " + err) reject(err) } else { resolve(result) } - }); + }) }) @@ -199,35 +223,35 @@ client.on("qr", async qr => { try { - let response = await axios.post(url, { whatsappId: process.env.WHATSAPP_ID }); + let response = await axios.post(url, { whatsappId: process.env.WHATSAPP_ID }) } catch (error) { - console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error); + console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error) } -}); +}) client.on("authenticated", async session => { - console.log(`Session: ${sessionName} AUTHENTICATED`); -}); + console.log(`Session: ${sessionName} AUTHENTICATED`) +}) client.on("auth_failure", async msg => { console.log( `Session: ${sessionName} AUTHENTICATION FAILURE! Reason: ${msg}` - ); + ) // omnihit.monitor(process.env.MOBILEUID, process.env.MOBILENAME, "AUTHFAILURE"); //reject(new Error("Error starting whatsapp session.")); -}); +}) client.on("ready", async () => { - console.log(`Session: ${sessionName} READY`); + console.log(`Session: ${sessionName} READY`) // console.log('>>>>>>>>>>>>>> ready client.ts MOBILE NUMBER: ', client.info["wid"]["user"]) - mobileuid = client.info["wid"]["user"]; - console.log(new Date().toISOString() + " >>> Mobile UID ::: " + mobileuid); + mobileuid = client.info["wid"]["user"] + console.log(new Date().toISOString() + " >>> Mobile UID ::: " + mobileuid) // logger.info(`Session: ${sessionName} READY`); @@ -244,13 +268,14 @@ client.on("ready", async () => { else { resolve(result) } - }); + }) }) if (whatsapp[0]['name'].includes(client.info["wid"]["user"])) { console.log('-----------------> THIS IS THE RIGHT NUMBER') + } else { console.log('-----------------> THIS IS THE WRONG NUMBER') @@ -265,10 +290,10 @@ client.on("ready", async () => { await client.logout() - let response = await axios.post(url, { number: read_number }); + let response = await axios.post(url, { number: read_number }) } catch (error) { - console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error); + console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error) } return @@ -283,14 +308,14 @@ client.on("ready", async () => { function (err, result) { if (err) { - console.log("ERROR: " + err); + console.log("ERROR: " + err) reject(err) } else { resolve(result) } - }); + }) }) @@ -300,10 +325,10 @@ client.on("ready", async () => { try { - let response = await axios.post(url, { whatsappId: process.env.WHATSAPP_ID }); + let response = await axios.post(url, { whatsappId: process.env.WHATSAPP_ID }) } catch (error) { - console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error); + console.log('There was an error on POST THE DATA TO URL: ', url, '\n' + error) } console.log('SEND SEEN: ', sendSeen) @@ -312,7 +337,7 @@ client.on("ready", async () => { await syncUnreadMessages(client) if (sendSeen) { - client.sendPresenceAvailable(); + client.sendPresenceAvailable() } // if(asking_qrcode){ @@ -324,26 +349,30 @@ client.on("ready", async () => { asking_qrcode = false console.log('PASSOU............') -}); +}) async function read() { - let chats = await client.getState(); - console.log(chats); + let chats = await client.getState() + console.log(chats) } client.on("message_create", async msg => { - // if (msg.hasMedia && msg.fromMe) // return - await handleMessage(msg); + if (msg.fromMe && msg.type === "chat" && auxCampaignMessage.trim() == msg?.body?.trim()) { + console.log('IGNORED MESSAGE SENT CAMPAIGN') + return + } + + await handleMessage(msg) -}); +}) client.on("media_uploaded", async msg => { @@ -354,23 +383,23 @@ client.on("media_uploaded", async msg => { if (msg.fromMe) { - msgContact = await client.getContactById(msg.to); + msgContact = await client.getContactById(msg.to) } else { - msgContact = await msg.getContact(); + msgContact = await msg.getContact() } - const chat = await msg.getChat(); + const chat = await msg.getChat() msgContact.getProfilePicUrl = await msgContact.getProfilePicUrl() - let quotedMsg = await msg.getQuotedMessage(); + let quotedMsg = await msg.getQuotedMessage() if (msg.hasMedia) { - media = await msg.downloadMedia(); + media = await msg.downloadMedia() } let data = { @@ -382,61 +411,93 @@ client.on("media_uploaded", async msg => { media: media } - socketIo.emit("media_uploaded", data); + socketIo.emit("media_uploaded", data) -}); +}) client.on("message_ack", async (msg, ack) => { + const campaigSend = await db.collection('campaignsends').findOne({ whatsapp_msg_id: msg.id.id }) + + if (campaigSend && ack == 3) { + + const updateResult = await db.collection('campaignsends').updateOne({ _id: ObjectId(campaigSend._id) }, + { + $set: { + read: new Date(new Date() + "UTC"), + ack: ack + } + }) + + // console.log('RESULT ACK UPDATE: ', updateResult) + + const read = await db.collection('campaignsends').countDocuments({ campaignId: ObjectId(campaigSend.campaignId), ack: 3 }) + + const data = { + id: ObjectId(campaigSend.campaignId), + read: read + } + + console.log('DATA ACK READ MESSAGE CAMPAIGN: ', data) + + socketIo.emit("campaign_message_sent", data) + + return + } + else if (campaigSend && (ack == 2 || ack == 1)) { + return + } + + let data = { whatsappId: process.env.WHATSAPP_ID, id: msg.id.id, ack: ack } - socketIo.emit("message_ack", data); + socketIo.emit("message_ack", data) -}); +}) socketIo.on('send_message', async data => { console.log('#') - console.log('--------------> send_message from number: ', mobileuid); - console.log('--------------> send_message to number: ', data.msg.number); - console.log('--------------> send_message body: ', data.msg.body); - console.log('--------------> send_message quotedMessageId: ', data.msg.quotedMessageId); - console.log('--------------> send_message linkPreview: ', data.msg.linkPreview); + console.log('--------------> send_message from number: ', mobileuid) + console.log('--------------> send_message to number: ', data.msg.number) + console.log('--------------> send_message body: ', data.msg.body) + console.log('--------------> send_message quotedMessageId: ', data.msg.quotedMessageId) + console.log('--------------> send_message linkPreview: ', data.msg.linkPreview) console.log('#') - const sentMessage = await client.sendMessage(data.msg.number, data.msg.body, { quotedMessageId: data.msg.quotedMessageId, linkPreview: data.msg.linkPreview }); + const sentMessage = await client.sendMessage(data.msg.number, data.msg.body, { quotedMessageId: data.msg.quotedMessageId, linkPreview: data.msg.linkPreview }) // console.log('=====================> sentMessage: ', sentMessage) -}); +}) socketIo.on('send_media', async data => { console.log('#') - console.log('--------------> send_message from number: ', mobileuid); - console.log('--------------> send_message to number: ', data.msg.number); + console.log('--------------> send_message from number: ', mobileuid) + console.log('--------------> send_message to number: ', data.msg.number) // console.log('--------------> send_message media: ', data.msg.media); - console.log('--------------> send_message sendAudioAsVoice: ', data.msg.sendAudioAsVoice); - console.log('--------------> data.msg.media.mimetype: ', data.msg.media.mimetype); - console.log('--------------> data.msg.media.filename: ', data.msg.media.filename); + console.log('--------------> send_message sendAudioAsVoice: ', data.msg.sendAudioAsVoice) + console.log('--------------> data.msg.media.mimetype: ', data.msg.media.mimetype) + console.log('--------------> data.msg.media.filename: ', data.msg.media.filename) console.log('#') - let media = new MessageMedia(data.msg.media.mimetype, data.msg.media.data, data.msg.media.file); + let media = new MessageMedia(data.msg.media.mimetype, data.msg.media.data, data.msg.media.file) if (media && !media.filename) media.filename = data.msg.media.filename - const sentMessage = await client.sendMessage(data.msg.number, media, { sendAudioAsVoice: data.msg.sendAudioAsVoice }); + const sentMessage = await client.sendMessage(data.msg.number, media, { sendAudioAsVoice: data.msg.sendAudioAsVoice }) // const fullFilename = process.cwd() + process.env.MEDIA_DOWNLOAD_IN + data.msg.media.filename; // console.log('fullFIlename: ', fullFilename) // fs.writeFileSync(fullFilename, data.msg.media.data, { encoding: 'base64' }); -}); +}) @@ -451,11 +512,11 @@ client.on("change_state", async newState => { let data = { action: 'change_state', whatsappId: process.env.WHATSAPP_ID - }; + } - await whatsappMonitor(newState, omnihit_url, data); + await whatsappMonitor(newState, omnihit_url, data) -}); +}) client.on("disconnected", async reason => { @@ -467,7 +528,7 @@ client.on("disconnected", async reason => { action: 'disconnected', whatsappId: process.env.WHATSAPP_ID, reason: reason - }; + } await removeDir(path.join(__dirname, '.wwebjs_auth', 'session-omnihit_sesssion')) @@ -476,21 +537,21 @@ client.on("disconnected", async reason => { process.exit() }, 3000) - await whatsappMonitor('OPENING', omnihit_url, data); + await whatsappMonitor('OPENING', omnihit_url, data) -}); +}) -app.get('/', function (req, res) { return res.send('Express + TypeScript Server'); }); +app.get('/', function (req, res) { return res.send('Express + TypeScript Server') }) app.post('/start', function (req, res) { - client.initialize(); - res.send("OK"); -}); + client.initialize() + res.send("OK") +}) app.post('/qr', function (req, res) { - res.send(QRCODE); -}); + res.send(QRCODE) +}) app.post('/api/getWbotMessage', async (req, res) => { @@ -499,37 +560,37 @@ app.post('/api/getWbotMessage', async (req, res) => { console.log('number: ', number, ' | limit: ', limit) - const wbotChat = await client.getChatById(number); + const wbotChat = await client.getChatById(number) const fetchWbotMessagesGradually = async () => { - const chatMessages = await wbotChat.fetchMessages({ limit }); + const chatMessages = await wbotChat.fetchMessages({ limit }) - const msgFound = chatMessages.find(msg => msg.id.id === messageId); + const msgFound = chatMessages.find(msg => msg.id.id === messageId) if (!msgFound && limit < 100) { - limit += 20; - return fetchWbotMessagesGradually(); + limit += 20 + return fetchWbotMessagesGradually() } - return msgFound; - }; + return msgFound + } try { - const msgFound = await fetchWbotMessagesGradually(); + const msgFound = await fetchWbotMessagesGradually() if (!msgFound) { - res.status(404).json({ message: "Cannot found message within 100 last messages" }); + res.status(404).json({ message: "Cannot found message within 100 last messages" }) return } - res.status(200).json({ message: "ok", data: msgFound }); + res.status(200).json({ message: "ok", data: msgFound }) } catch (err) { console.log('ERR_FETCH_WAPP_MSG: ', err) - res.status(404).json({ message: "ERR_FETCH_WAPP_MSG" }); + res.status(404).json({ message: "ERR_FETCH_WAPP_MSG" }) } }) @@ -543,7 +604,7 @@ app.post('/api/disconnect', async (req, res) => { await removeDir(path.join(__dirname, '.wwebjs_auth', 'session-omnihit_sesssion')) - await client.logout(); + await client.logout() setTimeout(() => { process.exit() @@ -554,7 +615,7 @@ app.post('/api/disconnect', async (req, res) => { console.log('There was an error on try disconnect the whatsapp: ', error) } - res.status(200).json({ message: "ok" }); + res.status(200).json({ message: "ok" }) }) @@ -569,16 +630,16 @@ app.post('/api/DeleteWhatsAppMessage', async (req, res) => { const messageToDelete = await getWbotMessage(messageId, number, limit) - await messageToDelete.delete(true); + await messageToDelete.delete(true) - res.status(200).json({ message: "ok", data: messageToDelete }); + res.status(200).json({ message: "ok", data: messageToDelete }) return } catch (error) { console.log('There was an error on try delete the massage: ', error) - res.status(500).json({ message: "There was an error on trying delete the message" }); + res.status(500).json({ message: "There was an error on trying delete the message" }) return } @@ -592,9 +653,9 @@ app.post('/api/GetProfilePicUrl', async (req, res) => { console.log('THE NUMBER: ', number) - const profilePicUrl = await client.getProfilePicUrl(`${number}@c.us`); + const profilePicUrl = await client.getProfilePicUrl(`${number}@c.us`) - res.status(200).json({ message: "ok", data: profilePicUrl }); + res.status(200).json({ message: "ok", data: profilePicUrl }) }) @@ -602,24 +663,24 @@ app.post('/api/restore', async (req, res) => { await restore(client) - res.status(200).json({ message: "ok" }); + res.status(200).json({ message: "ok" }) }) app.post('/api/sendSeen', async (req, res) => { let stat - const { number } = req.body + const { number } = req.body try { - stat = await client.getState(); + stat = await client.getState() // await syncUnreadMessages(client) - const wbotChat = await client.getChatById(number); + const wbotChat = await client.getChatById(number) - wbotChat.sendSeen(); + wbotChat.sendSeen() // const chatMessages = await wbotChat.fetchMessages({ limit: 100 }); @@ -627,13 +688,13 @@ app.post('/api/sendSeen', async (req, res) => { } catch (err) { - let terr = err.message; + let terr = err.message stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } - res.status(200).json({ message: "ok" }); + res.status(200).json({ message: "ok" }) }) app.get('/api/connection/status', async (req, res) => { @@ -642,17 +703,17 @@ app.get('/api/connection/status', async (req, res) => { try { - stat = await client.getState(); + stat = await client.getState() } catch (err) { - let terr = err.message; + let terr = err.message stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } - res.status(200).json({ message: "ok", data: stat }); + res.status(200).json({ message: "ok", data: stat }) }) @@ -661,7 +722,7 @@ const syncUnreadMessages = async (wbot) => { console.log('ENTROU NO UNREAD MESSAGES +++++++++++++=') - const chats = await wbot.getChats(); + const chats = await wbot.getChats() /* eslint-disable no-restricted-syntax */ /* eslint-disable no-await-in-loop */ @@ -673,7 +734,7 @@ const syncUnreadMessages = async (wbot) => { const unreadMessages = await chat.fetchMessages({ limit: chat.unreadCount - }); + }) for (const msg of unreadMessages) { @@ -683,38 +744,38 @@ const syncUnreadMessages = async (wbot) => { return } - await handleMessage(msg, wbot); + await handleMessage(msg, wbot) } console.log(':::::::::::::::::::::::::::::PASSOU') - await chat.sendSeen(); + await chat.sendSeen() } } -}; +} const getWbotMessage = async (messageId, number, limit,) => { - const wbotChat = await client.getChatById(number); + const wbotChat = await client.getChatById(number) const fetchWbotMessagesGradually = async () => { - const chatMessages = await wbotChat.fetchMessages({ limit }); + const chatMessages = await wbotChat.fetchMessages({ limit }) - const msgFound = chatMessages.find(msg => msg.id.id === messageId); + const msgFound = chatMessages.find(msg => msg.id.id === messageId) if (!msgFound && limit < 100) { - limit += 20; - return fetchWbotMessagesGradually(); + limit += 20 + return fetchWbotMessagesGradually() } - return msgFound; - }; + return msgFound + } try { - const msgFound = await fetchWbotMessagesGradually(); + const msgFound = await fetchWbotMessagesGradually() if (!msgFound) { return null @@ -743,9 +804,9 @@ async function whatsappMonitor(newState, omnihit_url, data) { try { - let response = await axios.post(omnihit_url, data); + let response = await axios.post(omnihit_url, data) } catch (error) { - console.log('There was an error on POST THE DATA TO URL: ', omnihit_url, '\n' + error); + console.log('There was an error on POST THE DATA TO URL: ', omnihit_url, '\n' + error) } } @@ -755,45 +816,45 @@ async function whatsappUpdateStatus(newState) { dbcc.query("UPDATE Whatsapps SET status = ? where id = ?", [newState, process.env.WHATSAPP_ID], function (err, result) { if (err) { - console.log("ERROR: " + err); - reject(err); + console.log("ERROR: " + err) + reject(err) } else { - resolve(result); + resolve(result) } - }); + }) - }); + }) } async function handleMessage(msg) { - console.log('Entrou no message_create'); + console.log('Entrou no message_create') - let msgContact = null; - let media = null; + let msgContact = null + let media = null if (msg.fromMe) { - msgContact = await client.getContactById(msg.to); + msgContact = await client.getContactById(msg.to) } else { console.log('################# RECEIVING MESSAGE FROM: ', msg.from, ' to ', msg.to) - msgContact = await msg.getContact(); + msgContact = await msg.getContact() } - const chat = await msg.getChat(); + const chat = await msg.getChat() - msgContact.getProfilePicUrl = await msgContact.getProfilePicUrl(); + msgContact.getProfilePicUrl = await msgContact.getProfilePicUrl() - let quotedMsg = await msg.getQuotedMessage(); + let quotedMsg = await msg.getQuotedMessage() if (msg.hasMedia) { - media = await msg.downloadMedia(); + media = await msg.downloadMedia() } let data = { @@ -803,26 +864,26 @@ async function handleMessage(msg) { chat: chat, quotedMsg: quotedMsg ? quotedMsg.id.id : null, media: media - }; + } - socketIo.emit("message_create", data); + socketIo.emit("message_create", data) } async function getlabels() { - var ret = await client.getContactById('551721379544-1625752306@g.us'); + var ret = await client.getContactById('551721379544-1625752306@g.us') //createGroup('The books', ['551100000000@c.us']); - console.log("-- Chats --------------------------------"); - console.log(ret); - return ret; + console.log("-- Chats --------------------------------") + console.log(ret) + return ret } function base64_encode(file) { // read binary data - var bitmap = fs.readFileSync(file); + var bitmap = fs.readFileSync(file) // convert binary data to base64 encoded string - return new Buffer(bitmap).toString('base64'); + return new Buffer(bitmap).toString('base64') } function getBase64(url) { @@ -834,17 +895,17 @@ function getBase64(url) { } function downloadMedia(url) { - let base64 = axios.get(url, { response: "arraybuffer" }).toString("base64"); - console.log("-- BASE64 -------------------------------"); - console.log(base64); - return base64; + let base64 = axios.get(url, { response: "arraybuffer" }).toString("base64") + console.log("-- BASE64 -------------------------------") + console.log(base64) + return base64 } async function validate(mobile, cb) { // let ret = await client.isRegisteredUser(mobile); - let ret = await client.isRegisteredUser(`${mobile}@c.us`); + let ret = await client.isRegisteredUser(`${mobile}@c.us`) // ///////////////////////////////////////////////////// 5571992888229 casaes @@ -854,7 +915,7 @@ async function validate(mobile, cb) { try { - _validNumber = (await client.getNumberId(`${mobile}@c.us`)).user; + _validNumber = (await client.getNumberId(`${mobile}@c.us`)).user } catch (err) { console.log(`Error number: ${err}`) @@ -865,7 +926,7 @@ async function validate(mobile, cb) { //////////////////////////////////////////////////////////////////// - cb({ isValid: ret, number: _validNumber }); + cb({ isValid: ret, number: _validNumber }) // cb(ret) } @@ -874,66 +935,68 @@ app.post('/api/validate', (req, res) => { console.log('ENTROU') - let mobile = req.body['mobile']; + let mobile = req.body['mobile'] - console.log(new Date() + " >>> Validating Registration Number ::: " + mobile + " on WhatsApp ..."); + console.log(new Date() + " >>> Validating Registration Number ::: " + mobile + " on WhatsApp ...") validate(mobile, function (e) { - res.send(e); + res.send(e) - }); -}); + }) +}) app.post('/api/chat', (req, res) => { - let mobile = req.body['mobile']; - let message = req.body['message']; - console.log(new Date() + " >>> Send Message ::: " + mobile + " ..."); - client.sendMessage(mobile, message); - res.send('OK'); -}); + let mobile = req.body['mobile'] + let message = req.body['message'] + console.log(new Date() + " >>> Send Message ::: " + mobile + " ...") + client.sendMessage(mobile, message) + res.send('OK') +}) app.post('/group', function (req, res) { //var ret = client.createGroup("Prueba", ["55@c.us"]); var ret = getlabels() - res.send(ret); -}); + res.send(ret) +}) app.post('/stop', function (req, res) { - client.destroy(); - res.send("OK"); -}); + client.destroy() + res.send("OK") +}) app.post('/api/status', function (req, res) { - res.send("OK"); -}); + res.send("OK") +}) async function monitor() { - let _nextime = 0; + let _nextime = 0 try { - clearInterval(scheduler_monitor); - let stat; + clearInterval(scheduler_monitor) + let stat if (mobileuid != undefined) { try { - stat = await client.getState(); + stat = await client.getState() } catch (err) { - let terr = err.message; + let terr = err.message stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } // omnihit.monitor(process.env.MOBILEUID, process.env.MOBILENAME, stat); - _nextime = 30000; + _nextime = 30000 } else { - _nextime = 10000; + _nextime = 10000 } console.log(`WHATSAPP_ID: ${process.env.WHATSAPP_ID} | CLIENT MOBILEUID: ${mobileuid} | NAME: ${process.env.MOBILENAME} | ENV MOBILEUID: ${process.env.MOBILEUID} | STATUS: ${stat}`) if (stat && stat === 'CONNECTED') { + + const result = await whatsappUpdateStatus('CONNECTED') if (result) @@ -944,27 +1007,132 @@ async function monitor() { } catch (error) { //new Date(new Date() + 'UTC') // console.log(new Date().toISOString() + " >>> ", error); - console.log(new Date(new Date() + 'UTC') + " >>> ", error); + console.log(new Date(new Date() + 'UTC') + " >>> ", error) } finally { - scheduler_monitor = setInterval(monitor, _nextime); + scheduler_monitor = setInterval(monitor, _nextime) + } +} + + +const sendCampaignMessage = async () => { + + try { + clearInterval(scheduler_campaign_monitor) + + if (mobileuid != undefined) { + + auxCampaignMessage = '' + + const campaign = await db.collection('campaigns').findOne({ 'campaign.whatsapp_sender': process.env.MOBILEUID, 'app.status': 'running' }) + + if (!campaign) + return + + const campaigSend = await db.collection('campaignsends').findOne({ campaignId: ObjectId(campaign._id), ack: 1 }) + + if (!campaigSend) { + + const countCampaignSend = await db.collection('campaignsends').countDocuments() + + if (countCampaignSend && countCampaignSend > 0) { + + await db.collection('campaigns').updateOne({ _id: ObjectId(campaign._id) }, + { + $set: { + 'app.status': 'success' + } + }) + + const data = { + id: ObjectId(campaign._id), + status: 'success' + } + + socketIo.emit("campaign_message_sent", data) + + } + + return + } + + + if (campaign.campaign?.textToSeconds && + campaign.campaign?.message && + campaign.campaign.message.trim().length > 0) { + + let msgMs = Math.round((campaign.campaign.message.trim().length * 0.1) * 1000) + + console.log('AWAITING MESSAGE TEXT LENGTH TO MILISECONDS: ', msgMs) + + await sleep(msgMs) + + } + + if (campaign.campaign?.secondStart && campaign.campaign?.secondEnd) { + + let randomTime = getRandomNumber(campaign.campaign.secondStart, campaign.campaign.secondEnd) * 1000 + + console.log('AWAITING RANDOM TIME TO SEND CAMPAIGN MESSAGE: ', randomTime) + + await sleep(randomTime) + } + + + auxCampaignMessage = campaign.campaign.message + + const sentMessage = await client.sendMessage(`${campaigSend.number}@c.us`, campaign.campaign.message) + + if (sentMessage) { + + const updateResult = await db.collection('campaignsends').updateOne({ _id: ObjectId(campaigSend._id) }, + { + $set: { + whatsapp_msg_id: sentMessage.id.id, + sender: process.env.MOBILEUID, + delivered: new Date(new Date() + "UTC"), + ack: 2 + } + }) + + // console.log('RESULT: ', updateResult) + + const sent = await db.collection('campaignsends').countDocuments({ campaignId: ObjectId(campaign._id), $or: [{ ack: 2 }, { ack: 3 }] }) + + const data = { + id: ObjectId(campaign._id), + sent + } + + socketIo.emit("campaign_message_sent", data) + + } + + + } + + } catch (error) { + console.log('error on sendCampaignMessage: ', error) + } + finally { + scheduler_campaign_monitor = setInterval(sendCampaignMessage, 3000) } } async function monitorCell() { try { - clearInterval(scheduler_monitor_cell); + clearInterval(scheduler_monitor_cell) // let _contact_mobile = "5511954803572@c.us"; - let _message = new Date(new Date() + 'UTC'); + let _message = new Date(new Date() + 'UTC') if (client.info && client.info["wid"]["user"]) { - client.sendMessage(`${process.env.MONITOR_NUMBER}@c.us`, _message); + client.sendMessage(`${process.env.MONITOR_NUMBER}@c.us`, _message) } } catch (error) { - console.log(`Error on send monitor message to number ${process.env.MONITOR_NUMBER} from monitorCell function: ${error}`); + console.log(`Error on send monitor message to number ${process.env.MONITOR_NUMBER} from monitorCell function: ${error}`) } finally { - scheduler_monitor_cell = setInterval(monitorCell, 1800000); + scheduler_monitor_cell = setInterval(monitorCell, 1800000) } } @@ -983,21 +1151,23 @@ function comercialBuss(until_hour) { } -scheduler_monitor = setInterval(monitor, 10000); +scheduler_monitor = setInterval(monitor, 10000) +scheduler_campaign_monitor = setInterval(sendCampaignMessage, 3000) app.listen(process.env.PORT || 8003, function () { - console.log("\u26A1[server]: Server is running at Port ::: " + process.env.PORT || 8003); -}); + console.log("\u26A1[server]: Server is running at Port ::: " + process.env.PORT || 8003) +}) process.on('uncaughtException', function (err) { - console.error(' '); + console.error(' ') console.error('----- ' + (new Date).toUTCString() + ' ----------------------------------') console.error('Erro uncaughtException: ', err.message) console.error(err.stack) - console.error(' '); + console.error(' ') return }); + diff --git a/TEST_SERVER1/whats/funcs/mongoConn.js b/TEST_SERVER1/whats/funcs/mongoConn.js new file mode 100644 index 0000000..8017bb6 --- /dev/null +++ b/TEST_SERVER1/whats/funcs/mongoConn.js @@ -0,0 +1,18 @@ +const { MongoClient } = require('mongodb') + +const uri = process.env.DB_MONGO_URL + +const mongo = new MongoClient(uri) + +async function run() { + try { + await mongo.connect() + console.log('Connectado ao mongo db') + } catch (err) { + console.log(err) + } +} + +run() + +module.exports = mongo \ No newline at end of file diff --git a/TEST_SERVER1/whats/package-lock.json b/TEST_SERVER1/whats/package-lock.json index ae06e37..f3082a6 100644 --- a/TEST_SERVER1/whats/package-lock.json +++ b/TEST_SERVER1/whats/package-lock.json @@ -14,27 +14,23 @@ "dotenv": "^16.0.0", "express": "^4.17.1", "form-data": "^4.0.0", + "fs-extra": "^11.1.0", "logger": "^0.0.1", "mime": "^2.4.5", "mongodb": "^4.1.1", + "mongoose": "^7.4.3", "multer": "^1.4.4", "mysql": "^2.18.1", "node-os-utils": "^1.3.5", "qr-encode": "^0.3.0", "qrcode-terminal": "^0.12.0", "socket.io": "^4.5.4", - "socket.io-client": "^4.5.4", - "whatsapp-web.js": "github:pedroslopez/whatsapp-web.js" + "socket.io-client": "^4.5.4" }, "devDependencies": { "nodemon": "^2.0.20" } }, - "node_modules/@pedroslopez/moduleraid": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@pedroslopez/moduleraid/-/moduleraid-5.0.2.tgz", - "integrity": "sha512-wtnBAETBVYZ9GvcbgdswRVSLkFkYAGv1KzwBBTeRXvGT9sb9cPllOgFFWXCn9PyARQ0H+Ijz6mmoRrGateUDxQ==" - }, "node_modules/@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -72,15 +68,6 @@ "@types/webidl-conversions": "*" } }, - "node_modules/@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "optional": true, - "dependencies": { - "@types/node": "*" - } - }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -99,38 +86,6 @@ "node": ">= 0.6" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "dependencies": { - "debug": "4" - }, - "engines": { - "node": ">= 6.0.0" - } - }, - "node_modules/agent-base/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/agent-base/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -149,91 +104,11 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, - "node_modules/archiver": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", - "optional": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "async": "^3.2.3", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "optional": true, - "dependencies": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/archiver-utils/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "node_modules/archiver-utils/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/archiver-utils/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "node_modules/archiver-utils/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "node_modules/async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -250,7 +125,8 @@ "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "node_modules/base64-js": { "version": "1.5.1", @@ -279,15 +155,6 @@ "node": "^4.5.0 || >= 5.9" } }, - "node_modules/big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "optional": true, - "engines": { - "node": ">=0.6" - } - }, "node_modules/bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", @@ -296,19 +163,6 @@ "node": "*" } }, - "node_modules/binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "optional": true, - "dependencies": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - }, - "engines": { - "node": "*" - } - }, "node_modules/binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", @@ -318,22 +172,6 @@ "node": ">=8" } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "optional": true - }, "node_modules/body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -361,6 +199,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -412,37 +251,11 @@ "ieee754": "^1.1.13" } }, - "node_modules/buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", - "engines": { - "node": "*" - } - }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "node_modules/buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "optional": true, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "optional": true, - "engines": { - "node": ">=0.2.0" - } - }, "node_modules/busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -491,18 +304,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "optional": true, - "dependencies": { - "traverse": ">=0.3.0 <0.4" - }, - "engines": { - "node": "*" - } - }, "node_modules/chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -530,11 +331,6 @@ "fsevents": "~2.3.2" } }, - "node_modules/chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -546,25 +342,11 @@ "node": ">= 0.8" } }, - "node_modules/compress-commons": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", - "optional": true, - "dependencies": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "node_modules/concat-stream": { "version": "1.6.2", @@ -661,39 +443,6 @@ "node": ">= 0.10" } }, - "node_modules/crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "optional": true, - "bin": { - "crc32": "bin/crc32.njs" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/crc32-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", - "optional": true, - "dependencies": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - }, - "engines": { - "node": ">= 10" - } - }, - "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "dependencies": { - "node-fetch": "2.6.7" - } - }, "node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -735,11 +484,6 @@ "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/devtools-protocol": { - "version": "0.0.969999", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", - "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==" - }, "node_modules/dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", @@ -776,51 +520,6 @@ "node": ">=12" } }, - "node_modules/duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "optional": true, - "dependencies": { - "readable-stream": "^2.0.2" - } - }, - "node_modules/duplexer2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "node_modules/duplexer2/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/duplexer2/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "node_modules/duplexer2/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -834,14 +533,6 @@ "node": ">= 0.8" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/engine.io": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz", @@ -1096,68 +787,6 @@ "node": ">= 0.8" } }, - "node_modules/extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" - }, - "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" - } - }, - "node_modules/extract-zip/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/extract-zip/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dependencies": { - "pump": "^3.0.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/extract-zip/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, - "node_modules/fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "dependencies": { - "pend": "~1.2.0" - } - }, "node_modules/fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -1198,30 +827,6 @@ "node": ">= 0.8" } }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fluent-ffmpeg": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", - "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=", - "dependencies": { - "async": ">=0.2.9", - "which": "^1.1.1" - }, - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/follow-redirects": { "version": "1.14.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", @@ -1270,55 +875,17 @@ "node": ">= 0.6" } }, - "node_modules/fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "optional": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "node_modules/fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "optional": true, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "engines": { - "node": ">=0.6" - } - }, - "node_modules/fstream/node_modules/rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "optional": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" + "node": ">=14.14" } }, "node_modules/function-bind": { @@ -1339,25 +906,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -1373,8 +921,7 @@ "node_modules/graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "optional": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "node_modules/has": { "version": "1.0.3", @@ -1430,39 +977,6 @@ "node": ">= 0.8" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dependencies": { - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/https-proxy-agent/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/https-proxy-agent/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -1499,24 +1013,15 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "node_modules/ipaddr.js": { "version": "1.9.1", @@ -1573,16 +1078,10 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, "node_modules/jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "optional": true, "dependencies": { "universalify": "^2.0.0" }, @@ -1590,106 +1089,14 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsqr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", - "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==" - }, - "node_modules/lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "optional": true, - "dependencies": { - "readable-stream": "^2.0.5" - }, + "node_modules/kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==", "engines": { - "node": ">= 0.6.3" + "node": ">=12.0.0" } }, - "node_modules/lazystream/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "node_modules/lazystream/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/lazystream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "node_modules/lazystream/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, - "node_modules/listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "optional": true - }, - "node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "optional": true - }, - "node_modules/lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "optional": true - }, - "node_modules/lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "optional": true - }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "optional": true - }, - "node_modules/lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "optional": true - }, "node_modules/logger": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/logger/-/logger-0.0.1.tgz", @@ -1759,6 +1166,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "dependencies": { "brace-expansion": "^1.1.7" }, @@ -1782,11 +1190,6 @@ "mkdirp": "bin/cmd.js" } }, - "node_modules/mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, "node_modules/mongodb": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.5.0.tgz", @@ -1805,14 +1208,128 @@ } }, "node_modules/mongodb-connection-string-url": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", - "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "dependencies": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" } }, + "node_modules/mongoose": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", + "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "dependencies": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/mongoose" + } + }, + "node_modules/mongoose/node_modules/bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/mongoose/node_modules/mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "dependencies": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.201.0", + "@mongodb-js/zstd": "^1.1.0", + "kerberos": "^2.0.1", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "@mongodb-js/zstd": { + "optional": true + }, + "kerberos": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongoose/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, + "node_modules/mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "dependencies": { + "debug": "4.x" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/mquery/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/mquery/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -1890,54 +1407,11 @@ "node": ">= 0.6" } }, - "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dependencies": { - "whatwg-url": "^5.0.0" - }, - "engines": { - "node": "4.x || >=6.0.0" - }, - "peerDependencies": { - "encoding": "^0.1.0" - }, - "peerDependenciesMeta": { - "encoding": { - "optional": true - } - } - }, - "node_modules/node-fetch/node_modules/tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "node_modules/node-fetch/node_modules/webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "node_modules/node-fetch/node_modules/whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "dependencies": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, "node_modules/node-os-utils": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/node-os-utils/-/node-os-utils-1.3.6.tgz", "integrity": "sha512-WympE9ELtdOzNak/rAuuIV5DwvX/PTJtN0LjyWeGyTTR2Kt0sY56ldLoGbVBnfM1dz46VeO3sHcNZI5BZ+EB+w==" }, - "node_modules/node-webpmux": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-webpmux/-/node-webpmux-3.1.1.tgz", - "integrity": "sha512-vG75BAe9zKghN+Y+XsJMPdOfVyesn1MmGvd/DMxeQ6gtpB3U053yCWXO1Gl2QWXTfU1++7flTihv/yB6EEdtKQ==" - }, "node_modules/nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", @@ -2000,7 +1474,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "devOptional": true, + "dev": true, "engines": { "node": ">=0.10.0" } @@ -2032,47 +1506,6 @@ "node": ">= 0.8" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "engines": { - "node": ">=6" - } - }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -2081,32 +1514,11 @@ "node": ">= 0.8" } }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "node_modules/pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", @@ -2119,30 +1531,11 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "node_modules/progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -2155,26 +1548,12 @@ "node": ">= 0.10" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "node_modules/pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", @@ -2183,50 +1562,6 @@ "node": ">=6" } }, - "node_modules/puppeteer": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.5.2.tgz", - "integrity": "sha512-DJAyXODBikZ3xPs8C35CtExEw78LZR9RyelGDAs0tX1dERv3OfW7qpQ9VPBgsfz+hG2HiMTO/Tyf7BuMVWsrxg==", - "hasInstallScript": true, - "dependencies": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.969999", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.0", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" - }, - "engines": { - "node": ">=10.18.1" - } - }, - "node_modules/puppeteer/node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/puppeteer/node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - }, "node_modules/qr-encode": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/qr-encode/-/qr-encode-0.3.0.tgz", @@ -2276,49 +1611,6 @@ "node": ">= 0.8" } }, - "node_modules/readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", - "optional": true, - "dependencies": { - "minimatch": "^5.1.0" - } - }, - "node_modules/readdir-glob/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/readdir-glob/node_modules/minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "optional": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -2331,20 +1623,6 @@ "node": ">=8.10.0" } }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -2482,12 +1760,6 @@ "node": ">= 0.8.0" } }, - "node_modules/setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "optional": true - }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -2506,6 +1778,11 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, "node_modules/simple-update-notifier": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", @@ -2647,11 +1924,11 @@ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "dependencies": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" }, "engines": { @@ -2692,14 +1969,6 @@ "node": ">=0.8.0" } }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -2712,37 +1981,6 @@ "node": ">=4" } }, - "node_modules/tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "dependencies": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "node_modules/tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "dependencies": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -2786,15 +2024,6 @@ "node": ">=12" } }, - "node_modules/traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "optional": true, - "engines": { - "node": "*" - } - }, "node_modules/type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -2812,15 +2041,6 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, - "node_modules/unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "dependencies": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "node_modules/undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -2831,7 +2051,6 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "optional": true, "engines": { "node": ">= 10.0.0" } @@ -2844,60 +2063,6 @@ "node": ">= 0.8" } }, - "node_modules/unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "optional": true, - "dependencies": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - } - }, - "node_modules/unzipper/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "node_modules/unzipper/node_modules/readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "node_modules/unzipper/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "node_modules/unzipper/node_modules/string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "dependencies": { - "safe-buffer": "~5.1.0" - } - }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -2927,39 +2092,6 @@ "node": ">=12" } }, - "node_modules/whatsapp-web.js": { - "version": "1.19.3", - "resolved": "git+ssh://git@github.com/pedroslopez/whatsapp-web.js.git#f1607752dd8411df4020bcfd6ee2b7533210b32e", - "license": "Apache-2.0", - "dependencies": { - "@pedroslopez/moduleraid": "^5.0.2", - "fluent-ffmpeg": "^2.1.2", - "jsqr": "^1.3.1", - "mime": "^3.0.0", - "node-fetch": "^2.6.5", - "node-webpmux": "^3.1.0", - "puppeteer": "^13.0.0" - }, - "engines": { - "node": ">=12.0.0" - }, - "optionalDependencies": { - "archiver": "^5.3.1", - "fs-extra": "^10.1.0", - "unzipper": "^0.10.11" - } - }, - "node_modules/whatsapp-web.js/node_modules/mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==", - "bin": { - "mime": "cli.js" - }, - "engines": { - "node": ">=10.0.0" - } - }, "node_modules/whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", @@ -2972,42 +2104,6 @@ "node": ">=12" } }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", @@ -3023,37 +2119,9 @@ "engines": { "node": ">=0.4" } - }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "node_modules/zip-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", - "optional": true, - "dependencies": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">= 10" - } } }, "dependencies": { - "@pedroslopez/moduleraid": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/@pedroslopez/moduleraid/-/moduleraid-5.0.2.tgz", - "integrity": "sha512-wtnBAETBVYZ9GvcbgdswRVSLkFkYAGv1KzwBBTeRXvGT9sb9cPllOgFFWXCn9PyARQ0H+Ijz6mmoRrGateUDxQ==" - }, "@socket.io/component-emitter": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.0.tgz", @@ -3091,15 +2159,6 @@ "@types/webidl-conversions": "*" } }, - "@types/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-Cn6WYCm0tXv8p6k+A8PvbDG763EDpBoTzHdA+Q/MF6H3sapGjCm9NzoaJncJS9tUKSuCoDs9XHxYYsQDgxR6kw==", - "optional": true, - "requires": { - "@types/node": "*" - } - }, "abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -3115,29 +2174,6 @@ "negotiator": "0.6.3" } }, - "agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "anymatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz", @@ -3153,87 +2189,11 @@ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" }, - "archiver": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-5.3.1.tgz", - "integrity": "sha512-8KyabkmbYrH+9ibcTScQ1xCJC/CGcugdVIwB+53f5sZziXgwUh3iXlAlANMxcZyDEfTHMe6+Z5FofV8nopXP7w==", - "optional": true, - "requires": { - "archiver-utils": "^2.1.0", - "async": "^3.2.3", - "buffer-crc32": "^0.2.1", - "readable-stream": "^3.6.0", - "readdir-glob": "^1.0.0", - "tar-stream": "^2.2.0", - "zip-stream": "^4.1.0" - } - }, - "archiver-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-2.1.0.tgz", - "integrity": "sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==", - "optional": true, - "requires": { - "glob": "^7.1.4", - "graceful-fs": "^4.2.0", - "lazystream": "^1.0.0", - "lodash.defaults": "^4.2.0", - "lodash.difference": "^4.5.0", - "lodash.flatten": "^4.4.0", - "lodash.isplainobject": "^4.0.6", - "lodash.union": "^4.6.0", - "normalize-path": "^3.0.0", - "readable-stream": "^2.0.0" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" }, - "async": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.3.tgz", - "integrity": "sha512-spZRyzKL5l5BZQrr/6m/SqFdBN0q3OCI0f9rjfBzCMBIP4p75P620rR3gTmaksNOhmzgdxcaxdNfMy6anrbM0g==" - }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -3250,7 +2210,8 @@ "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true }, "base64-js": { "version": "1.5.1", @@ -3262,49 +2223,17 @@ "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==" }, - "big-integer": { - "version": "1.6.51", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.51.tgz", - "integrity": "sha512-GPEid2Y9QU1Exl1rpO9B2IPJGHPSupF5GnVIP0blYvNOMer2bTvSWs1jGOUg04hTmu67nmLsQ9TBo1puaotBHg==", - "optional": true - }, "bignumber.js": { "version": "9.0.0", "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==" }, - "binary": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/binary/-/binary-0.3.0.tgz", - "integrity": "sha512-D4H1y5KYwpJgK8wk1Cue5LLPgmwHKYSChkbspQg5JtVuR5ulGckxfR62H3AE9UDkdMC8yyXlqYihuz3Aqg2XZg==", - "optional": true, - "requires": { - "buffers": "~0.1.1", - "chainsaw": "~0.1.0" - } - }, "binary-extensions": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", "dev": true }, - "bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "requires": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "bluebird": { - "version": "3.4.7", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.4.7.tgz", - "integrity": "sha512-iD3898SR7sWVRHbiQv+sHUtHnMvC1o3nW5rAcqnq3uOn07DSAppZYUkIGslDz6gXC7HfunPe7YVBgoEJASPcHA==", - "optional": true - }, "body-parser": { "version": "1.20.0", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.0.tgz", @@ -3328,6 +2257,7 @@ "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, "requires": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -3359,28 +2289,11 @@ "ieee754": "^1.1.13" } }, - "buffer-crc32": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", - "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" - }, "buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" }, - "buffer-indexof-polyfill": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz", - "integrity": "sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==", - "optional": true - }, - "buffers": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/buffers/-/buffers-0.1.1.tgz", - "integrity": "sha512-9q/rDEGSb/Qsvv2qvzIzdluL5k7AaJOTrw23z9reQthrbF7is4CtlT0DXyO1oei2DCp4uojjzQ7igaSHp1kAEQ==", - "optional": true - }, "busboy": { "version": "0.2.14", "resolved": "https://registry.npmjs.org/busboy/-/busboy-0.2.14.tgz", @@ -3422,15 +2335,6 @@ "get-intrinsic": "^1.0.2" } }, - "chainsaw": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/chainsaw/-/chainsaw-0.1.0.tgz", - "integrity": "sha512-75kWfWt6MEKNC8xYXIdRpDehRYY/tNSgwKaJq+dbbDcxORuVrrQ+SEHoWsniVn9XPYfP4gmdWIeDk/4YNp1rNQ==", - "optional": true, - "requires": { - "traverse": ">=0.3.0 <0.4" - } - }, "chokidar": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", @@ -3447,11 +2351,6 @@ "readdirp": "~3.6.0" } }, - "chownr": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", - "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" - }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -3460,22 +2359,11 @@ "delayed-stream": "~1.0.0" } }, - "compress-commons": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-4.1.1.tgz", - "integrity": "sha512-QLdDLCKNV2dtoTorqgxngQCMA+gWXkM/Nwu7FpeBhk/RdkzimqC3jueb/FDmaZeXh+uby1jkBqE3xArsLBE5wQ==", - "optional": true, - "requires": { - "buffer-crc32": "^0.2.13", - "crc32-stream": "^4.0.2", - "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" - } - }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true }, "concat-stream": { "version": "1.6.2", @@ -3559,30 +2447,6 @@ "vary": "^1" } }, - "crc-32": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", - "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", - "optional": true - }, - "crc32-stream": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-4.0.2.tgz", - "integrity": "sha512-DxFZ/Hk473b/muq1VJ///PMNLj0ZMnzye9thBpmjpJKCc5eMgB95aK8zCGrGfQ90cWo561Te6HK9D+j4KPdM6w==", - "optional": true, - "requires": { - "crc-32": "^1.2.0", - "readable-stream": "^3.4.0" - } - }, - "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", - "requires": { - "node-fetch": "2.6.7" - } - }, "debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", @@ -3611,11 +2475,6 @@ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==" }, - "devtools-protocol": { - "version": "0.0.969999", - "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.969999.tgz", - "integrity": "sha512-6GfzuDWU0OFAuOvBokXpXPLxjOJ5DZ157Ue3sGQQM3LgAamb8m0R0ruSfN0DDu+XG5XJgT50i6zZ/0o8RglreQ==" - }, "dicer": { "version": "0.2.5", "resolved": "https://registry.npmjs.org/dicer/-/dicer-0.2.5.tgz", @@ -3648,53 +2507,6 @@ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.0.tgz", "integrity": "sha512-qD9WU0MPM4SWLPJy/r2Be+2WgQj8plChsyrCNQzW/0WjvcJQiKQJ9mH3ZgB3fxbUUxgc/11ZJ0Fi5KiimWGz2Q==" }, - "duplexer2": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", - "integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==", - "optional": true, - "requires": { - "readable-stream": "^2.0.2" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -3705,14 +2517,6 @@ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" }, - "end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "requires": { - "once": "^1.4.0" - } - }, "engine.io": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.2.1.tgz", @@ -3894,48 +2698,6 @@ } } }, - "extract-zip": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", - "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "requires": { - "@types/yauzl": "^2.9.1", - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "requires": { - "pump": "^3.0.0" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, - "fd-slicer": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", - "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", - "requires": { - "pend": "~1.2.0" - } - }, "fill-range": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", @@ -3969,24 +2731,6 @@ } } }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "fluent-ffmpeg": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/fluent-ffmpeg/-/fluent-ffmpeg-2.1.2.tgz", - "integrity": "sha1-yVLeIkD4EuvaCqgAbXd27irPfXQ=", - "requires": { - "async": ">=0.2.9", - "which": "^1.1.1" - } - }, "follow-redirects": { "version": "1.14.9", "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.9.tgz", @@ -4012,50 +2756,16 @@ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" }, - "fs-constants": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", - "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" - }, "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", - "optional": true, + "version": "11.1.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.1.tgz", + "integrity": "sha512-MGIE4HOvQCeUCzmlHs0vXpih4ysz4wg9qiSAu6cd42lVwPbTM1TjV7RusoyQqMmk/95gdQZX72u+YW+c3eEpFQ==", "requires": { "graceful-fs": "^4.2.0", "jsonfile": "^6.0.1", "universalify": "^2.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" - }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "optional": true, - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "dependencies": { - "rimraf": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", - "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", - "optional": true, - "requires": { - "glob": "^7.1.3" - } - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -4071,19 +2781,6 @@ "has-symbols": "^1.0.1" } }, - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, "glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", @@ -4096,8 +2793,7 @@ "graceful-fs": { "version": "4.2.10", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.10.tgz", - "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==", - "optional": true + "integrity": "sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==" }, "has": { "version": "1.0.3", @@ -4137,30 +2833,6 @@ } } }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -4180,24 +2852,15 @@ "integrity": "sha1-SMptcvbGo68Aqa1K5odr44ieKwk=", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=" + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" }, "ipaddr.js": { "version": "1.9.1", @@ -4239,116 +2902,19 @@ "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" - }, "jsonfile": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", - "optional": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" } }, - "jsqr": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/jsqr/-/jsqr-1.4.0.tgz", - "integrity": "sha512-dxLob7q65Xg2DvstYkRpkYtmKm2sPJ9oFhrhmudT1dZvNFFTlroai3AWSpLey/w5vMcLBXRgOJsbXpdN9HzU/A==" - }, - "lazystream": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", - "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", - "optional": true, - "requires": { - "readable-stream": "^2.0.5" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, - "listenercount": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/listenercount/-/listenercount-1.0.1.tgz", - "integrity": "sha512-3mk/Zag0+IJxeDrxSgaDPy4zZ3w05PRZeJNnlWhzFz5OkX49J4krc+A8X2d2M69vGMBEX0uyl8M+W+8gH+kBqQ==", - "optional": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "requires": { - "p-locate": "^4.1.0" - } - }, - "lodash.defaults": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz", - "integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ==", - "optional": true - }, - "lodash.difference": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/lodash.difference/-/lodash.difference-4.5.0.tgz", - "integrity": "sha512-dS2j+W26TQ7taQBGN8Lbbq04ssV3emRw4NY58WErlTO29pIqS0HmoT5aJ9+TUQ1N3G+JOZSji4eugsWwGp9yPA==", - "optional": true - }, - "lodash.flatten": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flatten/-/lodash.flatten-4.4.0.tgz", - "integrity": "sha512-C5N2Z3DgnnKr0LOpv/hKCgKdb7ZZwafIrsesve6lmzvZIRZRGaZ/l6Q8+2W7NaT+ZwO3fFlSCzCzrDCFdJfZ4g==", - "optional": true - }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "optional": true - }, - "lodash.union": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/lodash.union/-/lodash.union-4.6.0.tgz", - "integrity": "sha512-c4pB2CdGrGdjMKYLA+XiRDO7Y0PRQbm/Gzg8qMj+QH+pFVAoTp5sBpO0odL3FjoPCGjK96p6qsP+yQoiLoOBcw==", - "optional": true + "kareem": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.5.1.tgz", + "integrity": "sha512-7jFxRVm+jD+rkq3kY0iZDJfsO2/t4BBPeEb2qKn2lR/9KhuksYk5hxzfRYWMPV8P/x2d0kHD306YyWLzjjH+uA==" }, "logger": { "version": "0.0.1", @@ -4398,6 +2964,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, "requires": { "brace-expansion": "^1.1.7" } @@ -4415,11 +2982,6 @@ "minimist": "^1.2.6" } }, - "mkdirp-classic": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", - "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" - }, "mongodb": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.5.0.tgz", @@ -4433,14 +2995,79 @@ } }, "mongodb-connection-string-url": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz", - "integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==", + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", "requires": { "@types/whatwg-url": "^8.2.1", "whatwg-url": "^11.0.0" } }, + "mongoose": { + "version": "7.4.3", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-7.4.3.tgz", + "integrity": "sha512-eok0lW6mZJHK2vVSWyJb9tUfPMUuRF3h7YC4pU2K2/YSZBlNDUwvKsHgftMOANbokP2Ry+4ylvzAdW4KjkRFjw==", + "requires": { + "bson": "^5.4.0", + "kareem": "2.5.1", + "mongodb": "5.7.0", + "mpath": "0.9.0", + "mquery": "5.0.0", + "ms": "2.1.3", + "sift": "16.0.1" + }, + "dependencies": { + "bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==" + }, + "mongodb": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.7.0.tgz", + "integrity": "sha512-zm82Bq33QbqtxDf58fLWBwTjARK3NSvKYjyz997KSy6hpat0prjeX/kxjbPVyZY60XYPDNETaHkHJI2UCzSLuw==", + "requires": { + "bson": "^5.4.0", + "mongodb-connection-string-url": "^2.6.0", + "saslprep": "^1.0.3", + "socks": "^2.7.1" + } + }, + "ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + } + } + }, + "mpath": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.9.0.tgz", + "integrity": "sha512-ikJRQTk8hw5DEoFVxHG1Gn9T/xcjtdnOKIU1JTmGjZZlg9LST2mBLmcX3/ICIbgJydT2GOc15RnNy5mHmzfSew==" + }, + "mquery": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-5.0.0.tgz", + "integrity": "sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==", + "requires": { + "debug": "4.x" + }, + "dependencies": { + "debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "requires": { + "ms": "2.1.2" + } + }, + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, "ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -4511,45 +3138,11 @@ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==" }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "requires": { - "whatwg-url": "^5.0.0" - }, - "dependencies": { - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - } - } - }, "node-os-utils": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/node-os-utils/-/node-os-utils-1.3.6.tgz", "integrity": "sha512-WympE9ELtdOzNak/rAuuIV5DwvX/PTJtN0LjyWeGyTTR2Kt0sY56ldLoGbVBnfM1dz46VeO3sHcNZI5BZ+EB+w==" }, - "node-webpmux": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-webpmux/-/node-webpmux-3.1.1.tgz", - "integrity": "sha512-vG75BAe9zKghN+Y+XsJMPdOfVyesn1MmGvd/DMxeQ6gtpB3U053yCWXO1Gl2QWXTfU1++7flTihv/yB6EEdtKQ==" - }, "nodemon": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-2.0.20.tgz", @@ -4598,7 +3191,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "devOptional": true + "dev": true }, "object-assign": { "version": "4.1.1", @@ -4618,84 +3211,27 @@ "ee-first": "1.1.1" } }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "requires": { - "wrappy": "1" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "requires": { - "p-limit": "^2.2.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" - }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" - }, "path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" }, - "pend": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", - "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" - }, "picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "requires": { - "find-up": "^4.0.0" - } - }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" }, - "progress": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", - "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" - }, "proxy-addr": { "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", @@ -4705,65 +3241,17 @@ "ipaddr.js": "1.9.1" } }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" - }, "pstree.remy": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", "dev": true }, - "pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "requires": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "punycode": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" }, - "puppeteer": { - "version": "13.5.2", - "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.5.2.tgz", - "integrity": "sha512-DJAyXODBikZ3xPs8C35CtExEw78LZR9RyelGDAs0tX1dERv3OfW7qpQ9VPBgsfz+hG2HiMTO/Tyf7BuMVWsrxg==", - "requires": { - "cross-fetch": "3.1.5", - "debug": "4.3.4", - "devtools-protocol": "0.0.969999", - "extract-zip": "2.0.1", - "https-proxy-agent": "5.0.0", - "pkg-dir": "4.2.0", - "progress": "2.0.3", - "proxy-from-env": "1.1.0", - "rimraf": "3.0.2", - "tar-fs": "2.1.1", - "unbzip2-stream": "1.4.3", - "ws": "8.5.0" - }, - "dependencies": { - "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" - } - } - }, "qr-encode": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/qr-encode/-/qr-encode-0.3.0.tgz", @@ -4798,45 +3286,6 @@ "unpipe": "1.0.0" } }, - "readable-stream": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", - "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, - "readdir-glob": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.2.tgz", - "integrity": "sha512-6RLVvwJtVwEDfPdn6X6Ille4/lxGl0ATOY4FN/B9nxQcgOazvvI0nodiD19ScKq0PvA/29VpaOQML36o5IzZWA==", - "optional": true, - "requires": { - "minimatch": "^5.1.0" - }, - "dependencies": { - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "optional": true, - "requires": { - "balanced-match": "^1.0.0" - } - }, - "minimatch": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.0.tgz", - "integrity": "sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg==", - "optional": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, "readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -4846,14 +3295,6 @@ "picomatch": "^2.2.1" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "requires": { - "glob": "^7.1.3" - } - }, "safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", @@ -4952,12 +3393,6 @@ "send": "0.17.2" } }, - "setimmediate": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "optional": true - }, "setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -4973,6 +3408,11 @@ "object-inspect": "^1.9.0" } }, + "sift": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-16.0.1.tgz", + "integrity": "sha512-Wv6BjQ5zbhW7VFefWusVP33T/EM0vYikCaQ2qR8yULbsilAT8/wQaXvuQ3ptGLpoKx+lihJE3y2UTgKDyyNHZQ==" + }, "simple-update-notifier": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.0.7.tgz", @@ -5079,11 +3519,11 @@ } }, "socks": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz", - "integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==", + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", "requires": { - "ip": "^1.1.5", + "ip": "^2.0.0", "smart-buffer": "^4.2.0" } }, @@ -5111,14 +3551,6 @@ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz", "integrity": "sha1-gIudDlb8Jz2Am6VzOOkpkZoanxo=" }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "requires": { - "safe-buffer": "~5.2.0" - } - }, "supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", @@ -5128,34 +3560,6 @@ "has-flag": "^3.0.0" } }, - "tar-fs": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", - "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", - "requires": { - "chownr": "^1.1.1", - "mkdirp-classic": "^0.5.2", - "pump": "^3.0.0", - "tar-stream": "^2.1.4" - } - }, - "tar-stream": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", - "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", - "requires": { - "bl": "^4.0.3", - "end-of-stream": "^1.4.1", - "fs-constants": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" - } - }, - "through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -5187,12 +3591,6 @@ "punycode": "^2.1.1" } }, - "traverse": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/traverse/-/traverse-0.3.9.tgz", - "integrity": "sha512-iawgk0hLP3SxGKDfnDJf8wTz4p2qImnyihM5Hh/sGvQ3K37dPi/w8sRhdNIxYA1TwFwc5mDhIJq+O0RsvXBKdQ==", - "optional": true - }, "type-is": { "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", @@ -5207,15 +3605,6 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=" }, - "unbzip2-stream": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", - "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", - "requires": { - "buffer": "^5.2.1", - "through": "^2.3.8" - } - }, "undefsafe": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", @@ -5225,70 +3614,13 @@ "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", - "optional": true + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" }, "unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" }, - "unzipper": { - "version": "0.10.11", - "resolved": "https://registry.npmjs.org/unzipper/-/unzipper-0.10.11.tgz", - "integrity": "sha512-+BrAq2oFqWod5IESRjL3S8baohbevGcVA+teAIOYWM3pDVdseogqbzhhvvmiyQrUNKFUnDMtELW3X8ykbyDCJw==", - "optional": true, - "requires": { - "big-integer": "^1.6.17", - "binary": "~0.3.0", - "bluebird": "~3.4.1", - "buffer-indexof-polyfill": "~1.0.0", - "duplexer2": "~0.1.4", - "fstream": "^1.0.12", - "graceful-fs": "^4.2.2", - "listenercount": "~1.0.1", - "readable-stream": "~2.3.6", - "setimmediate": "~1.0.4" - }, - "dependencies": { - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "optional": true - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "optional": true - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - } - } - }, "util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -5309,29 +3641,6 @@ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==" }, - "whatsapp-web.js": { - "version": "git+ssh://git@github.com/pedroslopez/whatsapp-web.js.git#f1607752dd8411df4020bcfd6ee2b7533210b32e", - "from": "whatsapp-web.js@github:pedroslopez/whatsapp-web.js", - "requires": { - "@pedroslopez/moduleraid": "^5.0.2", - "archiver": "^5.3.1", - "fluent-ffmpeg": "^2.1.2", - "fs-extra": "^10.1.0", - "jsqr": "^1.3.1", - "mime": "^3.0.0", - "node-fetch": "^2.6.5", - "node-webpmux": "^3.1.0", - "puppeteer": "^13.0.0", - "unzipper": "^0.10.11" - }, - "dependencies": { - "mime": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz", - "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==" - } - } - }, "whatwg-url": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", @@ -5341,24 +3650,6 @@ "webidl-conversions": "^7.0.0" } }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "requires": { - "isexe": "^2.0.0" - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==" - }, "xmlhttprequest-ssl": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz", @@ -5368,26 +3659,6 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==" - }, - "yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", - "requires": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, - "zip-stream": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-4.1.0.tgz", - "integrity": "sha512-zshzwQW7gG7hjpBlgeQP9RuyPGNxvJdzR8SUM3QhxCnLjWN2E7j3dOvpeDcQoETfHx0urRS7EtmVToql7YpU4A==", - "optional": true, - "requires": { - "archiver-utils": "^2.1.0", - "compress-commons": "^4.1.0", - "readable-stream": "^3.6.0" - } } } } diff --git a/TEST_SERVER1/whats/package.json b/TEST_SERVER1/whats/package.json index b2f7256..6f8bdd7 100644 --- a/TEST_SERVER1/whats/package.json +++ b/TEST_SERVER1/whats/package.json @@ -15,17 +15,18 @@ "dotenv": "^16.0.0", "express": "^4.17.1", "form-data": "^4.0.0", + "fs-extra": "^11.1.0", "logger": "^0.0.1", "mime": "^2.4.5", "mongodb": "^4.1.1", + "mongoose": "^7.4.3", "multer": "^1.4.4", "mysql": "^2.18.1", "node-os-utils": "^1.3.5", "qr-encode": "^0.3.0", "qrcode-terminal": "^0.12.0", "socket.io": "^4.5.4", - "socket.io-client": "^4.5.4", - "fs-extra": "^11.1.0" + "socket.io-client": "^4.5.4" }, "devDependencies": { "nodemon": "^2.0.20" diff --git a/frontend/src/pages/Campaign/index.js b/frontend/src/pages/Campaign/index.js index f6a4d69..0cae436 100644 --- a/frontend/src/pages/Campaign/index.js +++ b/frontend/src/pages/Campaign/index.js @@ -26,8 +26,7 @@ import MainHeader from '../../components/MainHeader' import MainHeaderButtonsWrapper from '../../components/MainHeaderButtonsWrapper' import Title from '../../components/Title' import TableRowSkeleton from '../../components/TableRowSkeleton' - -import api from '../../services/api' + import CampaignModal from '../../components/CampaignModal' import ConfirmationModal from '../../components/ConfirmationModal' import QrcodeModal from '../../components/QrcodeModal' @@ -175,30 +174,7 @@ const Campaign = () => { }, 500) return () => clearTimeout(delayDebounceFn) }, [user.id]) - - useEffect(() => { - const fetchSession = async () => { - try { - // const test = await apiBroker.get('/contacts/status/insert/onqueue', { - // params: { - // adminId: user.id, - // baseURL: process.env.REACT_APP_BACKEND_URL_PRIVATE, - // identifier: 'campaign', - // }, - // }) - - // console.log('-------------------> test: ', test) - - // const { data } = await api.get('/settings') - // setSettings(data) - - } catch (err) { - toastError(err) - } - } - fetchSession() - }, []) - + const handleOpenCampaignModal = () => { setSelectedCampaign(null) @@ -269,14 +245,7 @@ const Campaign = () => { setConfirmModalOpen(true) } - const handleSubmitConfirmationModal = async () => { - if (confirmModalInfo.action === 'disconnect') { - try { - await api.delete(`/whatsappsession/${confirmModalInfo.campaignId}`) - } catch (err) { - toastError(err) - } - } + const handleSubmitConfirmationModal = async () => { if (confirmModalInfo.action === 'delete') { try { diff --git a/frontend/src/pages/Contacts/index.js b/frontend/src/pages/Contacts/index.js index ab8a653..1fe8066 100644 --- a/frontend/src/pages/Contacts/index.js +++ b/frontend/src/pages/Contacts/index.js @@ -179,10 +179,7 @@ const Contacts = () => { } }) - if (insertOnQueue && insertOnQueue.data) { - - console.log('insertOnQueue: ', insertOnQueue.data) - console.log('data.app.file: ', insertOnQueue.data.app.file) + if (insertOnQueue && insertOnQueue.data) { setZipFile(insertOnQueue.data.app.file) setOnQueueProcessStatus(insertOnQueue.data.app.status) From 22ad48e9beb1da9bae555de63c7946d3dfbf1733 Mon Sep 17 00:00:00 2001 From: adriano Date: Tue, 15 Aug 2023 13:59:25 -0300 Subject: [PATCH 17/19] =?UTF-8?q?Corre=C3=A7=C3=A3o=20de=20propriedade=20n?= =?UTF-8?q?ull?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/src/helpers/TicketConfig.ts | 3 +-- backend/src/services/WbotServices/wbotMessageListener.ts | 8 ++++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/backend/src/helpers/TicketConfig.ts b/backend/src/helpers/TicketConfig.ts index 830646a..00a7f1b 100644 --- a/backend/src/helpers/TicketConfig.ts +++ b/backend/src/helpers/TicketConfig.ts @@ -104,8 +104,7 @@ const isWeekend = async () => { else{ // obj.set = true; // obj.msg = weekend.message; - } - + } return obj; } }; diff --git a/backend/src/services/WbotServices/wbotMessageListener.ts b/backend/src/services/WbotServices/wbotMessageListener.ts index b7b0d7a..3620d14 100644 --- a/backend/src/services/WbotServices/wbotMessageListener.ts +++ b/backend/src/services/WbotServices/wbotMessageListener.ts @@ -632,7 +632,7 @@ const handleMessage = async (msg: any, wbot: any): Promise => { // MESSAGE TO HOLIDAY const holiday: any = await isHoliday(); - if (holiday.set) { + if (holiday && holiday.set) { if (msg.fromMe && holiday.msg == msg.body) { console.log("HOLIDAY MESSAGE IGNORED"); return; @@ -643,9 +643,9 @@ const handleMessage = async (msg: any, wbot: any): Promise => { } // MESSAGES TO SATURDAY OR SUNDAY - const weekend: any = await isWeekend(); + const weekend: any = await isWeekend(); - if (weekend.set) { + if (weekend && weekend.set) { if (msg.fromMe && weekend.msg == msg.body) { console.log("WEEKEND MESSAGE IGNORED"); return; @@ -658,7 +658,7 @@ const handleMessage = async (msg: any, wbot: any): Promise => { // MESSAGE TO BUSINESS TIME const businessTime = await isOutBusinessTime(); - if (businessTime.set) { + if (businessTime && businessTime.set) { if (msg.fromMe && businessTime.msg == msg.body) { console.log("BUSINESS TIME MESSAGE IGNORED"); return; From a1cd7e33721c49f876ac79dc49bd905739aae625 Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 16 Aug 2023 08:39:10 -0300 Subject: [PATCH 18/19] =?UTF-8?q?Adi=C3=A7=C3=A3o=20de=20recurso=20para=20?= =?UTF-8?q?gerenciar=20sess=C3=B5es=20sem=20conex=C3=A3o=20com=20internet?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 68cf144..c86c332 100644 --- a/.gitignore +++ b/.gitignore @@ -26,7 +26,7 @@ WWebJS .wwebjs_auth */wwebjs_auth/* .wwebjs_cache -*/wwebjs_cache/* +*/wwebjs_cache/* # testing /coverage From bfad9fc0b22122881fa24366844d30bfacf705d7 Mon Sep 17 00:00:00 2001 From: adriano Date: Wed, 16 Aug 2023 08:39:48 -0300 Subject: [PATCH 19/19] =?UTF-8?q?Adi=C3=A7=C3=A3o=20de=20funcionalidade=20?= =?UTF-8?q?para=20checar=20internet=20nas=20sessoes=20remotas?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- TEST_SERVER1/whats/.env | 4 +- TEST_SERVER1/whats/app.js | 48 ++++++++++++++++++++-- TEST_SERVER1/whats/helpers/checkIntenet.js | 41 ++++++++++++++++++ 3 files changed, 88 insertions(+), 5 deletions(-) create mode 100644 TEST_SERVER1/whats/helpers/checkIntenet.js diff --git a/TEST_SERVER1/whats/.env b/TEST_SERVER1/whats/.env index 6349035..9141735 100644 --- a/TEST_SERVER1/whats/.env +++ b/TEST_SERVER1/whats/.env @@ -1,5 +1,5 @@ # NUMBER AND NAME THAT WILL BE DISPLAYED ON CONSOLE -MOBILEUID=5521995996701 +MOBILEUID=5517988310949 MOBILENAME=test - S1 # PORT NUMBER FOR THIS API @@ -16,7 +16,7 @@ DB_PASS=strongpassword DB_PORT=3306 # WHATSAPP ID OF THE TABLE Whatsapps FROM THE OMNIHIT DATABASE -WHATSAPP_ID=229 +WHATSAPP_ID=223 # MONGO CONNECTION DB_MONGO_URL=mongodb://localhost:27017 diff --git a/TEST_SERVER1/whats/app.js b/TEST_SERVER1/whats/app.js index 7bdc7de..fc3f9c2 100644 --- a/TEST_SERVER1/whats/app.js +++ b/TEST_SERVER1/whats/app.js @@ -40,6 +40,8 @@ const qrcode = require('qrcode-terminal') const omnihit = require('./funcs/omnihit.js') const { allowedNodeEnvironmentFlags } = require('process') +const checkInternetConnection = require('./helpers/checkIntenet') + const mongo = require('./funcs/mongoConn') const db = mongo.db(process.env.DB_MONGO_NAME) @@ -53,6 +55,7 @@ let scheduler_messages_outbound let scheduler_monitor let scheduler_monitor_cell let scheduler_campaign_monitor +let scheduler_internet_conn let client // const PORT = 80; @@ -64,6 +67,7 @@ const { imageUpload } = require('./helpers/image-uploader') var QRCODE = "0" var mobileuid var destroy +var changeInternetConn = true let asking_qrcode = false @@ -991,7 +995,7 @@ async function monitor() { _nextime = 10000 } - console.log(`WHATSAPP_ID: ${process.env.WHATSAPP_ID} | CLIENT MOBILEUID: ${mobileuid} | NAME: ${process.env.MOBILENAME} | ENV MOBILEUID: ${process.env.MOBILEUID} | STATUS: ${stat}`) + console.log(`WHATSAPP_ID: ${process.env.WHATSAPP_ID} | CLIENT MOBILEUID: ${mobileuid} | NAME: ${process.env.MOBILENAME} | ENV MOBILEUID: ${process.env.MOBILEUID} | STATUS: ${stat} | INTERNET: ${changeInternetConn}`) if (stat && stat === 'CONNECTED') { @@ -1019,7 +1023,24 @@ const sendCampaignMessage = async () => { try { clearInterval(scheduler_campaign_monitor) - if (mobileuid != undefined) { + + let internetConnection = await checkInternetConnection() + + if (!internetConnection) { + changeInternetConn = false + } else { + changeInternetConn = true + } + + // let stat + // try { + // stat = await client.getState() + // } catch (err) { + // stat = (err?.message?.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') + // } + // console.log('===========> stat: ', stat) + + if (mobileuid != undefined && internetConnection) { auxCampaignMessage = '' @@ -1137,6 +1158,25 @@ async function monitorCell() { } +async function internetMonitor() { + try { + clearInterval(scheduler_internet_conn) + + if (!changeInternetConn) { + + console.log('INTERNET IS OFFLINE. THE PM2 WILL RESTORE THE PROCESS') + + process.exit() + } + + } catch (error) { + console.log(`Error on try kill the process from internetMonitor function`) + } finally { + scheduler_internet_conn = setInterval(internetMonitor, 60000) + } +} + + function comercialBuss(until_hour) { const _hour = new Date().getHours() @@ -1153,7 +1193,9 @@ function comercialBuss(until_hour) { scheduler_monitor = setInterval(monitor, 10000) -scheduler_campaign_monitor = setInterval(sendCampaignMessage, 3000) +scheduler_campaign_monitor = setInterval(sendCampaignMessage, 3000) + +scheduler_internet_conn = setInterval(internetMonitor, 60000) app.listen(process.env.PORT || 8003, function () { console.log("\u26A1[server]: Server is running at Port ::: " + process.env.PORT || 8003) diff --git a/TEST_SERVER1/whats/helpers/checkIntenet.js b/TEST_SERVER1/whats/helpers/checkIntenet.js new file mode 100644 index 0000000..090a779 --- /dev/null +++ b/TEST_SERVER1/whats/helpers/checkIntenet.js @@ -0,0 +1,41 @@ +const http = require('http') + +const checkInternetConnection = async () => { + const options = { + hostname: 'www.google.com', + port: 80, + method: 'HEAD' + } + + return new Promise((resolve, reject) => { + const req = http.request(options, (res) => { + if (res.statusCode === 200) { + resolve(true) + } else { + resolve(false) + } + req.abort() + }) + + req.on('error', (err) => { + resolve(false) + }) + + req.end() + }) +}; + +// (async () => { +// try { +// const isConnected = await checkInternetConnection() +// if (isConnected) { +// console.log('Internet connection is available.') +// } else { +// console.log('Internet connection is not available.') +// } +// } catch (error) { +// console.error('Error checking internet connection:', error) +// } +// })() + +module.exports = checkInternetConnection