projeto-hit/TEST_SERVER1/whats/app.js

1004 lines
24 KiB
JavaScript

'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
});