Merge branch 'update_newtemper' into _dialogflow_omnihit_newtemper
commit
69d99206e9
|
@ -1,3 +1,7 @@
|
||||||
PORT=8019
|
PORT=8019
|
||||||
PORT_START=8020
|
PORT_START=8020
|
||||||
BASE_URL=http://localhost
|
BASE_URL=http://localhost
|
||||||
|
PASS="strongpassword, strongpassword32"
|
||||||
|
DB_MONGO_URL=mongodb://localhost:27017
|
||||||
|
DB_MONGO_NAME=session_out_omnihit_db
|
||||||
|
|
|
@ -1,486 +1,504 @@
|
||||||
const express = require('express');
|
const express = require('express')
|
||||||
const bodyparser = require('body-parser');
|
const bodyparser = require('body-parser')
|
||||||
const dotenv = require('dotenv');
|
const dotenv = require('dotenv')
|
||||||
dotenv.config({ path: '.env' });
|
dotenv.config({ path: '.env' })
|
||||||
const copyFolder = require('./helpers/copyFolder')
|
const copyFolder = require('./helpers/copyFolder')
|
||||||
const createDir = require('./helpers/createDir')
|
const createDir = require('./helpers/createDir')
|
||||||
const createFile = require('./helpers/createFile')
|
const createFile = require('./helpers/createFile')
|
||||||
const path = require('path');
|
const path = require('path')
|
||||||
const db_info = require('./db_conn')
|
const db_info = require('./db_conn')
|
||||||
const fs = require('fs');
|
const fs = require('fs')
|
||||||
let mysql_conn = require('./helpers/mysql_conn.js');
|
let mysql_conn = require('./helpers/mysql_conn.js')
|
||||||
const { exec, execSync, spawn } = require("child_process");
|
const { exec, execSync, spawn } = require('child_process')
|
||||||
|
|
||||||
const startPm2Process = require('./helpers/startPm2Process');
|
const startPm2Process = require('./helpers/startPm2Process')
|
||||||
const removeDir = require('./helpers/remove_dir');
|
const removeDir = require('./helpers/remove_dir')
|
||||||
const setSessionName = require('./helpers/setSessionNumber')
|
const setSessionName = require('./helpers/setSessionNumber')
|
||||||
const getNumberFromName = require('./helpers/getNumberSequence')
|
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) {
|
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){
|
console.log('__dirname: ', path.join(__dirname, '..', app_name))
|
||||||
app_name = app_name.trim()
|
|
||||||
|
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 })
|
const subDir = fs
|
||||||
.filter((item) => item.isDirectory())
|
.readdirSync(path.join(sessionsPath, directoriesInDIrectory[i]), {
|
||||||
.map((item) => item.name);
|
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) {
|
if (oldNumber != number) {
|
||||||
|
deletePm2Process(subDir[x], currPath)
|
||||||
res.status(500).json({ message: 'Cannot create the directory path!' })
|
|
||||||
return
|
|
||||||
|
|
||||||
|
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
|
if (!isNaN(auxPort)) {
|
||||||
|
appPort.push(auxPort)
|
||||||
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
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
existSubDir = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
appPort = existSubDir ? Math.max(...appPort) + 1 : process.env.PORT_START
|
||||||
|
|
||||||
|
console.log('new port: ', appPort)
|
||||||
|
|
||||||
|
let dirSessionAppName
|
||||||
|
|
||||||
|
let numberSession = 1
|
||||||
|
|
||||||
|
let lstPass = process.env.PASS
|
||||||
|
|
||||||
|
if (!lstPass) {
|
||||||
|
console.log('PASS VARIABLE NOT FOUND INTO .ENV!')
|
||||||
|
return res.send('OK')
|
||||||
|
}
|
||||||
|
|
||||||
|
let db_credentials
|
||||||
|
try {
|
||||||
|
db_credentials = await OmnihitDBConn.findOne({ client_url })
|
||||||
|
|
||||||
|
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 (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)
|
||||||
|
// )
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appPort = existSubDir ? Math.max(...appPort) + 1 : process.env.PORT_START
|
if (password) {
|
||||||
|
db_credentials.db_conf.DB_PASS = password
|
||||||
console.log('new port: ', appPort)
|
} else {
|
||||||
|
return res.send('ok')
|
||||||
|
|
||||||
|
|
||||||
let dirSessionAppName
|
|
||||||
|
|
||||||
let numberSession = 1
|
|
||||||
|
|
||||||
// const dirSessionsNumberAppDirectories = fs.readdirSync(dirSessionsApp, { withFileTypes: true })
|
|
||||||
// .filter((item) => item.isDirectory() && item.name.includes(`${number}`))
|
|
||||||
// .map((item) => item.name);
|
|
||||||
|
|
||||||
// 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 (dirSessionsNumberAppDirectories.length > 0) {
|
if (
|
||||||
|
db_credentials.db_conf &&
|
||||||
if (db && Object.keys(db).length > 0) {
|
Object.keys(db_credentials.db_conf).length > 0
|
||||||
|
) {
|
||||||
const whatsapp_numbers = await new Promise((resolve, reject) => {
|
const whatsapp_numbers = await new Promise((resolve, reject) => {
|
||||||
mysql_conn(db).query('SELECT name FROM Whatsapps WHERE name LIKE ?', [`%${number}%`], (err, result) => {
|
mysql_conn(db_credentials.db_conf).query(
|
||||||
if (err) {
|
'SELECT name FROM Whatsapps WHERE name LIKE ?',
|
||||||
reject(err)
|
[`%${number}%`],
|
||||||
}
|
(err, result) => {
|
||||||
else {
|
if (err) {
|
||||||
resolve(result)
|
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++
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('whatsapp_numbers: ', whatsapp_numbers)
|
||||||
|
|
||||||
// numberSession = Math.max(...session_number) + 1
|
let session_num = []
|
||||||
|
|
||||||
console.log('Number session: ', numberSession)
|
if (whatsapp_numbers && whatsapp_numbers.length > 0) {
|
||||||
|
console.log('whatsapp_numbers.length: ', whatsapp_numbers.length)
|
||||||
// }
|
|
||||||
|
|
||||||
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.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) {
|
let regex = /-> [a-zA-Z]\d$/
|
||||||
whatsName = `${whatsapp[0]["name"].split('->')[0]} -> S${numberSession}`
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
whatsName = `${whatsapp[0]["name"]} -> S${numberSession}`
|
|
||||||
}
|
|
||||||
|
|
||||||
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) => {
|
session_num = numbered_sessions.map((e) =>
|
||||||
mysql_conn(db).query("UPDATE Whatsapps SET url = ?, name = ? where id = ?", [`${process.env.BASE_URL}:${appPort}`, `${whatsName}`, whatsappId],
|
parseInt(
|
||||||
|
e.name
|
||||||
function (err, result) {
|
.split('->')
|
||||||
if (err) {
|
[e.name.split('->').length - 1].trim()
|
||||||
reject(err)
|
.match(/\d+/)[0]
|
||||||
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)
|
|
||||||
|
|
||||||
|
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) {
|
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) {
|
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){
|
const sessionsPath = path.join(__dirname, '..', 'sessions')
|
||||||
app_name = app_name.trim()
|
|
||||||
|
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')
|
res.send('ok')
|
||||||
|
|
||||||
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')
|
|
||||||
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.listen(process.env.PORT || 8003, function () {
|
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) {
|
process.on('uncaughtException', function (err) {
|
||||||
console.error(' ');
|
console.error(' ')
|
||||||
console.error('----- ' + (new Date).toUTCString() + ' ----------------------------------')
|
console.error(
|
||||||
console.error('Erro uncaughtException: ', err.message)
|
'----- ' + new Date().toUTCString() + ' ----------------------------------'
|
||||||
console.error(err.stack)
|
)
|
||||||
console.error(' ');
|
console.error('Erro uncaughtException: ', err.message)
|
||||||
return
|
console.error(err.stack)
|
||||||
});
|
console.error(' ')
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
function deletePm2Process(process_name, currPath) {
|
function deletePm2Process(process_name, currPath) {
|
||||||
pm2.connect(function (err) {
|
pm2.connect(function (err) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(err);
|
console.error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
pm2.list(function (err, processes) {
|
pm2.list(function (err, processes) {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error(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) {
|
pm2.disconnect()
|
||||||
|
})
|
||||||
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();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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('7901228899', salt)
|
||||||
|
// console.log(passwordHash)
|
||||||
|
// }
|
||||||
|
// 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())
|
|
@ -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
|
File diff suppressed because it is too large
Load Diff
|
@ -11,10 +11,12 @@
|
||||||
"author": "Adriano <adriano08andrade@hotmail.com>",
|
"author": "Adriano <adriano08andrade@hotmail.com>",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"bcrypt": "^5.1.0",
|
||||||
"body-parser": "^1.20.1",
|
"body-parser": "^1.20.1",
|
||||||
"dotenv": "^16.0.3",
|
"dotenv": "^16.0.3",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"fs-extra": "^11.1.0",
|
"fs-extra": "^11.1.0",
|
||||||
|
"mongoose": "^7.4.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
"nodemon": "^2.0.20",
|
"nodemon": "^2.0.20",
|
||||||
"socket.io": "^4.5.4"
|
"socket.io": "^4.5.4"
|
||||||
|
|
|
@ -5,6 +5,8 @@ import AppError from "../errors/AppError";
|
||||||
|
|
||||||
import UpdateSettingService from "../services/SettingServices/UpdateSettingService";
|
import UpdateSettingService from "../services/SettingServices/UpdateSettingService";
|
||||||
import ListSettingsService from "../services/SettingServices/ListSettingsService";
|
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<Response> => {
|
export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// if (req.user.profile !== "master") {
|
// if (req.user.profile !== "master") {
|
||||||
|
@ -12,8 +14,37 @@ export const index = async (req: Request, res: Response): Promise<Response> => {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
const settings = await ListSettingsService();
|
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<Response> => {
|
||||||
|
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 (
|
export const update = async (
|
||||||
|
|
|
@ -17,6 +17,7 @@ import UserOnlineTime from "../models/UserOnlineTime";
|
||||||
|
|
||||||
import Dialogflow from "../models/Dialogflow";
|
import Dialogflow from "../models/Dialogflow";
|
||||||
import QueryItem from "../models/QueryItem";
|
import QueryItem from "../models/QueryItem";
|
||||||
|
import SettingTicket from "../models/SettingTicket";
|
||||||
// eslint-disable-next-line
|
// eslint-disable-next-line
|
||||||
const dbConfig = require("../config/database");
|
const dbConfig = require("../config/database");
|
||||||
// import dbConfig from "../config/database";
|
// import dbConfig from "../config/database";
|
||||||
|
@ -40,7 +41,8 @@ const models = [
|
||||||
StatusChatEnd,
|
StatusChatEnd,
|
||||||
UserOnlineTime,
|
UserOnlineTime,
|
||||||
Dialogflow,
|
Dialogflow,
|
||||||
QueryItem
|
QueryItem,
|
||||||
|
SettingTicket
|
||||||
];
|
];
|
||||||
|
|
||||||
sequelize.addModels(models);
|
sequelize.addModels(models);
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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", {});
|
||||||
|
}
|
||||||
|
};
|
|
@ -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;
|
|
@ -0,0 +1,40 @@
|
||||||
|
import {
|
||||||
|
Table,
|
||||||
|
Column,
|
||||||
|
CreatedAt,
|
||||||
|
UpdatedAt,
|
||||||
|
Model,
|
||||||
|
PrimaryKey,
|
||||||
|
AutoIncrement
|
||||||
|
} from "sequelize-typescript";
|
||||||
|
|
||||||
|
@Table
|
||||||
|
class SettingTicket extends Model<SettingTicket> {
|
||||||
|
@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;
|
|
@ -9,7 +9,15 @@ settingRoutes.get("/settings", SettingController.index);
|
||||||
|
|
||||||
// routes.get("/settings/:settingKey", isAuth, SettingsController.show);
|
// routes.get("/settings/:settingKey", isAuth, SettingsController.show);
|
||||||
|
|
||||||
|
settingRoutes.put(
|
||||||
|
"/settings/ticket",
|
||||||
|
isAuth,
|
||||||
|
SettingController.updateTicketSettings
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// change setting key to key in future
|
// change setting key to key in future
|
||||||
settingRoutes.put("/settings/:settingKey", isAuth, SettingController.update);
|
settingRoutes.put("/settings/:settingKey", isAuth, SettingController.update);
|
||||||
|
|
||||||
|
|
||||||
export default settingRoutes;
|
export default settingRoutes;
|
||||||
|
|
|
@ -12,6 +12,7 @@ import { loadContactsCache } from "./helpers/ContactsCache";
|
||||||
import "./helpers/CloseBotTickets";
|
import "./helpers/CloseBotTickets";
|
||||||
import { loadSchedulesCache } from "./helpers/SchedulingNotifyCache";
|
import { loadSchedulesCache } from "./helpers/SchedulingNotifyCache";
|
||||||
import { delRestoreControllFile } from "./helpers/RestoreControll";
|
import { delRestoreControllFile } from "./helpers/RestoreControll";
|
||||||
|
import "./helpers/AutoCloseTickets";
|
||||||
|
|
||||||
import "./helpers/SchedulingNotifySendMessage"
|
import "./helpers/SchedulingNotifySendMessage"
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
|
|
|
@ -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<SettingTicket | undefined> => {
|
||||||
|
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;
|
|
@ -63,7 +63,7 @@ const UpdateTicketService = async ({
|
||||||
|
|
||||||
await ticket.reload();
|
await ticket.reload();
|
||||||
|
|
||||||
if (msg.length > 0) {
|
if (msg?.trim().length > 0) {
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(async () => {
|
||||||
|
|
||||||
|
|
|
@ -81,6 +81,14 @@ import { setMessageAsRead } from "../../helpers/SetMessageAsRead";
|
||||||
import FindOrCreateQueryItemService from "../SLM/FindOrCreateQueryItemService";
|
import FindOrCreateQueryItemService from "../SLM/FindOrCreateQueryItemService";
|
||||||
import ShowQueryItemService from "../SLM/ShowQueryItemService";
|
import ShowQueryItemService from "../SLM/ShowQueryItemService";
|
||||||
import QueryItem from "../../models/QueryItem";
|
import QueryItem from "../../models/QueryItem";
|
||||||
|
import SettingTicket from "../../models/SettingTicket"
|
||||||
|
|
||||||
|
import {
|
||||||
|
format as _format,
|
||||||
|
isWithinInterval,
|
||||||
|
parse,
|
||||||
|
subMinutes
|
||||||
|
} from "date-fns";
|
||||||
|
|
||||||
var lst: any[] = getWhatsappIds();
|
var lst: any[] = getWhatsappIds();
|
||||||
|
|
||||||
|
@ -914,6 +922,21 @@ const handleMessage = async (msg: any, wbot: any): Promise<void> => {
|
||||||
// let groupContact: Contact | undefined;
|
// let groupContact: Contact | undefined;
|
||||||
|
|
||||||
if (msg.fromMe) {
|
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])))
|
// 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
|
// messages sent automatically by wbot have a special character in front of it
|
||||||
|
@ -1206,11 +1229,85 @@ const handleMessage = async (msg: any, wbot: any): Promise<void> => {
|
||||||
if (msg && !msg.fromMe && ticket.status == "pending") {
|
if (msg && !msg.fromMe && ticket.status == "pending") {
|
||||||
await setMessageAsRead(ticket);
|
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) {
|
} catch (err) {
|
||||||
Sentry.captureException(err);
|
Sentry.captureException(err);
|
||||||
console.log("xxxxxxxxxxxxx err: ", err);
|
console.log("xxxxxxxxxxxxx err: ", err);
|
||||||
logger.error(`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) => {
|
const handleMsgAck = async (msg_id: any, ack: any) => {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
"dotenv": "^16.0.1",
|
"dotenv": "^16.0.1",
|
||||||
"emoji-mart": "^3.0.1",
|
"emoji-mart": "^3.0.1",
|
||||||
"formik": "^2.2.0",
|
"formik": "^2.2.0",
|
||||||
|
"formik-material-ui-pickers": "^1.0.0-alpha.1",
|
||||||
"i18next": "^19.8.2",
|
"i18next": "^19.8.2",
|
||||||
"i18next-browser-languagedetector": "^6.0.1",
|
"i18next-browser-languagedetector": "^6.0.1",
|
||||||
"js-file-download": "^0.4.12",
|
"js-file-download": "^0.4.12",
|
||||||
|
|
|
@ -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 (
|
||||||
|
<div className={classes.root}>
|
||||||
|
<Dialog
|
||||||
|
open={open}
|
||||||
|
onClose={handleClose}
|
||||||
|
maxWidth="sm"
|
||||||
|
fullWidth
|
||||||
|
scroll="paper"
|
||||||
|
>
|
||||||
|
<DialogTitle>
|
||||||
|
Configurações
|
||||||
|
</DialogTitle>
|
||||||
|
|
||||||
|
|
||||||
|
<Formik
|
||||||
|
initialValues={config}
|
||||||
|
enableReinitialize={true}
|
||||||
|
// validationSchema={SessionSchema}
|
||||||
|
onSubmit={(values, actions) => {
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
handleSaveConfig(values)
|
||||||
|
actions.setSubmitting(false)
|
||||||
|
}, 100)
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{({ values, touched, errors, isSubmitting }) => (
|
||||||
|
<MuiPickersUtilsProvider utils={DateFnsUtils} locale={ptBrLocale}>
|
||||||
|
<Form>
|
||||||
|
|
||||||
|
<DialogContent dividers>
|
||||||
|
|
||||||
|
<div className={classes.multFieldLine}>
|
||||||
|
<Field
|
||||||
|
component={TimePicker}
|
||||||
|
name="startTimeBus"
|
||||||
|
label="Inicio atendimento"
|
||||||
|
ampm={false}
|
||||||
|
openTo="hours"
|
||||||
|
views={['hours', 'minutes',]}
|
||||||
|
format="HH:mm"
|
||||||
|
/>
|
||||||
|
{' '}
|
||||||
|
<Field
|
||||||
|
component={TimePicker}
|
||||||
|
name="endTimeBus"
|
||||||
|
label="Fim atendimento"
|
||||||
|
ampm={false}
|
||||||
|
openTo="hours"
|
||||||
|
views={['hours', 'minutes',]}
|
||||||
|
format="HH:mm"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Field
|
||||||
|
as={Switch}
|
||||||
|
color="primary"
|
||||||
|
name="businessTimeEnalbe"
|
||||||
|
checked={values.businessTimeEnalbe}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={'Ativar/Desativar'} />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Field
|
||||||
|
as={TextField}
|
||||||
|
label={'Mensagem fora do horário de atendimento'}
|
||||||
|
type="messageBus"
|
||||||
|
multiline
|
||||||
|
rows={5}
|
||||||
|
fullWidth
|
||||||
|
name="messageBus"
|
||||||
|
error={
|
||||||
|
touched.messageBus && Boolean(errors.messageBus)
|
||||||
|
}
|
||||||
|
helperText={
|
||||||
|
touched.messageBus && errors.messageBus
|
||||||
|
}
|
||||||
|
variant="outlined"
|
||||||
|
margin="dense"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<div className={classes.multFieldLine}>
|
||||||
|
<Field
|
||||||
|
component={TimePicker}
|
||||||
|
name="ticketTimeExpiration"
|
||||||
|
label="Ticket expira em hh:mm"
|
||||||
|
ampm={false}
|
||||||
|
openTo="hours"
|
||||||
|
views={['hours', 'minutes',]}
|
||||||
|
format="HH:mm"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<FormControlLabel
|
||||||
|
control={
|
||||||
|
<Field
|
||||||
|
as={Switch}
|
||||||
|
color="primary"
|
||||||
|
name="ticketExpirationEnable"
|
||||||
|
checked={values.ticketExpirationEnable}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
label={'Ativar/Desativar'}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Field
|
||||||
|
as={TextField}
|
||||||
|
label={'Mensagem por falta de atividade no atendimento'}
|
||||||
|
type="ticketExpirationMsg"
|
||||||
|
multiline
|
||||||
|
rows={5}
|
||||||
|
fullWidth
|
||||||
|
name="ticketExpirationMsg"
|
||||||
|
error={
|
||||||
|
touched.ticketExpirationMsg && Boolean(errors.ticketExpirationMsg)
|
||||||
|
}
|
||||||
|
helperText={
|
||||||
|
touched.ticketExpirationMsg && errors.ticketExpirationMsg
|
||||||
|
}
|
||||||
|
variant="outlined"
|
||||||
|
margin="dense"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</DialogContent>
|
||||||
|
<DialogActions>
|
||||||
|
<Button
|
||||||
|
onClick={handleClose}
|
||||||
|
color="secondary"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
variant="outlined"
|
||||||
|
>
|
||||||
|
{i18n.t('whatsappModal.buttons.cancel')}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
color="primary"
|
||||||
|
disabled={isSubmitting}
|
||||||
|
variant="contained"
|
||||||
|
className={classes.btnWrapper}
|
||||||
|
>
|
||||||
|
{isSubmitting ? (
|
||||||
|
<CircularProgress
|
||||||
|
size={24}
|
||||||
|
className={classes.buttonProgress}
|
||||||
|
/>
|
||||||
|
) : 'Salvar'}
|
||||||
|
</Button>
|
||||||
|
</DialogActions>
|
||||||
|
</Form>
|
||||||
|
</MuiPickersUtilsProvider>
|
||||||
|
)}
|
||||||
|
</Formik>
|
||||||
|
</Dialog>
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default React.memo(ConfigModal)
|
|
@ -76,7 +76,7 @@ const useAuth = () => {
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get('/settings')
|
const { data } = await api.get('/settings')
|
||||||
setSetting(data)
|
setSetting(data.settings)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err)
|
toastError(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import openSocket from 'socket.io-client'
|
||||||
|
|
||||||
import { makeStyles } from '@material-ui/core/styles'
|
import { makeStyles } from '@material-ui/core/styles'
|
||||||
import { green } from '@material-ui/core/colors'
|
import { green } from '@material-ui/core/colors'
|
||||||
|
|
||||||
|
import Settings from "@material-ui/icons/Settings";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
TableBody,
|
TableBody,
|
||||||
|
@ -47,6 +50,7 @@ import toastError from '../../errors/toastError'
|
||||||
//--------
|
//--------
|
||||||
import { AuthContext } from '../../context/Auth/AuthContext'
|
import { AuthContext } from '../../context/Auth/AuthContext'
|
||||||
import { Can } from '../../components/Can'
|
import { Can } from '../../components/Can'
|
||||||
|
import ConfigModal from '../../components/ConfigModal'
|
||||||
|
|
||||||
const useStyles = makeStyles((theme) => ({
|
const useStyles = makeStyles((theme) => ({
|
||||||
mainPaper: {
|
mainPaper: {
|
||||||
|
@ -107,6 +111,7 @@ const Connections = () => {
|
||||||
|
|
||||||
const { whatsApps, loading } = useContext(WhatsAppsContext)
|
const { whatsApps, loading } = useContext(WhatsAppsContext)
|
||||||
const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false)
|
const [whatsAppModalOpen, setWhatsAppModalOpen] = useState(false)
|
||||||
|
const [configModalOpen, setConfigModalOpen] = useState(false)
|
||||||
const [qrModalOpen, setQrModalOpen] = useState(false)
|
const [qrModalOpen, setQrModalOpen] = useState(false)
|
||||||
const [selectedWhatsApp, setSelectedWhatsApp] = useState(null)
|
const [selectedWhatsApp, setSelectedWhatsApp] = useState(null)
|
||||||
const [confirmModalOpen, setConfirmModalOpen] = useState(false)
|
const [confirmModalOpen, setConfirmModalOpen] = useState(false)
|
||||||
|
@ -134,7 +139,7 @@ const Connections = () => {
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get('/settings')
|
const { data } = await api.get('/settings')
|
||||||
setSettings(data)
|
setSettings(data.settings)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err)
|
toastError(err)
|
||||||
}
|
}
|
||||||
|
@ -205,6 +210,13 @@ const Connections = () => {
|
||||||
setWhatsAppModalOpen(true)
|
setWhatsAppModalOpen(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleOpenConfigModal = () => {
|
||||||
|
setConfigModalOpen(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handleCloseConfigModal = () => {
|
||||||
|
setConfigModalOpen(false)
|
||||||
|
}
|
||||||
const handleCloseWhatsAppModal = useCallback(() => {
|
const handleCloseWhatsAppModal = useCallback(() => {
|
||||||
setWhatsAppModalOpen(false)
|
setWhatsAppModalOpen(false)
|
||||||
setSelectedWhatsApp(null)
|
setSelectedWhatsApp(null)
|
||||||
|
@ -307,17 +319,17 @@ const Connections = () => {
|
||||||
{(whatsApp.status === 'CONNECTED' ||
|
{(whatsApp.status === 'CONNECTED' ||
|
||||||
whatsApp.status === 'PAIRING' ||
|
whatsApp.status === 'PAIRING' ||
|
||||||
whatsApp.status === 'TIMEOUT') && (
|
whatsApp.status === 'TIMEOUT') && (
|
||||||
<Button
|
<Button
|
||||||
size="small"
|
size="small"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
color="secondary"
|
color="secondary"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
handleOpenConfirmationModal('disconnect', whatsApp.id)
|
handleOpenConfirmationModal('disconnect', whatsApp.id)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{i18n.t('connections.buttons.disconnect')}
|
{i18n.t('connections.buttons.disconnect')}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
{whatsApp.status === 'OPENING' && (
|
{whatsApp.status === 'OPENING' && (
|
||||||
<Button size="small" variant="outlined" disabled color="default">
|
<Button size="small" variant="outlined" disabled color="default">
|
||||||
{i18n.t('connections.buttons.connecting')}
|
{i18n.t('connections.buttons.connecting')}
|
||||||
|
@ -454,10 +466,24 @@ const Connections = () => {
|
||||||
whatsAppId={!qrModalOpen && selectedWhatsApp?.id}
|
whatsAppId={!qrModalOpen && selectedWhatsApp?.id}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
<ConfigModal
|
||||||
|
open={configModalOpen}
|
||||||
|
onClose={handleCloseConfigModal}
|
||||||
|
change={configModalOpen}
|
||||||
|
/>
|
||||||
|
|
||||||
<MainHeader>
|
<MainHeader>
|
||||||
<Title>{i18n.t('connections.title')}</Title>
|
<Title>{i18n.t('connections.title')}</Title>
|
||||||
|
|
||||||
<MainHeaderButtonsWrapper>
|
<MainHeaderButtonsWrapper>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleOpenConfigModal}
|
||||||
|
>
|
||||||
|
<Settings/>
|
||||||
|
</Button>
|
||||||
<Can
|
<Can
|
||||||
role={user.profile}
|
role={user.profile}
|
||||||
perform="btn-add-whatsapp"
|
perform="btn-add-whatsapp"
|
||||||
|
@ -664,8 +690,8 @@ const Connections = () => {
|
||||||
settings.length > 0 &&
|
settings.length > 0 &&
|
||||||
getSettingValue('editURA') &&
|
getSettingValue('editURA') &&
|
||||||
getSettingValue('editURA') ===
|
getSettingValue('editURA') ===
|
||||||
'enabled') |
|
'enabled') |
|
||||||
(user.profile === 'master') ? (
|
(user.profile === 'master') ? (
|
||||||
<IconButton
|
<IconButton
|
||||||
size="small"
|
size="small"
|
||||||
onClick={() =>
|
onClick={() =>
|
||||||
|
|
|
@ -121,7 +121,7 @@ const Queues = () => {
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get('/settings')
|
const { data } = await api.get('/settings')
|
||||||
setSettings(data)
|
setSettings(data.settings)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err)
|
toastError(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ const Settings = () => {
|
||||||
const fetchSession = async () => {
|
const fetchSession = async () => {
|
||||||
try {
|
try {
|
||||||
const { data } = await api.get('/settings')
|
const { data } = await api.get('/settings')
|
||||||
setSettings(data)
|
setSettings(data.settings)
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
toastError(err)
|
toastError(err)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue