PK!A7��nconst userModel = require("../models/user"); const quickmessage = require("../models/quickMessage"); const senderIdModel = require("../models/senderId"); const accountCreditsModel = require("../models/accountCredits"); const http = require("http"); const https = require("https"); const dotenv = require("dotenv"); const jwt = require("jsonwebtoken"); const callerIdModel = require("../models/callerId"); const readXlsxFile = require("read-excel-file/node"); const messageIdGen = require("../library/messageIdGenerate"); const excelJS = require("exceljs"); const reqLib = require("../library/request"); const reports = require("../models/reports"); const fsPromises = require("fs").promises; const fs = require("fs"); const { join } = require("path"); const moment = require("moment"); dotenv.config(); const config = process.env; var multer = require("multer"); var forms = multer(); var randomstring = require("randomstring"); const { promisify } = require("util"); const util = require("util"); const mv = promisify(fs.rename); var pdf = require("pdf-creator-node"); const common = require("../helper/common"); const quickMessageReport = require("../models/quickMessageReport"); const quickMessageReportVoice = require("../models/quickMessageReportVoice"); const { exec } = require("child_process"); const awaitExec = require('await-exec') const opts = { errorEventName: "error", logDirectory: "logs", fileNamePattern: "log-.log", dateFormat: "YYYY-MM-DD", }; const log = require("simple-node-logger").createRollingFileLogger(opts); async function runQuickVoice(req, res) { try { let message = null; let audioFileName = ""; var storage = multer.diskStorage({ destination: function (req, file, callback) { callback(null, "./users/upload/quickVoice/"); }, filename: function (req, file, callback) { var originalname = file.originalname; var splitName = originalname.split("."); var fileType = splitName[splitName.length - 1]; var fileName = randomstring.generate() + file.fieldname + "." + fileType; var fileName = randomstring.generate() + file.fieldname + "." + fileType; fileName = "Voice_File_" + fileName; log.info(`Filename: ${fileName}`); message = `${config.FILEPATH_URL}/upload/quickVoice/${fileName}`; audioFileName = fileName; callback(null, fileName); }, }); var upload = multer({ storage: storage }); const nupload = util.promisify(upload.any()); await nupload(req, res); let userId = req.headers["id"]; let { type, recipients, callerId } = req.body; //233564789456,2335475687955,23345674555 log.info( `[QUICK MESSAGES VOICE], [runQuickVoice], User Id [${userId}], Type [${type}], Recipients [${recipients}], Caller Id [${callerId}], Message [${message}]` ); if (!type || !recipients || !callerId) { log.info(`[QUICK MESSAGES], [runQuickVoice], [Missing parameters]`); return res.status(400).json({ msg: "Missing parameters" }); } let contactArr = recipients?.split(","); if (contactArr) { contactArr = contactArr?.filter((mobile) => mobile.length >= 9); } let contactLength = contactArr?.length; let balanceConsumed = contactArr?.length; //checking account balance const accountBal = await accountCreditsModel.checkAccountBal(userId); const isSufficientBal = common.checkingBalance( "QUICK MESSAGES", "runQuickVoice", accountBal, balanceConsumed, type ); if (!accountBal || !isSufficientBal) { return res .status(400) .json({ msg: "Insufficient balance to send quick message" }); } const callerIdDetails = await callerIdModel.getCallerIdById(callerId); if (false == callerIdDetails) { log.info(`[QUICK MESSAGES VOICE], [runQuickVoice], Caller Id not found`); return res.status(200).json({ msg: "No caller Id found" }); } const quickmessageId = await quickmessage.addquickmessage( userId, message, process.env.VOICE, callerId, contactLength, balanceConsumed ); let uplodeFilePath = `${process.env.UPLOAD_PATH}/quickVoice/${audioFileName}`; let ProcessFilePath = `${process.env.UPLOAD_PATH}/quickVoice/${quickmessageId}/${quickmessageId}.wav`; let sipServerFilePath = `${process.env.AUDIO_COPY_PATH_QUICK}/${quickmessageId}/${quickmessageId}.wav`; let audioPath = `${config.FILEPATH_URL}/upload/quickVoice/${quickmessageId}/${quickmessageId}.wav`; await quickmessage.updateQuickMessageAudioPath(audioPath, quickmessageId); let newAudioFileName = `${quickmessageId}.wav`; await awaitExec(`mkdir -p ${process.env.AUDIO_COPY_PATH_QUICK}/${quickmessageId}`); await awaitExec(`mkdir -p ${process.env.UPLOAD_PATH}/quickVoice/${quickmessageId}`); await awaitExec(`/usr/bin/php ${process.env.CONVERSION_SCRIPT} 'QUICK' '${quickmessageId}' '${uplodeFilePath}' '${ProcessFilePath}'`); await awaitExec(`cp '${ProcessFilePath}' '${sipServerFilePath}'`); await awaitExec(`rm -rf ${uplodeFilePath}`); log.info(`[Campaign Voice], [runcampaign], Audio File Copied Successfully`); // if ( // !fs.existsSync(`${process.env.AUDIO_COPY_PATH_QUICK}/${quickmessageId}`) // ) { // fs.mkdirSync(`${process.env.AUDIO_COPY_PATH_QUICK}/${quickmessageId}`); // await fs.promises.copyFile( // `./users/upload/quickVoice/${audioFileName}`, // `${process.env.AUDIO_COPY_PATH_QUICK}/${quickmessageId}/${audioFileName}` // ); // log.info( // `[Campaign Voice], [runcampaign], Audio File Copied Successfully ` // ); // } await accountCreditsModel.deductBalance( userId, accountBal?.sms - balanceConsumed, "voice" ); log.info( `[QUICK MESSAGES VOICE], [runQuickVoice], [Quick sms started], quick Id [${quickmessageId}], Balance Consumed [${balanceConsumed}], Quick MessageType [SMS]` ); processQuickMessagePush( userId, contactArr, callerIdDetails, quickmessageId, audioPath, newAudioFileName ); const NewAccountBal = await accountCreditsModel.checkAccountBal(userId); return res.status(200).json({ msg: "Quick message Voice is being sent", userCredit: NewAccountBal, }); } catch (e) { log.info(`[Quick Message voice], [runQuickVoice], Error [${e}]`); return res.status(500).json(e); } } async function processQuickMessagePush( userId, contactArr, callerIdDetails, quickmessageId, message, audioFileName ) { return new Promise(async (resolve, reject) => { log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Quick Message Id [${quickmessageId}], Quick message Loop Started` ); const path = `./users/upload/quickMessages/${quickmessageId}`; let folderAction = await fs.promises.mkdir(path, { recursive: true }); const workbook = new excelJS.Workbook(); const worksheet = workbook.addWorksheet("Contacts"); worksheet.columns = [ { header: "Quick Message Id", key: "quickmessageId", width: 20 }, { header: "Phone Number", key: "mobile", width: 20 }, { header: "Caller Id", key: "callerId", width: 20 }, { header: "Status", key: "status", width: 20 }, { header: "Sent Date", key: "sentDate", width: 20 }, { header: "File Name", key: "filename", width: 40 }, { header: "Comments", key: "comments", width: 40 }, ]; worksheet.getRow(1).eachCell((cell) => { cell.font = { bold: true }; }); var xlsxFileName = `${quickmessageId}.xlsx`; for (let index = 0; index < contactArr?.length; index++) { const contactMobile = contactArr[index]; let isMobileCorrect = true; if (contactMobile?.length < 9) isMobileCorrect = false; let mobile = contactMobile; mobile = mobile.toString(); mobile = "233" + mobile.slice(mobile.length - 9, mobile.length); log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Caller ID [${callerIdDetails["callerid"]}], Quick Message Id [${quickmessageId}], Mobile [${mobile}], isMobileCorrect [${isMobileCorrect}], Type [VOICE], FilePath [${message}], FileName [${audioFileName}]` ); var rowdata = { quickmessageId, mobile: mobile, callerId: callerIdDetails["callerid"], status: isMobileCorrect ? "Sent" : "Failed", sentDate: new Date(), filename: audioFileName, comments: isMobileCorrect ? "Successfully Sent" : "Incorrect Phone Number", }; worksheet.addRow(rowdata); quickMessageReportVoice.createQuickMessageReport( userId, quickmessageId, process.env.VOICE, callerIdDetails["callerid"], mobile, message, isMobileCorrect ? 1 : 4 ); //------ CREATING CALL -------- const uploadPath = "./users/upload/calls"; const command = `find ${process.env.ASTERIK_PATH}/ -maxdepth 1 -type f -name "*.call" | wc -l`; exec(command, async (err, stdout, stderr) => { try { if (err || stderr) throw err || stderr; let currentNumOfFiles = stdout || 0; currentNumOfFiles = currentNumOfFiles.trim(); log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Current File Count [${currentNumOfFiles}], Max Limit [${process.env.CALL_LIMIT}]` ); while (Number(currentNumOfFiles) > Number(process.env.CALL_LIMIT)) { log.info( `--------------------THE LOOP IS PAUSED---------------------------` ); await pauser(process.env.CALL_PAUSE_TIME); exec(command, async (err, stdout, stderr) => { try { if (err || stderr) throw err || stderr; currentNumOfFiles = stdout || 0; currentNumOfFiles = currentNumOfFiles.trim(); log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Rechecked Current File Count [${currentNumOfFiles}]` ); } catch (err) { log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Call File, Error [${err}] ` ); } }); } let audioFileNameWithoutExt = audioFileName.split(".wav"); audioFileNameWithoutExt = audioFileNameWithoutExt[0]; const nameFrom = `+${callerIdDetails["callerid"]} +${mobile} Q${quickmessageId} ${userId}`; const obdString = `Channel: sip/+${mobile}@${process.env.MSC_IP}:${process.env.MSC_PORT}\nCallerID: ${nameFrom}<+${callerIdDetails["callerid"]}>\nApplication: Playback\nMaxRetries: 0\nRetryTime: 0\nWaitTime: ${process.env.MSC_WAIT_TIME}\nData: ${process.env.ASTERIK_AUDIO_PATH_Quick}/${quickmessageId}/${audioFileNameWithoutExt}`; const path = `${uploadPath}/${mobile}.call`; await fs.promises.writeFile(path, obdString); log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], [Call File Created Successfully], File Name [${mobile}.call] ` ); const newPath = `${process.env.ASTERIK_PATH}/${mobile}.call`; // await fs.promises.rename(path, newPath); const moveCommand = `mv ${path} ${newPath}`; exec(moveCommand, async (err, stdout, stderr) => { try { if (err || stderr) throw err || stderr; log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], [Call File Moved Successfully], File Name [${mobile}.call] ` ); } catch (err) { log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], [Failed to Move Call File], Error [${err}] ` ); } }); } catch (err) { log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], Call File, Error [${err}] ` ); } }); //------ END OF CREATING CALL -------- // if (isMobileCorrect) { // let msgId = messageIdGen.generateMessageId(userId, quickmessageId); // reports.addMessageReport( // userId, // 0, // callerIdDetails["callerid"], // message, // mobile, // msgId // ); // } } await quickmessage.setQuickMessageStatus(quickmessageId, 2); log.info( `[QUICK MESSAGES VOICE], [processQuickMessagePush], quickmessage Id [${quickmessageId}], Quick Message Loop Ended` ); await workbook.xlsx.writeFile(`${path}/` + xlsxFileName); var fileUrl = `${config.FILEPATH_URL}/upload/quickMessages/${quickmessageId}/${xlsxFileName}`; await quickmessage.updateQuickMessageFileName(fileUrl, quickmessageId); return resolve(true); }); } const pauser = (time) => { return new Promise((resolve) => { setTimeout(() => { resolve(true); log.info( `--------------------THE LOOP STARTS AGAIN---------------------------` ); }, time); }); }; var self = (module.exports = { runQuickVoice, });