mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 04:02:54 -06:00
fix: Adjustment in the recording of temporary files and periodic cleaning
This commit is contained in:
parent
30cd8a03eb
commit
d359949310
10
Docker/.env
10
Docker/.env
@ -12,11 +12,17 @@ LOG_COLOR=true
|
|||||||
DEL_INSTANCE=5
|
DEL_INSTANCE=5
|
||||||
|
|
||||||
# Temporary data storage
|
# Temporary data storage
|
||||||
STORE_CLEANING_INTERVAL=7200 # seconds ===2h
|
STORE_MESSAGES=true
|
||||||
STORE_MESSAGE=true
|
STORE_MESSAGE_UP=true
|
||||||
STORE_CONTACTS=false
|
STORE_CONTACTS=false
|
||||||
STORE_CHATS=false
|
STORE_CHATS=false
|
||||||
|
|
||||||
|
CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds ===2h
|
||||||
|
CLEAN_STORE_MESSAGES=true
|
||||||
|
CLEAN_STORE_MESSAGE_UP=true
|
||||||
|
CLEAN_STORE_CONTACTS=false
|
||||||
|
CLEAN_STORE_CHATS=false
|
||||||
|
|
||||||
# Permanent data storage
|
# Permanent data storage
|
||||||
DATABASE_ENABLED=false
|
DATABASE_ENABLED=false
|
||||||
DATABASE_CONNECTION_URI='<uri>'
|
DATABASE_CONNECTION_URI='<uri>'
|
||||||
|
10
Dockerfile
10
Dockerfile
@ -21,11 +21,17 @@ ENV LOG_COLOR=true
|
|||||||
|
|
||||||
ENV DEL_INSTANCE=$DEL_INSTANCE
|
ENV DEL_INSTANCE=$DEL_INSTANCE
|
||||||
|
|
||||||
ENV STORE_CLEANING_INTERVAL=$STORE_CLEANING_INTERVAL
|
ENV STORE_MESSAGES=$STORE_MESSAGE
|
||||||
ENV STORE_MESSAGE=$STORE_MESSAGE
|
ENV STORE_MESSAGE_UP=$STORE_MESSAGE_UP
|
||||||
ENV STORE_CONTACTS=$STORE_CONTACTS
|
ENV STORE_CONTACTS=$STORE_CONTACTS
|
||||||
ENV STORE_CHATS=$STORE_CHATS
|
ENV STORE_CHATS=$STORE_CHATS
|
||||||
|
|
||||||
|
ENV CLEAN_STORE_CLEANING_INTERVAL=$CLEAN_STORE_CLEANING_INTERVAL
|
||||||
|
ENV CLEAN_STORE_MESSAGES=$CLEAN_STORE_MESSAGE
|
||||||
|
ENV CLEAN_STORE_MESSAGE_UP=$CLEAN_STORE_MESSAGE_UP
|
||||||
|
ENV CLEAN_STORE_CONTACTS=$CLEAN_STORE_CONTACTS
|
||||||
|
ENV CLEAN_STORE_CHATS=$CLEAN_STORE_CHATS
|
||||||
|
|
||||||
ENV DATABASE_ENABLED=$DATABASE_ENABLED
|
ENV DATABASE_ENABLED=$DATABASE_ENABLED
|
||||||
ENV DATABASE_CONNECTION_URI=$DATABASE_CONNECTION_URI
|
ENV DATABASE_CONNECTION_URI=$DATABASE_CONNECTION_URI
|
||||||
ENV DATABASE_CONNECTION_DB_PREFIX_NAME=$DATABASE_CONNECTION_DB_PREFIX_NAME
|
ENV DATABASE_CONNECTION_DB_PREFIX_NAME=$DATABASE_CONNECTION_DB_PREFIX_NAME
|
||||||
|
@ -12,6 +12,7 @@ services:
|
|||||||
- 8080:8080
|
- 8080:8080
|
||||||
volumes:
|
volumes:
|
||||||
- evolution_instances:/evolution/instances
|
- evolution_instances:/evolution/instances
|
||||||
|
- evolution_store:/evolution/store
|
||||||
depends_on:
|
depends_on:
|
||||||
- mongodb
|
- mongodb
|
||||||
- redis
|
- redis
|
||||||
@ -21,10 +22,15 @@ services:
|
|||||||
# If you don't even want an expiration, enter the value false
|
# If you don't even want an expiration, enter the value false
|
||||||
- DEL_INSTANCE=5 # or false
|
- DEL_INSTANCE=5 # or false
|
||||||
# Temporary data storage
|
# Temporary data storage
|
||||||
- STORE_CLEANING_INTERVAL=7200 # seconds === 2h
|
- STORE_MESSAGES=true
|
||||||
- STORE_MESSAGE=true
|
- STORE_MESSAGE_UP=true
|
||||||
- STORE_CONTACTS=true
|
- STORE_CONTACTS=true
|
||||||
- STORE_CHATS=true
|
- STORE_CHATS=true
|
||||||
|
- CLEAN_STORE_CLEANING_INTERVAL=7200 # seconds === 2h
|
||||||
|
- CLEAN_STORE_MESSAGES=true
|
||||||
|
- CLEAN_STORE_MESSAGE_UP=true
|
||||||
|
- CLEAN_STORE_CONTACTS=true
|
||||||
|
- CLEAN_STORE_CHATS=true
|
||||||
# Permanent data storage
|
# Permanent data storage
|
||||||
- DATABASE_ENABLED=true
|
- DATABASE_ENABLED=true
|
||||||
- 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
|
||||||
@ -131,6 +137,7 @@ services:
|
|||||||
|
|
||||||
volumes:
|
volumes:
|
||||||
evolution_instances:
|
evolution_instances:
|
||||||
|
evolution_store:
|
||||||
evolution_mongodb_data:
|
evolution_mongodb_data:
|
||||||
evolution_mongodb_configdb:
|
evolution_mongodb_configdb:
|
||||||
evolution_redis:
|
evolution_redis:
|
@ -29,8 +29,16 @@ export type SaveData = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export type StoreConf = {
|
export type StoreConf = {
|
||||||
|
MESSAGES: boolean;
|
||||||
|
MESSAGE_UP: boolean;
|
||||||
|
CONTACTS: boolean;
|
||||||
|
CHATS: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CleanStoreConf = {
|
||||||
CLEANING_INTERVAL: number;
|
CLEANING_INTERVAL: number;
|
||||||
MESSAGES: boolean;
|
MESSAGES: boolean;
|
||||||
|
MESSAGE_UP: boolean;
|
||||||
CONTACTS: boolean;
|
CONTACTS: boolean;
|
||||||
CHATS: boolean;
|
CHATS: boolean;
|
||||||
};
|
};
|
||||||
@ -107,6 +115,7 @@ export interface Env {
|
|||||||
CORS: Cors;
|
CORS: Cors;
|
||||||
SSL_CONF: SslConf;
|
SSL_CONF: SslConf;
|
||||||
STORE: StoreConf;
|
STORE: StoreConf;
|
||||||
|
CLEAN_STORE: CleanStoreConf;
|
||||||
DATABASE: Database;
|
DATABASE: Database;
|
||||||
REDIS: Redis;
|
REDIS: Redis;
|
||||||
LOG: Log;
|
LOG: Log;
|
||||||
@ -160,13 +169,20 @@ export class ConfigService {
|
|||||||
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN,
|
FULLCHAIN: process.env?.SSL_CONF_FULLCHAIN,
|
||||||
},
|
},
|
||||||
STORE: {
|
STORE: {
|
||||||
CLEANING_INTERVAL: Number.isInteger(process.env?.STORE_CLEANING_TERMINAL)
|
MESSAGES: process.env?.STORE_MESSAGES === 'true',
|
||||||
? Number.parseInt(process.env.STORE_CLEANING_TERMINAL)
|
MESSAGE_UP: process.env?.STORE_MESSAGE_UP === 'true',
|
||||||
: undefined,
|
|
||||||
MESSAGES: process.env?.STORE_MESSAGE === 'true',
|
|
||||||
CONTACTS: process.env?.STORE_CONTACTS === 'true',
|
CONTACTS: process.env?.STORE_CONTACTS === 'true',
|
||||||
CHATS: process.env?.STORE_CHATS === 'true',
|
CHATS: process.env?.STORE_CHATS === 'true',
|
||||||
},
|
},
|
||||||
|
CLEAN_STORE: {
|
||||||
|
CLEANING_INTERVAL: Number.isInteger(process.env?.CLEAN_STORE_CLEANING_TERMINAL)
|
||||||
|
? Number.parseInt(process.env.CLEAN_STORE_CLEANING_TERMINAL)
|
||||||
|
: undefined,
|
||||||
|
MESSAGES: process.env?.CLEAN_STORE_MESSAGES === 'true',
|
||||||
|
MESSAGE_UP: process.env?.CLEAN_STORE_MESSAGE_UP === 'true',
|
||||||
|
CONTACTS: process.env?.CLEAN_STORE_CONTACTS === 'true',
|
||||||
|
CHATS: process.env?.CLEAN_STORE_CHATS === 'true',
|
||||||
|
},
|
||||||
DATABASE: {
|
DATABASE: {
|
||||||
CONNECTION: {
|
CONNECTION: {
|
||||||
URI: process.env.DATABASE_CONNECTION_URI,
|
URI: process.env.DATABASE_CONNECTION_URI,
|
||||||
|
@ -45,8 +45,15 @@ DEL_INSTANCE: false # or false
|
|||||||
|
|
||||||
# Temporary data storage
|
# Temporary data storage
|
||||||
STORE:
|
STORE:
|
||||||
CLEANING_INTERVAL: 7200 # seconds === 2h
|
MESSAGES: true
|
||||||
MESSAGE: true
|
MESSAGE_UP: true
|
||||||
|
CONTACTS: true
|
||||||
|
CHATS: true
|
||||||
|
|
||||||
|
CLEAN_STORE:
|
||||||
|
CLEANING_INTERVAL: 7200 # 7200 seconds === 2h
|
||||||
|
MESSAGES: true
|
||||||
|
MESSAGE_UP: true
|
||||||
CONTACTS: true
|
CONTACTS: true
|
||||||
CHATS: true
|
CHATS: true
|
||||||
|
|
||||||
|
164
src/utils/poll-update-decrypt-message.ts
Normal file
164
src/utils/poll-update-decrypt-message.ts
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { ConfigService } from '../../config/env.config';
|
import { ConfigService, StoreConf } from '../../config/env.config';
|
||||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||||
import { opendirSync, readFileSync, rmSync } from 'fs';
|
import { opendirSync, readFileSync, rmSync } from 'fs';
|
||||||
import { ChatRaw, IChatModel } from '../models';
|
import { ChatRaw, IChatModel } from '../models';
|
||||||
@ -27,15 +27,21 @@ export class ChatRepository extends Repository {
|
|||||||
return { insertCount: insert.length };
|
return { insertCount: insert.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
data.forEach((chat) => {
|
const store = this.configService.get<StoreConf>('STORE');
|
||||||
this.writeStore<ChatRaw>({
|
|
||||||
path: join(this.storePath, 'chats', chat.owner),
|
|
||||||
fileName: chat.id,
|
|
||||||
data: chat,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return { insertCount: data.length };
|
if (store.CHATS) {
|
||||||
|
data.forEach((chat) => {
|
||||||
|
this.writeStore<ChatRaw>({
|
||||||
|
path: join(this.storePath, 'chats', chat.owner),
|
||||||
|
fileName: chat.id,
|
||||||
|
data: chat,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { insertCount: data.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { insertCount: 0 };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return error;
|
return error;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { opendirSync, readFileSync } from 'fs';
|
import { opendirSync, readFileSync } from 'fs';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { ConfigService } from '../../config/env.config';
|
import { ConfigService, StoreConf } from '../../config/env.config';
|
||||||
import { ContactRaw, IContactModel } from '../models';
|
import { ContactRaw, IContactModel } from '../models';
|
||||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||||
|
|
||||||
@ -27,15 +27,21 @@ export class ContactRepository extends Repository {
|
|||||||
return { insertCount: insert.length };
|
return { insertCount: insert.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
data.forEach((contact) => {
|
const store = this.configService.get<StoreConf>('STORE');
|
||||||
this.writeStore({
|
|
||||||
path: join(this.storePath, 'contacts', contact.owner),
|
|
||||||
fileName: contact.id,
|
|
||||||
data: contact,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return { insertCount: data.length };
|
if (store.CONTACTS) {
|
||||||
|
data.forEach((contact) => {
|
||||||
|
this.writeStore({
|
||||||
|
path: join(this.storePath, 'contacts', contact.owner),
|
||||||
|
fileName: contact.id,
|
||||||
|
data: contact,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return { insertCount: data.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { insertCount: 0 };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return error;
|
return error;
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ConfigService } from '../../config/env.config';
|
import { ConfigService, StoreConf } from '../../config/env.config';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
import { IMessageModel, MessageRaw } from '../models';
|
import { IMessageModel, MessageRaw } from '../models';
|
||||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||||
@ -47,7 +47,9 @@ export class MessageRepository extends Repository {
|
|||||||
return { insertCount: insert.length };
|
return { insertCount: insert.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
if (saveDb) {
|
const store = this.configService.get<StoreConf>('STORE');
|
||||||
|
|
||||||
|
if (store.MESSAGES) {
|
||||||
data.forEach((msg) =>
|
data.forEach((msg) =>
|
||||||
this.writeStore<MessageRaw>({
|
this.writeStore<MessageRaw>({
|
||||||
path: join(this.storePath, 'messages', msg.owner),
|
path: join(this.storePath, 'messages', msg.owner),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ConfigService } from '../../config/env.config';
|
import { ConfigService, StoreConf } from '../../config/env.config';
|
||||||
import { IMessageUpModel, MessageUpdateRaw } from '../models';
|
import { IMessageUpModel, MessageUpdateRaw } from '../models';
|
||||||
import { IInsert, Repository } from '../abstract/abstract.repository';
|
import { IInsert, Repository } from '../abstract/abstract.repository';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
@ -28,13 +28,21 @@ export class MessageUpRepository extends Repository {
|
|||||||
return { insertCount: insert.length };
|
return { insertCount: insert.length };
|
||||||
}
|
}
|
||||||
|
|
||||||
data.forEach((update) => {
|
const store = this.configService.get<StoreConf>('STORE');
|
||||||
this.writeStore<MessageUpdateRaw>({
|
|
||||||
path: join(this.storePath, 'message-up', update.owner),
|
if (store.MESSAGE_UP) {
|
||||||
fileName: update.id,
|
data.forEach((update) => {
|
||||||
data: update,
|
this.writeStore<MessageUpdateRaw>({
|
||||||
|
path: join(this.storePath, 'message-up', update.owner),
|
||||||
|
fileName: update.id,
|
||||||
|
data: update,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
return { insertCount: data.length };
|
||||||
|
}
|
||||||
|
|
||||||
|
return { insertCount: 0 };
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,16 @@ import makeWASocket, {
|
|||||||
WAMessage,
|
WAMessage,
|
||||||
WAMessageUpdate,
|
WAMessageUpdate,
|
||||||
WASocket,
|
WASocket,
|
||||||
|
WAMessageKey,
|
||||||
|
WAMessageContent,
|
||||||
|
getAggregateVotesInPollMessage,
|
||||||
|
jidNormalizedUser,
|
||||||
|
getKeyAuthor,
|
||||||
|
decryptPollVote,
|
||||||
} from '@evolution/base';
|
} from '@evolution/base';
|
||||||
import {
|
import {
|
||||||
Auth,
|
Auth,
|
||||||
|
CleanStoreConf,
|
||||||
ConfigService,
|
ConfigService,
|
||||||
ConfigSessionPhone,
|
ConfigSessionPhone,
|
||||||
Database,
|
Database,
|
||||||
@ -40,6 +47,7 @@ import {
|
|||||||
StoreConf,
|
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';
|
||||||
@ -231,14 +239,14 @@ export class WAStartupService {
|
|||||||
baseURL = this.localWebhook.url;
|
baseURL = this.localWebhook.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.log({
|
// this.logger.log({
|
||||||
local: WAStartupService.name + '.sendDataWebhook-local',
|
// local: WAStartupService.name + '.sendDataWebhook-local',
|
||||||
url: baseURL,
|
// url: baseURL,
|
||||||
event,
|
// event,
|
||||||
instance: this.instance.name,
|
// instance: this.instance.name,
|
||||||
data,
|
// data,
|
||||||
destination: this.localWebhook.url,
|
// destination: this.localWebhook.url,
|
||||||
});
|
// });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.localWebhook.enabled && isURL(this.localWebhook.url)) {
|
if (this.localWebhook.enabled && isURL(this.localWebhook.url)) {
|
||||||
@ -286,14 +294,14 @@ export class WAStartupService {
|
|||||||
localUrl = this.localWebhook.url;
|
localUrl = this.localWebhook.url;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.logger.log({
|
// this.logger.log({
|
||||||
local: WAStartupService.name + '.sendDataWebhook-global',
|
// local: WAStartupService.name + '.sendDataWebhook-global',
|
||||||
url: globalURL,
|
// url: globalURL,
|
||||||
event,
|
// event,
|
||||||
instance: this.instance.name,
|
// instance: this.instance.name,
|
||||||
data,
|
// data,
|
||||||
destination: localUrl,
|
// destination: localUrl,
|
||||||
});
|
// });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (globalWebhook && globalWebhook?.ENABLED && isURL(globalURL)) {
|
if (globalWebhook && globalWebhook?.ENABLED && isURL(globalURL)) {
|
||||||
@ -437,24 +445,24 @@ export class WAStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private cleanStore() {
|
private cleanStore() {
|
||||||
const store = this.configService.get<StoreConf>('STORE');
|
const cleanStore = this.configService.get<CleanStoreConf>('CLEAN_STORE');
|
||||||
const database = this.configService.get<Database>('DATABASE');
|
const database = this.configService.get<Database>('DATABASE');
|
||||||
if (store?.CLEANING_INTERVAL && !database.ENABLED) {
|
if (cleanStore?.CLEANING_INTERVAL && !database.ENABLED) {
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
try {
|
try {
|
||||||
for (const [key, value] of Object.entries(store)) {
|
for (const [key, value] of Object.entries(cleanStore)) {
|
||||||
if (value === true) {
|
if (value === true) {
|
||||||
execSync(
|
execSync(
|
||||||
`rm -rf ${join(
|
`rm -rf ${join(
|
||||||
this.storePath,
|
this.storePath,
|
||||||
key.toLowerCase(),
|
key.toLowerCase().replace('_', '-'),
|
||||||
this.instance.wuid,
|
this.instance.wuid,
|
||||||
)}/*.json`,
|
)}/*.json`,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
}, (store?.CLEANING_INTERVAL ?? 3600) * 1000);
|
}, (cleanStore?.CLEANING_INTERVAL ?? 3600) * 1000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -715,6 +723,49 @@ 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,
|
||||||
@ -732,6 +783,7 @@ export class WAStartupService {
|
|||||||
},
|
},
|
||||||
|
|
||||||
'messages.update': async (args: WAMessageUpdate[], database: Database) => {
|
'messages.update': async (args: WAMessageUpdate[], database: Database) => {
|
||||||
|
console.log('messages.update args: ', args);
|
||||||
const status: Record<number, wa.StatusMessage> = {
|
const status: Record<number, wa.StatusMessage> = {
|
||||||
0: 'ERROR',
|
0: 'ERROR',
|
||||||
1: 'PENDING',
|
1: 'PENDING',
|
||||||
@ -742,6 +794,18 @@ export class WAStartupService {
|
|||||||
};
|
};
|
||||||
for await (const { key, update } of args) {
|
for await (const { key, update } of args) {
|
||||||
if (key.remoteJid !== 'status@broadcast' && !key?.remoteJid?.match(/(:\d+)/)) {
|
if (key.remoteJid !== 'status@broadcast' && !key?.remoteJid?.match(/(:\d+)/)) {
|
||||||
|
if (update.pollUpdates) {
|
||||||
|
const pollCreation = await this.getMessage(key);
|
||||||
|
console.log('pollCreation: ', pollCreation);
|
||||||
|
if (pollCreation) {
|
||||||
|
const pollMessage = getAggregateVotesInPollMessage({
|
||||||
|
message: pollCreation as proto.IMessage,
|
||||||
|
pollUpdates: update.pollUpdates,
|
||||||
|
});
|
||||||
|
console.log('pollMessage: ', pollMessage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const message: MessageUpdateRaw = {
|
const message: MessageUpdateRaw = {
|
||||||
...key,
|
...key,
|
||||||
status: status[update.status],
|
status: status[update.status],
|
||||||
|
Loading…
Reference in New Issue
Block a user