'use strict'; const { initIO } = require("./helpers/socket") const backup_session = require('./helpers/backup_session'); const restore = require('./helpers/restore'); 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 { MessageMedia } = require('./node_modules/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 logger = require('logger') 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'); require("./funcs/tools.js")(); let scheduler_messages_outbound; let scheduler_monitor; let scheduler_monitor_cell; let client; // const PORT = 80; let sendSeen = false let unreadMessaesProcess const { imageUpload } = require('./helpers/image-uploader') var QRCODE = "0"; var mobileuid; var destroy; let asking_qrcode = false const dbcc = require('./helpers/mysql_conn.js'); const removeDir = require('./helpers/remove_dir'); // (async()=>{ // backup_session(destroy) // clearTimeout(destroy) // }) // console.log('PASSOU............') // return // Sleep const sleep = (ms) => { return new Promise((resolve) => setTimeout(resolve, ms)); }; const app = express(); app.use(express.static(path.join(__dirname, 'public'))); //app.use(bodyparser.urlencoded({ extended: true })); app.use(bodyparser.json()); const sessionName = process.env.MOBILEUID; // console.log('DIRNAME: ', path.join(__dirname, '.wwebjs_auth', 'session-omnihit_sesssion')) //TEST DEL console.log('process.env.CLIENT_URL: ', process.env.CLIENT_URL) console.log('1'); // Connect to server var io = require('socket.io-client'); // const socket = initIO('http://localhost:8024') 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('process.env.WHATSAPP_ID: ', process.env.WHATSAPP_ID) socketIo.emit('joinWhatsSession', process.env.WHATSAPP_ID); sendSeen = true if (mobileuid) { console.log('Socket conectado com o cliente: ', mobileuid) setTimeout(async () => { console.log('Entro no syncUnreadMessages ON CONNECTED SOCKET') await syncUnreadMessages(client) client.sendPresenceAvailable(); }, 5000) } }); socketIo.on('message_from_server', function () { console.log('message_from_server data: '); }); // socketIo.on('disconnect', function () { // console.log('disconnect'); // }); // 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.on('connect_error', async function (err) { console.log('connection errror', err); sendSeen = false if (mobileuid) { client.sendPresenceUnavailable() } }); // //NOVA OPÇÃO MD 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.on("qr", async qr => { console.log("Session:", sessionName); // Generate and scan this code with your phone QRCODE = qr; qrcode.generate(qr, { small: true }) console.log('QR RECEIVED', qr); // omnihit.qrcode(process.env.MOBILEUID, process.env.MOBILENAME, qr); // omnihit.monitor(process.env.MOBILEUID, process.env.MOBILENAME, "STARTUP"); asking_qrcode = true await new Promise((resolve, reject) => { dbcc.query("UPDATE Whatsapps SET qrcode = ?, status = ?, retries = ? where id = ?", [qr, 'qrcode', 0, process.env.WHATSAPP_ID], function (err, result) { if (err) { console.log("ERROR: " + err); reject(err) } else { resolve(result) } }); }) let url = process.env.CLIENT_URL + '/whatsapp/connection/qrcode' try { 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); } }); client.on("authenticated", async session => { 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('>>>>>>>>>>>>>> ready client.ts MOBILE NUMBER: ', client.info["wid"]["user"]) mobileuid = client.info["wid"]["user"]; console.log(new Date().toISOString() + " >>> Mobile UID ::: " + mobileuid); // logger.info(`Session: ${sessionName} READY`); const whatsapp = await new Promise((resolve, reject) => { dbcc.query("SELECT * from Whatsapps where id = ?", [process.env.WHATSAPP_ID], (err, result) => { if (err) { reject(err) } 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') let read_number = client.info["wid"]["user"] let url = process.env.CLIENT_URL + '/whatsapp/connection/number' try { await client.logout() 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); } return } await new Promise((resolve, reject) => { dbcc.query("UPDATE Whatsapps SET qrcode = ?, status = ?, retries = ?, number = ? where id = ?", ["", 'CONNECTED', 0, client.info["wid"]["user"], process.env.WHATSAPP_ID], function (err, result) { if (err) { console.log("ERROR: " + err); reject(err) } else { resolve(result) } }); }) let url = process.env.CLIENT_URL + '/whatsapp/connection/qrcode' try { 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('SEND SEEN: ', sendSeen) await syncUnreadMessages(client) if (sendSeen) { client.sendPresenceAvailable(); } // if(asking_qrcode){ // // backup_session(destroy, 120000, true) // } backup_session(destroy, 120000, false) asking_qrcode = false console.log('PASSOU............') }); async function read() { let chats = await client.getState(); console.log(chats); } client.on("message_create", async msg => { // if (msg.hasMedia && msg.fromMe) // return await handleMessage(msg); }); client.on("media_uploaded", async msg => { console.log('Entrou no midia upload') let msgContact = null let media = null if (msg.fromMe) { msgContact = await client.getContactById(msg.to); } else { msgContact = await msg.getContact(); } const chat = await msg.getChat(); msgContact.getProfilePicUrl = await msgContact.getProfilePicUrl() let quotedMsg = await msg.getQuotedMessage(); if (msg.hasMedia) { media = await msg.downloadMedia(); } let data = { id: process.env.WHATSAPP_ID, msg: msg, msgContact: msgContact, chat: chat, quotedMsg: quotedMsg ? quotedMsg.id.id : null, media: media } socketIo.emit("media_uploaded", data); }); client.on("message_ack", async (msg, ack) => { let data = { whatsappId: process.env.WHATSAPP_ID, id: msg.id.id, ack: ack } 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('#') 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 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('#') 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 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' }); }); client.on("change_state", async newState => { let omnihit_url = process.env.CLIENT_URL + '/whatsapp/connection/monitor' // logger.info(`Monitor session: ${sessionName}, ${newState}`); console.log('>>>>>>>>>>>>>> change_state wbotMonitor.ts MOBILE NUMBER: ', client.info["wid"]["user"]) let data = { action: 'change_state', whatsappId: process.env.WHATSAPP_ID }; await whatsappMonitor(newState, omnihit_url, data); }); client.on("disconnected", async reason => { let omnihit_url = process.env.CLIENT_URL + '/whatsapp/connection/monitor' console.log('>>>>>>>>>>>>>> change_state wbotMonitor.ts MOBILE NUMBER: ', client.info["wid"]["user"]) let data = { action: 'disconnected', whatsappId: process.env.WHATSAPP_ID, reason: reason }; await removeDir(path.join(__dirname, '.wwebjs_auth', 'session-omnihit_sesssion')) setTimeout(() => { process.exit() }, 3000) await whatsappMonitor('OPENING', omnihit_url, data); }); app.get('/', function (req, res) { return res.send('Express + TypeScript Server'); }); app.post('/start', function (req, res) { client.initialize(); res.send("OK"); }); app.post('/qr', function (req, res) { res.send(QRCODE); }); app.post('/api/getWbotMessage', async (req, res) => { const { number, messageId, limit } = req.body console.log('number: ', number, ' | limit: ', limit) const wbotChat = await client.getChatById(number); const fetchWbotMessagesGradually = async () => { const chatMessages = await wbotChat.fetchMessages({ limit }); const msgFound = chatMessages.find(msg => msg.id.id === messageId); if (!msgFound && limit < 100) { limit += 20; return fetchWbotMessagesGradually(); } return msgFound; }; try { const msgFound = await fetchWbotMessagesGradually(); if (!msgFound) { res.status(404).json({ message: "Cannot found message within 100 last messages" }); return } 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" }); } }) app.post('/api/disconnect', async (req, res) => { try { console.log('Restaring the session.........') await removeDir(path.join(__dirname, '.wwebjs_auth', 'session-omnihit_sesssion')) await client.logout(); setTimeout(() => { process.exit() }, 3000) } catch (error) { console.log('There was an error on try disconnect the whatsapp: ', error) } res.status(200).json({ message: "ok" }); }) app.post('/api/DeleteWhatsAppMessage', async (req, res) => { const { number, messageId, limit } = req.body console.log('number: ', number, ' | messageId: ', messageId, ' | limit: ', limit) try { const messageToDelete = await getWbotMessage(messageId, number, limit) await messageToDelete.delete(true); 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" }); return } }) app.post('/api/GetProfilePicUrl', async (req, res) => { const { number } = req.body console.log('THE NUMBER: ', number) const profilePicUrl = await client.getProfilePicUrl(`${number}@c.us`); res.status(200).json({ message: "ok", data: profilePicUrl }); }) app.post('/api/restore', async (req, res) => { await restore(client) res.status(200).json({ message: "ok" }); }) app.post('/api/sendSeen', async (req, res) => { let stat const { number } = req.body try { stat = await client.getState(); // await syncUnreadMessages(client) const wbotChat = await client.getChatById(number); wbotChat.sendSeen(); // const chatMessages = await wbotChat.fetchMessages({ limit: 100 }); // console.log('=============> wbotChat: ', chatMessages) } catch (err) { let terr = err.message; stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } res.status(200).json({ message: "ok" }); }) app.get('/api/connection/status', async (req, res) => { let stat try { stat = await client.getState(); } catch (err) { let terr = err.message; stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } res.status(200).json({ message: "ok", data: stat }); }) const syncUnreadMessages = async (wbot) => { console.log('ENTROU NO UNREAD MESSAGES +++++++++++++=') const chats = await wbot.getChats(); /* eslint-disable no-restricted-syntax */ /* eslint-disable no-await-in-loop */ for (const chat of chats) { // console.log('chat: ', chat) if (chat.unreadCount > 0) { const unreadMessages = await chat.fetchMessages({ limit: chat.unreadCount }); for (const msg of unreadMessages) { // console.log('--BACKEND MSG: ', msg) if (!sendSeen) { return } await handleMessage(msg, wbot); } console.log(':::::::::::::::::::::::::::::PASSOU') await chat.sendSeen(); } } }; const getWbotMessage = async (messageId, number, limit,) => { const wbotChat = await client.getChatById(number); const fetchWbotMessagesGradually = async () => { const chatMessages = await wbotChat.fetchMessages({ limit }); const msgFound = chatMessages.find(msg => msg.id.id === messageId); if (!msgFound && limit < 100) { limit += 20; return fetchWbotMessagesGradually(); } return msgFound; }; try { const msgFound = await fetchWbotMessagesGradually(); if (!msgFound) { return null } return msgFound } catch (err) { console.log('ERR_FETCH_WAPP_MSG: ', err) } return null } async function whatsappMonitor(newState, omnihit_url, data) { const whatsapp = await whatsappUpdateStatus(newState) if (whatsapp && whatsapp.affectedRows) { console.log('whatsapp status update affectedRows: ', whatsapp.affectedRows) } // console.log(' whatsappwhatsappwhatsappwhatsapp: ', whatsapp) try { 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); } } async function whatsappUpdateStatus(newState) { return await new Promise((resolve, reject) => { dbcc.query("UPDATE Whatsapps SET status = ? where id = ?", [newState, process.env.WHATSAPP_ID], function (err, result) { if (err) { console.log("ERROR: " + err); reject(err); } else { resolve(result); } }); }); } async function handleMessage(msg) { console.log('Entrou no message_create'); let msgContact = null; let media = null; if (msg.fromMe) { msgContact = await client.getContactById(msg.to); } else { console.log('################# RECEIVING MESSAGE FROM: ', msg.from, ' to ', msg.to) msgContact = await msg.getContact(); } const chat = await msg.getChat(); msgContact.getProfilePicUrl = await msgContact.getProfilePicUrl(); let quotedMsg = await msg.getQuotedMessage(); if (msg.hasMedia) { media = await msg.downloadMedia(); } let data = { id: process.env.WHATSAPP_ID, msg: msg, msgContact: msgContact, chat: chat, quotedMsg: quotedMsg ? quotedMsg.id.id : null, media: media }; socketIo.emit("message_create", data); } async function getlabels() { var ret = await client.getContactById('551721379544-1625752306@g.us'); //createGroup('The books', ['551100000000@c.us']); console.log("-- Chats --------------------------------"); console.log(ret); return ret; } function base64_encode(file) { // read binary data var bitmap = fs.readFileSync(file); // convert binary data to base64 encoded string return new Buffer(bitmap).toString('base64'); } function getBase64(url) { return axios .get(url, { responseType: 'arraybuffer' }) .then(response => Buffer.from(response.data, 'binary').toString('base64')) } function downloadMedia(url) { 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`); // ///////////////////////////////////////////////////// 5571992888229 casaes let _validNumber = null console.log('******** mobile: ', mobile) try { _validNumber = (await client.getNumberId(`${mobile}@c.us`)).user; } catch (err) { console.log(`Error number: ${err}`) } console.log('_validNumber: ', _validNumber) //////////////////////////////////////////////////////////////////// cb({ isValid: ret, number: _validNumber }); // cb(ret) } app.post('/api/validate', (req, res) => { console.log('ENTROU') let mobile = req.body['mobile']; console.log(new Date() + " >>> Validating Registration Number ::: " + mobile + " on WhatsApp ..."); validate(mobile, function (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'); }); app.post('/group', function (req, res) { //var ret = client.createGroup("Prueba", ["55@c.us"]); var ret = getlabels() res.send(ret); }); app.post('/stop', function (req, res) { client.destroy(); res.send("OK"); }); app.post('/api/status', function (req, res) { res.send("OK"); }); async function monitor() { let _nextime = 0; try { clearInterval(scheduler_monitor); let stat; if (mobileuid != undefined) { try { stat = await client.getState(); } catch (err) { let terr = err.message; stat = (terr.search('Session closed') > -1 ? 'SESSIONCLOSED' : 'UNKNOWN') } // omnihit.monitor(process.env.MOBILEUID, process.env.MOBILENAME, stat); _nextime = 30000; } else { _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) console.log(`Update status to CONNECTED WHATSAPP_ID: ${process.env.WHATSAPP_ID} => result.affectedRows: ${result.affectedRows}`) } } catch (error) { //new Date(new Date() + 'UTC') // console.log(new Date().toISOString() + " >>> ", error); console.log(new Date(new Date() + 'UTC') + " >>> ", error); } finally { scheduler_monitor = setInterval(monitor, _nextime); } } async function monitorCell() { try { clearInterval(scheduler_monitor_cell); // let _contact_mobile = "5511954803572@c.us"; let _message = new Date(new Date() + 'UTC'); if (client.info && client.info["wid"]["user"]) { 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}`); } finally { scheduler_monitor_cell = setInterval(monitorCell, 1800000); } } function comercialBuss(until_hour) { const _hour = new Date().getHours() console.log(' _hour: ', _hour) // const _minute = new Date().getMinutes() // const _second = new Date().getSeconds() if (_hour >= until_hour) { console.log('Trying send message into comercial buss!') return } } scheduler_monitor = setInterval(monitor, 10000); 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 });