mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 04:02:54 -06:00
fix: fix for container mode also work only with files
This commit is contained in:
parent
a08bbab9dc
commit
5d29c2d881
@ -36,10 +36,10 @@ services:
|
|||||||
- DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
|
- DATABASE_CONNECTION_URI=mongodb://root:root@mongodb:27017/?authSource=admin&readPreference=primary&ssl=false&directConnection=true
|
||||||
- DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
|
- DATABASE_CONNECTION_DB_PREFIX_NAME=evolution
|
||||||
# Choose the data you want to save in the application's database or store
|
# Choose the data you want to save in the application's database or store
|
||||||
- DATABASE_SAVE_DATA_INSTANCE=false
|
- DATABASE_SAVE_DATA_INSTANCE=true
|
||||||
- DATABASE_SAVE_DATA_OLD_MESSAGE=false
|
- DATABASE_SAVE_DATA_OLD_MESSAGE=false
|
||||||
- DATABASE_SAVE_DATA_NEW_MESSAGE=true
|
- DATABASE_SAVE_DATA_NEW_MESSAGE=true
|
||||||
- DATABASE_SAVE_MESSAGE_UPDATE=false
|
- DATABASE_SAVE_MESSAGE_UPDATE=true
|
||||||
- DATABASE_SAVE_DATA_CONTACTS=true
|
- DATABASE_SAVE_DATA_CONTACTS=true
|
||||||
- DATABASE_SAVE_DATA_CHATS=true
|
- DATABASE_SAVE_DATA_CHATS=true
|
||||||
- REDIS_ENABLED=true
|
- REDIS_ENABLED=true
|
||||||
|
@ -51,6 +51,7 @@
|
|||||||
"cross-env": "^7.0.3",
|
"cross-env": "^7.0.3",
|
||||||
"dayjs": "^1.11.7",
|
"dayjs": "^1.11.7",
|
||||||
"eventemitter2": "^6.4.9",
|
"eventemitter2": "^6.4.9",
|
||||||
|
"exiftool-vendored": "^22.0.0",
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
"express-async-errors": "^3.1.1",
|
"express-async-errors": "^3.1.1",
|
||||||
"hbs": "^4.2.0",
|
"hbs": "^4.2.0",
|
||||||
|
@ -1,164 +0,0 @@
|
|||||||
// Built around ShellTear's POC at #2215#issuecomment-1292885678 on @adiwajshing/baileys
|
|
||||||
// Copyright ~ purpshell
|
|
||||||
|
|
||||||
import crypto from 'node:crypto';
|
|
||||||
|
|
||||||
const enc = new TextEncoder();
|
|
||||||
/**
|
|
||||||
* Decrypt PollUpdate messages
|
|
||||||
*/
|
|
||||||
export class PollUpdateDecrypt {
|
|
||||||
/**
|
|
||||||
* Compare the SHA-256 hashes of the poll options from the update to find the original choices
|
|
||||||
* @param options Options from the poll creation message
|
|
||||||
* @param pollOptionHash hash from `this.decrypt()`
|
|
||||||
* @returns the original option, can be empty when none are currently selected
|
|
||||||
*/
|
|
||||||
static async compare(options: string[], pollOptionHashes: string[]): Promise<string[]> {
|
|
||||||
const selectedOptions = [];
|
|
||||||
for (const option of options) {
|
|
||||||
const hash = Buffer.from(
|
|
||||||
await crypto.webcrypto.subtle.digest('SHA-256', new TextEncoder().encode(option)),
|
|
||||||
)
|
|
||||||
.toString('hex')
|
|
||||||
.toUpperCase();
|
|
||||||
for (const pollOptionHash of pollOptionHashes) {
|
|
||||||
if (pollOptionHash === hash) {
|
|
||||||
selectedOptions.push(option);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return selectedOptions;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* decrypt a poll message update
|
|
||||||
* @param encPayload from the update
|
|
||||||
* @param encIv from the update
|
|
||||||
* @param encKey from the original poll
|
|
||||||
* @param pollMsgSender sender jid of the pollCreation message
|
|
||||||
* @param pollMsgId id of the pollCreation message
|
|
||||||
* @param voteMsgSender sender of the pollUpdate message
|
|
||||||
* @returns The option or empty array if something went wrong OR everything was unticked
|
|
||||||
*/
|
|
||||||
static async decrypt(
|
|
||||||
encKey: Uint8Array,
|
|
||||||
encPayload: Uint8Array,
|
|
||||||
encIv: Uint8Array,
|
|
||||||
pollMsgSender: string,
|
|
||||||
pollMsgId: string,
|
|
||||||
voteMsgSender: string,
|
|
||||||
): Promise<string[]> {
|
|
||||||
const stanzaId = enc.encode(pollMsgId);
|
|
||||||
const parentMsgOriginalSender = enc.encode(pollMsgSender);
|
|
||||||
const modificationSender = enc.encode(voteMsgSender);
|
|
||||||
const modificationType = enc.encode('Poll Vote');
|
|
||||||
const pad = new Uint8Array([1]);
|
|
||||||
|
|
||||||
const signMe = new Uint8Array([
|
|
||||||
...stanzaId,
|
|
||||||
...parentMsgOriginalSender,
|
|
||||||
...modificationSender,
|
|
||||||
...modificationType,
|
|
||||||
pad,
|
|
||||||
] as any);
|
|
||||||
|
|
||||||
const createSignKey = async (n: Uint8Array = new Uint8Array(32)) => {
|
|
||||||
return await crypto.webcrypto.subtle.importKey(
|
|
||||||
'raw',
|
|
||||||
n,
|
|
||||||
{ name: 'HMAC', hash: 'SHA-256' },
|
|
||||||
false,
|
|
||||||
['sign'],
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const sign = async (
|
|
||||||
n: crypto.webcrypto.BufferSource,
|
|
||||||
key: crypto.webcrypto.CryptoKey,
|
|
||||||
) => {
|
|
||||||
return await crypto.webcrypto.subtle.sign(
|
|
||||||
{ name: 'HMAC', hash: 'SHA-256' },
|
|
||||||
key,
|
|
||||||
n,
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
let key = await createSignKey();
|
|
||||||
|
|
||||||
const temp = await sign(encKey, key);
|
|
||||||
|
|
||||||
key = await createSignKey(new Uint8Array(temp));
|
|
||||||
|
|
||||||
const decryptionKey = new Uint8Array(await sign(signMe, key));
|
|
||||||
|
|
||||||
const additionalData = enc.encode(`${pollMsgId}\u0000${voteMsgSender}`);
|
|
||||||
|
|
||||||
const decryptedMessage = await this._decryptMessage(
|
|
||||||
encPayload,
|
|
||||||
encIv,
|
|
||||||
additionalData,
|
|
||||||
decryptionKey,
|
|
||||||
);
|
|
||||||
|
|
||||||
const pollOptionHash = this._decodeMessage(decryptedMessage);
|
|
||||||
|
|
||||||
// '0A20' in hex represents unicode " " and "\n" thus declaring the end of one option
|
|
||||||
// we want multiple hashes to make it easier to iterate and understand for your use cases
|
|
||||||
return pollOptionHash.split('0A20') || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Internal method to decrypt the message after gathering all information
|
|
||||||
* @deprecated Use `this.decrypt()` instead, only use this if you know what you are doing
|
|
||||||
* @param encPayload
|
|
||||||
* @param encIv
|
|
||||||
* @param additionalData
|
|
||||||
* @param decryptionKey
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
static async _decryptMessage(
|
|
||||||
encPayload: Uint8Array,
|
|
||||||
encIv: Uint8Array,
|
|
||||||
additionalData: Uint8Array,
|
|
||||||
decryptionKey: Uint8Array,
|
|
||||||
) {
|
|
||||||
const tagSize_multiplier = 16;
|
|
||||||
const encoded = encPayload;
|
|
||||||
const key = await crypto.webcrypto.subtle.importKey(
|
|
||||||
'raw',
|
|
||||||
decryptionKey,
|
|
||||||
'AES-GCM',
|
|
||||||
false,
|
|
||||||
['encrypt', 'decrypt'],
|
|
||||||
);
|
|
||||||
const decrypted = await crypto.webcrypto.subtle.decrypt(
|
|
||||||
{
|
|
||||||
name: 'AES-GCM',
|
|
||||||
iv: encIv,
|
|
||||||
additionalData: additionalData,
|
|
||||||
tagLength: 8 * tagSize_multiplier,
|
|
||||||
},
|
|
||||||
key,
|
|
||||||
encoded,
|
|
||||||
);
|
|
||||||
return new Uint8Array(decrypted).slice(2); // remove 2 bytes (OA20)(space+newline)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decode the message from `this._decryptMessage()`
|
|
||||||
* @param decryptedMessage the message from `this._decrpytMessage()`
|
|
||||||
* @returns
|
|
||||||
*/
|
|
||||||
static _decodeMessage(decryptedMessage: Uint8Array) {
|
|
||||||
const n = [48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70];
|
|
||||||
const outarr: number[] = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < decryptedMessage.length; i++) {
|
|
||||||
const val = decryptedMessage[i];
|
|
||||||
outarr.push(n[val >> 4], n[15 & val]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return String.fromCharCode(...outarr);
|
|
||||||
}
|
|
||||||
}
|
|
@ -224,6 +224,7 @@ export class WAMonitoringService {
|
|||||||
await set(dirent.name);
|
await set(dirent.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
initInstance();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
}
|
}
|
||||||
|
@ -29,12 +29,7 @@ import makeWASocket, {
|
|||||||
WAMessage,
|
WAMessage,
|
||||||
WAMessageUpdate,
|
WAMessageUpdate,
|
||||||
WASocket,
|
WASocket,
|
||||||
WAMessageKey,
|
|
||||||
WAMessageContent,
|
|
||||||
getAggregateVotesInPollMessage,
|
getAggregateVotesInPollMessage,
|
||||||
jidNormalizedUser,
|
|
||||||
getKeyAuthor,
|
|
||||||
decryptPollVote,
|
|
||||||
} from '@evolution/base';
|
} from '@evolution/base';
|
||||||
import {
|
import {
|
||||||
Auth,
|
Auth,
|
||||||
@ -44,10 +39,8 @@ import {
|
|||||||
Database,
|
Database,
|
||||||
QrCode,
|
QrCode,
|
||||||
Redis,
|
Redis,
|
||||||
StoreConf,
|
|
||||||
Webhook,
|
Webhook,
|
||||||
} from '../../config/env.config';
|
} from '../../config/env.config';
|
||||||
import { PollUpdateDecrypt } from '../../utils/poll-update-decrypt-message';
|
|
||||||
import fs from 'fs';
|
import fs from 'fs';
|
||||||
import { Logger } from '../../config/logger.config';
|
import { Logger } from '../../config/logger.config';
|
||||||
import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config';
|
import { INSTANCE_DIR, ROOT_DIR } from '../../config/path.config';
|
||||||
@ -119,7 +112,6 @@ import { WebhookRaw } from '../models/webhook.model';
|
|||||||
import { dbserver } from '../../db/db.connect';
|
import { dbserver } from '../../db/db.connect';
|
||||||
import NodeCache from 'node-cache';
|
import NodeCache from 'node-cache';
|
||||||
import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db';
|
import { useMultiFileAuthStateRedisDb } from '../../utils/use-multi-file-auth-state-redis-db';
|
||||||
import { promisify } from 'util';
|
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
|
|
||||||
export class WAStartupService {
|
export class WAStartupService {
|
||||||
@ -726,49 +718,6 @@ export class WAStartupService {
|
|||||||
received.messageTimestamp = received.messageTimestamp?.toNumber();
|
received.messageTimestamp = received.messageTimestamp?.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
// if (received.message?.pollUpdateMessage) {
|
|
||||||
// const creationMsgKey = received.message.pollUpdateMessage.pollCreationMessageKey;
|
|
||||||
// const pollCreation = (await this.getMessage(
|
|
||||||
// creationMsgKey,
|
|
||||||
// true,
|
|
||||||
// )) as proto.IWebMessageInfo;
|
|
||||||
|
|
||||||
// if (pollCreation) {
|
|
||||||
// const meIdNormalised = jidNormalizedUser(this.instance.wuid);
|
|
||||||
// const pollCreatorJid = getKeyAuthor(creationMsgKey, meIdNormalised);
|
|
||||||
// const voterJid = getKeyAuthor(received.key!, meIdNormalised);
|
|
||||||
// const pollEncKey = pollCreation.message?.messageContextInfo?.messageSecret;
|
|
||||||
// // const voteMsg = decryptPollVote(received.message.pollUpdateMessage.vote, {
|
|
||||||
// // pollEncKey,
|
|
||||||
// // pollCreatorJid,
|
|
||||||
// // pollMsgId: creationMsgKey.id,
|
|
||||||
// // voterJid,
|
|
||||||
// // });
|
|
||||||
// // console.log('voteMsg: ', voteMsg);
|
|
||||||
// // console.log(
|
|
||||||
// // pollEncKey,
|
|
||||||
// // received.message?.pollUpdateMessage.vote.encPayload,
|
|
||||||
// // received.message?.pollUpdateMessage.vote.encIv,
|
|
||||||
// // pollCreatorJid,
|
|
||||||
// // pollCreation.key.id,
|
|
||||||
// // voterJid,
|
|
||||||
// // );
|
|
||||||
// const hash = await PollUpdateDecrypt.decrypt(
|
|
||||||
// pollEncKey, // from PollCreationMessage, HAS to be Uint8Array
|
|
||||||
// received.message?.pollUpdateMessage.vote.encPayload, // from PollUpdateMessage, HAS to be Uint8Array
|
|
||||||
// received.message?.pollUpdateMessage.vote.encIv, // from PollUpdateMessage, HAS to be Uint8Array
|
|
||||||
// pollCreatorJid, // PollCreationMessage sender jid (author)
|
|
||||||
// pollCreation.key.id, // Message ID of the PollCreationMessage (can be gotten via the store & pollCreationMessageKey property on the update)
|
|
||||||
// voterJid, // PollUpdateMessage sender jid (author) \\ from above
|
|
||||||
// );
|
|
||||||
// const opt = pollCreation.message?.pollCreationMessage?.options.map(
|
|
||||||
// (o) => o.optionName,
|
|
||||||
// );
|
|
||||||
// const option = await PollUpdateDecrypt.compare(opt, hash);
|
|
||||||
// console.log('option: ', option);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
const messageRaw: MessageRaw = {
|
const messageRaw: MessageRaw = {
|
||||||
key: received.key,
|
key: received.key,
|
||||||
pushName: received.pushName,
|
pushName: received.pushName,
|
||||||
@ -1218,6 +1167,7 @@ export class WAStartupService {
|
|||||||
imagePath = `${join(process.cwd(), 'temp', 'temp-sticker.png')}`;
|
imagePath = `${join(process.cwd(), 'temp', 'temp-sticker.png')}`;
|
||||||
await sharp(imageBuffer).toFile(imagePath);
|
await sharp(imageBuffer).toFile(imagePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
await sharp(imagePath).webp().toFile(outputPath);
|
await sharp(imagePath).webp().toFile(outputPath);
|
||||||
|
|
||||||
return outputPath;
|
return outputPath;
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 8.4 KiB After Width: | Height: | Size: 8.6 KiB |
BIN
temp/sticker.webp_original
Normal file
BIN
temp/sticker.webp_original
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.4 KiB |
Binary file not shown.
Before Width: | Height: | Size: 6.4 KiB |
Loading…
Reference in New Issue
Block a user