diff --git a/Dockerfile b/Dockerfile index 97c1db22e..019d1759e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,6 +2,7 @@ FROM node:19-alpine ARG _WORKDIR=/home/node/app ARG PORT=3333 +ENV MONGODB_URL mongodb://mongo:27017/whatsapp_api USER root RUN apk add git @@ -9,9 +10,9 @@ RUN apk add git WORKDIR ${_WORKDIR} ADD . ${_WORKDIR} -RUN yarn install +RUN npm install USER node EXPOSE ${PORT} -CMD yarn start \ No newline at end of file +CMD npm start \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index c44e2507f..4ad4cf4f6 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,6 @@ services: mongodb: container_name: mongodb image: mongo:latest - restart: unless-stopped ports: - 27017:27017 volumes: @@ -15,21 +14,18 @@ services: context: . dockerfile: Dockerfile args: - - PORT=${PORT} + - PORT=3333 depends_on: - mongodb - restart: unless-stopped env_file: .env ports: - - ${PORT}:${PORT} + - 3333:3333 environment: - - TOKEN=${TOKEN} - - PORT=${PORT} - - MONGODB_ENABLED=${MONGODB_ENABLED} + - PORT=3333 + - MONGODB_ENABLED=true - MONGODB_URL=mongodb://mongodb:27017 - - WEBHOOK_ENABLED=${WEBHOOK_ENABLED} - - WEBHOOK_URL=${WEBHOOK_URL} - - WEBHOOK_BASE64=${WEBHOOK_BASE64} + - WEBHOOK_ENABLED=false + - LOG_LEVEL=trace volumes: - ./:/home/node/app - /home/node/app/node_modules/ diff --git a/package.json b/package.json index ce4f2c04b..06d4ecd9d 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "license": "MIT", "dependencies": { "@adiwajshing/keyed-db": "^0.2.4", - "@whiskeysockets/baileys": "6.5.0", + "@whiskeysockets/baileys": "^6.6.0", "axios": "^1.1.3", "dotenv": "^16.0.3", "ejs": "^3.1.7", @@ -46,7 +46,7 @@ "multer": "^1.4.5-lts.1", "pino": "^8.7.0", "qrcode": "^1.5.1", - "sharp": "^0.30.5", + "sharp": "^0.32.6", "uuid": "^9.0.0" }, "devDependencies": { diff --git a/src/api/class/audit.js b/src/api/class/audit.js new file mode 100644 index 000000000..c3d0e429e --- /dev/null +++ b/src/api/class/audit.js @@ -0,0 +1,100 @@ +const useMongoDBAuthState = require('../helper/mongoAuthState'); +const logger = require('pino')() + +function statusHandler(numberStatus) { + switch (numberStatus) { + case 1: + return 'pending' + case 3: + return 'played' + default: + return 'unknown' + } +} + +class AuditMessageType { + constructor(data) { + this.key = data.key; + this.remoteJid = data.key.remoteJid; + this.identificator = data.id; + this.id = data.key.id; + this.messag = data.message; + this.status = statusHandler(data.status); + this.messageTimestamp = data.messageTimestamp; + } +} + +class AuditMessages { + constructor(id) { + this.messages = []; + this.collectionName = 'audit_messages'; + this.id = id; + } + + find(query) { + const collection = mongoClient.db('whatsapp-api').collection(this.collectionName) + return useMongoDBAuthState(collection) + .then(({ find }) => { + return find(query) + }) + } + + findHistory(remoteJid) { + const findes = this.messages.filter(message => message.remoteJid === remoteJid) + if (findes.length > 0) { + return new Promise(resolve => resolve(findes)) + } + + const collection = mongoClient.db('whatsapp-api').collection(this.collectionName) + return useMongoDBAuthState(collection) + .then(({ find }) => { + return find({ remoteJid }) + }) + } + + append(message) { + const messageStruct = new AuditMessageType({ + key: message.key, + message: message.message, + status: message.status, + messageTimestamp: message.messageTimestamp, + id: this.id, + remoteJid: message.key.remoteJid, + }); + + const collection = mongoClient.db('whatsapp-api').collection(this.collectionName) + useMongoDBAuthState(collection) + .then(({ insertData }) => { + insertData(messageStruct) + .then((result) => { + logger.info('Audit message requested save saved', result) + this.messages.push(messageStruct); + }) + }) + } + + update(message) { + const remoteJid = message?.key?.remoteJid + if (remoteJid) { + this.findHistory(remoteJid) + .then(entities => { + const collection = mongoClient.db('whatsapp-api').collection(this.collectionName) + const id = message.key.id; + entities.forEach(entitie => { + if (entitie.id === id) { + useMongoDBAuthState(collection).then(({ updateOne }) => { + updateOne( + { id: entitie.id, remoteJid: entitie.remoteJid }, + { $set: { status: statusHandler(message.update.status), updateAt: new Date() } } + ) + }) + + } + + }) + }) + } + } +} + +exports.AuditMessages = new AuditMessages(); \ No newline at end of file diff --git a/src/api/class/instance.js b/src/api/class/instance.js index 8541d3d84..e887df1d6 100644 --- a/src/api/class/instance.js +++ b/src/api/class/instance.js @@ -17,6 +17,7 @@ const config = require('../../config/config') const downloadMessage = require('../helper/downloadMsg') const logger = require('pino')() const useMongoDBAuthState = require('../helper/mongoAuthState') +const { AuditMessages } = require('./audit') const libPhonenumber = require('libphonenumber-js') class WhatsAppInstance { @@ -309,9 +310,11 @@ class WhatsAppInstance { }) sock?.ev.on('messages.update', async (messages) => { - //console.log('messages.update') - //console.dir(messages); + messages.forEach(element => { + AuditMessages.update(element) + }) }) + sock?.ws.on('CB:call', async (data) => { if (data.content) { if (data.content.find((e) => e.tag === 'offer')) { diff --git a/src/api/controllers/audit.controller.js b/src/api/controllers/audit.controller.js new file mode 100644 index 000000000..8b3333bf3 --- /dev/null +++ b/src/api/controllers/audit.controller.js @@ -0,0 +1,14 @@ +const { AuditMessages } = require("../class/audit") + +exports.find = async (req, res) => { + const query = {} + + if (req.query.id) + query.id = req.query.id + + if (req.query.key) + query.identificator = req.query.key + + const result = await AuditMessages.find(query) + return res.status(200).json({ error: false, data: result }) +} \ No newline at end of file diff --git a/src/api/controllers/message.controller.js b/src/api/controllers/message.controller.js index b11da33f4..2938c248a 100644 --- a/src/api/controllers/message.controller.js +++ b/src/api/controllers/message.controller.js @@ -1,8 +1,12 @@ +const { AuditMessages } = require("../class/audit") + exports.Text = async (req, res) => { const data = await WhatsAppInstances[req.query.key].sendTextMessage( req.body.id, req.body.message ) + + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -13,6 +17,7 @@ exports.Image = async (req, res) => { 'image', req.body?.caption ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -23,6 +28,7 @@ exports.Video = async (req, res) => { 'video', req.body?.caption ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -32,6 +38,7 @@ exports.Audio = async (req, res) => { req.file, 'audio' ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -43,6 +50,7 @@ exports.Document = async (req, res) => { '', req.body.filename ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -54,6 +62,7 @@ exports.Mediaurl = async (req, res) => { req.body.mimetype, // mimeType of mediaFile / Check Common mimetypes in `https://mzl.la/3si3and` req.body.caption ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -63,6 +72,7 @@ exports.Button = async (req, res) => { req.body.id, req.body.btndata ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -71,6 +81,7 @@ exports.Contact = async (req, res) => { req.body.id, req.body.vcard ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -79,6 +90,7 @@ exports.List = async (req, res) => { req.body.id, req.body.msgdata ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -87,6 +99,7 @@ exports.MediaButton = async (req, res) => { req.body.id, req.body.btndata ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } @@ -110,6 +123,7 @@ exports.SetStatus = async (req, res) => { req.body.status, req.body.id ) + AuditMessages.append(data) return res.status(201).json({ error: false, data: data }) } diff --git a/src/api/helper/mongoAuthState.js b/src/api/helper/mongoAuthState.js index 9062ef7a5..c3d8270df 100644 --- a/src/api/helper/mongoAuthState.js +++ b/src/api/helper/mongoAuthState.js @@ -25,12 +25,13 @@ const initAuthCreds = () => { }, //mobile creds deviceId: Buffer.from(randomUUID().replace(/-/g, ''), 'hex').toString('base64url'), - phoneId: randomUUID(), - identityId: randomBytes(20), - registered: false, - backupToken: randomBytes(20), - registration: {}, - pairingCode: undefined, + auditoria-de-mensagens + phoneId: randomUUID(), + identityId: randomBytes(20), + registered: false, + backupToken: randomBytes(20), + registration: {}, + pairingCode: undefined, } } @@ -67,6 +68,17 @@ const BufferJSON = { } module.exports = useMongoDBAuthState = async (collection) => { + const insertData = (data) => { + return collection.insertOne({ + createdAt: new Date(), + ...JSON.parse(JSON.stringify(data, BufferJSON.replacer)) + }) + } + + const updateOne = (filter, update) => { + return collection.updateOne(filter, update) + } + const writeData = (data, id) => { return collection.replaceOne( { _id: id }, @@ -74,6 +86,9 @@ module.exports = useMongoDBAuthState = async (collection) => { { upsert: true } ) } + const find = (query = {}) => { + return collection.find(query).toArray() + } const readData = async (id) => { try { const data = JSON.stringify(await collection.findOne({ _id: id })) @@ -85,7 +100,7 @@ module.exports = useMongoDBAuthState = async (collection) => { const removeData = async (id) => { try { await collection.deleteOne({ _id: id }) - } catch (_a) {} + } catch (_a) { } } const creds = (await readData('creds')) || (0, initAuthCreds)() return { @@ -126,5 +141,8 @@ module.exports = useMongoDBAuthState = async (collection) => { saveCreds: () => { return writeData(creds, 'creds') }, + insertData, + find, + updateOne } } diff --git a/src/api/middlewares/keyCheck.js b/src/api/middlewares/keyCheck.js index c1f8acea0..824547524 100644 --- a/src/api/middlewares/keyCheck.js +++ b/src/api/middlewares/keyCheck.js @@ -1,3 +1,5 @@ +const { AuditMessages } = require("../class/audit") + function keyVerification(req, res, next) { const key = req.query['key']?.toString() if (!key) { @@ -6,6 +8,7 @@ function keyVerification(req, res, next) { .send({ error: true, message: 'no key query was present' }) } const instance = WhatsAppInstances[key] + AuditMessages.id = key if (!instance) { return res .status(403) diff --git a/src/api/middlewares/loginCheck.js b/src/api/middlewares/loginCheck.js index ae40cfe50..90ab1f1aa 100644 --- a/src/api/middlewares/loginCheck.js +++ b/src/api/middlewares/loginCheck.js @@ -6,6 +6,7 @@ function loginVerification(req, res, next) { .send({ error: true, message: 'no key query was present' }) } const instance = WhatsAppInstances[key] + if (!instance.instance?.online) { return res .status(401) diff --git a/src/api/routes/audit.route.js b/src/api/routes/audit.route.js new file mode 100644 index 000000000..ffdb70091 --- /dev/null +++ b/src/api/routes/audit.route.js @@ -0,0 +1,8 @@ +const express = require('express') +const controller = require('../controllers/audit.controller') + +const router = express.Router() + +router.route('/find').get(controller.find) + +module.exports = router \ No newline at end of file diff --git a/src/api/routes/index.js b/src/api/routes/index.js index 3f3acac21..b6fae93ae 100644 --- a/src/api/routes/index.js +++ b/src/api/routes/index.js @@ -4,11 +4,13 @@ const instanceRoutes = require('./instance.route') const messageRoutes = require('./message.route') const miscRoutes = require('./misc.route') const groupRoutes = require('./group.route') +const auditRoutes = require('./audit.route') router.get('/status', (req, res) => res.send('OK')) router.use('/instance', instanceRoutes) router.use('/message', messageRoutes) router.use('/group', groupRoutes) router.use('/misc', miscRoutes) +router.use('/audit', auditRoutes) module.exports = router