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 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 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 bcrypt = require('bcrypt') const OmnihitDBConn = require('./model/db_conn') const app = express() app.use(bodyparser.json()) 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 oldNumber = '' 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 } } let appPort = [] 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]) ) oldNumber = subDir[x].split('_')[1] if (oldNumber != number) { deletePm2Process(subDir[x], currPath) removeDir(currPath) } else { res.send('ok') return } } let auxPort = subDir[x].split('_')[3] console.log('---------> auxPort: ' + auxPort) if (auxPort) { auxPort = +auxPort.trim() if (!isNaN(auxPort)) { appPort.push(auxPort) } } 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 } } 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, number FROM Whatsapps WHERE name LIKE ?', [`%${number}%`], (err, result) => { if (err) { reject(err) } else { resolve(result) } } ) }) 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++ } } // 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(`OLD_MOBILEUID=${oldNumber}\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}\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() }) 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}`) }) 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') }) app.post('/api/session/edit', async function (req, res) { const { app_name, whatsappId, client_url, number } = req.body }) app.post('/api/session/del', async function (req, res) { let { whatsappId, app_name } = req.body 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') } } } res.send('ok') }) app.listen(process.env.PORT || 8003, function () { 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 }) function deletePm2Process(process_name, currPath) { pm2.connect(function (err) { 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}`) } ) } }) pm2.disconnect() }) }) }