mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-16 20:22:54 -06:00
Compare commits
29 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b8fe5603fd | ||
![]() |
762453c0e3 | ||
![]() |
af1b5caa29 | ||
![]() |
50b3379d88 | ||
![]() |
c9ac5984ec | ||
![]() |
29ba63d621 | ||
![]() |
2ce64af502 | ||
![]() |
28c517a3d5 | ||
![]() |
18ebe27bc3 | ||
![]() |
0f7a39a08f | ||
![]() |
a8121d7fe6 | ||
![]() |
b63b7b0b7b | ||
![]() |
14ea5d959f | ||
![]() |
86b2999fcf | ||
![]() |
f5bd11fc19 | ||
![]() |
c060d330de | ||
![]() |
1e320f7904 | ||
![]() |
975b3ee528 | ||
![]() |
5b47bc9ef0 | ||
![]() |
053a7981d1 | ||
![]() |
5f1f025d65 | ||
![]() |
dfb003fd72 | ||
![]() |
5239e431c2 | ||
![]() |
53cc6132f5 | ||
![]() |
0bc1b78db9 | ||
![]() |
2a9412c81a | ||
![]() |
f707cf4109 | ||
![]() |
410cfc8bcb | ||
![]() |
f1a3fd872f |
48
.github/workflows/publish_docker_image_latest.yml
vendored
Normal file
48
.github/workflows/publish_docker_image_latest.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
name: Build Docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_deploy:
|
||||||
|
name: Build and Deploy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: atendai/evolution-api
|
||||||
|
tags: latest
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Image digest
|
||||||
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
48
.github/workflows/publish_docker_image_v2.yml
vendored
Normal file
48
.github/workflows/publish_docker_image_v2.yml
vendored
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
name: Build Docker image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- v2.0.0
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build_deploy:
|
||||||
|
name: Build and Deploy
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v5
|
||||||
|
with:
|
||||||
|
images: atendai/evolution-api
|
||||||
|
tags: v2.0.0-alpha
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
|
||||||
|
- name: Build and push
|
||||||
|
id: docker_build
|
||||||
|
uses: docker/build-push-action@v5
|
||||||
|
with:
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: ${{ steps.meta.outputs.tags }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
||||||
|
- name: Image digest
|
||||||
|
run: echo ${{ steps.docker_build.outputs.digest }}
|
@ -1,3 +1,12 @@
|
|||||||
|
# 1.8.2 (2024-07-03 13:50)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
* Corretion in globall rabbitmq queue name
|
||||||
|
* Improvement in the use of mongodb database for credentials
|
||||||
|
* Fixed base64 in webhook for documentWithCaption
|
||||||
|
* Fixed Generate pairing code
|
||||||
|
|
||||||
# 1.8.1 (2024-06-08 21:32)
|
# 1.8.1 (2024-06-08 21:32)
|
||||||
|
|
||||||
### Feature
|
### Feature
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "evolution-api",
|
"name": "evolution-api",
|
||||||
"version": "1.8.1",
|
"version": "1.8.2",
|
||||||
"description": "Rest api for communication with WhatsApp",
|
"description": "Rest api for communication with WhatsApp",
|
||||||
"main": "./dist/src/main.js",
|
"main": "./dist/src/main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@ -49,7 +49,7 @@
|
|||||||
"amqplib": "^0.10.3",
|
"amqplib": "^0.10.3",
|
||||||
"@aws-sdk/client-sqs": "^3.569.0",
|
"@aws-sdk/client-sqs": "^3.569.0",
|
||||||
"axios": "^1.6.5",
|
"axios": "^1.6.5",
|
||||||
"@whiskeysockets/baileys": "6.7.4",
|
"baileys": "github:EvolutionAPI/Baileys",
|
||||||
"class-validator": "^0.14.1",
|
"class-validator": "^0.14.1",
|
||||||
"compression": "^1.7.4",
|
"compression": "^1.7.4",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { delay } from '@whiskeysockets/baileys';
|
import { delay } from 'baileys';
|
||||||
import { isURL } from 'class-validator';
|
import { isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
import { v4 } from 'uuid';
|
import { v4 } from 'uuid';
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from '@whiskeysockets/baileys';
|
import { proto, WAPresence, WAPrivacyOnlineValue, WAPrivacyValue, WAReadReceiptsValue } from 'baileys';
|
||||||
|
|
||||||
export class OnWhatsAppDto {
|
export class OnWhatsAppDto {
|
||||||
constructor(
|
constructor(
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { WAPresence } from '@whiskeysockets/baileys';
|
import { WAPresence } from 'baileys';
|
||||||
|
|
||||||
import { ProxyDto } from './proxy.dto';
|
import { ProxyDto } from './proxy.dto';
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { proto, WAPresence } from '@whiskeysockets/baileys';
|
import { proto, WAPresence } from 'baileys';
|
||||||
|
|
||||||
export class Quoted {
|
export class Quoted {
|
||||||
key: proto.IMessageKey;
|
key: proto.IMessageKey;
|
||||||
|
@ -8,8 +8,8 @@ import ChatwootClient, {
|
|||||||
inbox,
|
inbox,
|
||||||
} from '@figuro/chatwoot-sdk';
|
} from '@figuro/chatwoot-sdk';
|
||||||
import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request';
|
import { request as chatwootRequest } from '@figuro/chatwoot-sdk/dist/core/request';
|
||||||
import { proto } from '@whiskeysockets/baileys';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { proto } from 'baileys';
|
||||||
import FormData from 'form-data';
|
import FormData from 'form-data';
|
||||||
import { createReadStream, unlinkSync, writeFileSync } from 'fs';
|
import { createReadStream, unlinkSync, writeFileSync } from 'fs';
|
||||||
import Jimp from 'jimp';
|
import Jimp from 'jimp';
|
||||||
@ -444,8 +444,7 @@ export class ChatwootService {
|
|||||||
const searchableFields = this.getSearchableFields();
|
const searchableFields = this.getSearchableFields();
|
||||||
|
|
||||||
// eslint-disable-next-line prettier/prettier
|
// eslint-disable-next-line prettier/prettier
|
||||||
if(contacts.length === 2 && this.getClientCwConfig().merge_brazil_contacts && query.startsWith('+55')){
|
if (contacts.length === 2 && this.getClientCwConfig().merge_brazil_contacts && query.startsWith('+55')) {
|
||||||
|
|
||||||
const contact = this.mergeBrazilianContacts(contacts);
|
const contact = this.mergeBrazilianContacts(contacts);
|
||||||
if (contact) {
|
if (contact) {
|
||||||
return contact;
|
return contact;
|
||||||
@ -736,7 +735,12 @@ export class ChatwootService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.logger.verbose('find inbox by name');
|
this.logger.verbose('find inbox by name');
|
||||||
const findByName = inbox.payload.find((inbox) => inbox.name === this.getClientCwConfig().name_inbox);
|
let findByName = inbox.payload.find((inbox) => inbox.name === this.getClientCwConfig().name_inbox);
|
||||||
|
|
||||||
|
if (!findByName) {
|
||||||
|
findByName = inbox.payload.find((inbox) => inbox.name === this.getClientCwConfig().name_inbox.split('-cwId-')[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
if (!findByName) {
|
if (!findByName) {
|
||||||
this.logger.warn('inbox not found');
|
this.logger.warn('inbox not found');
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { inbox } from '@figuro/chatwoot-sdk';
|
import { inbox } from '@figuro/chatwoot-sdk';
|
||||||
import { proto } from '@whiskeysockets/baileys';
|
import { proto } from 'baileys';
|
||||||
|
|
||||||
import { InstanceDto } from '../../../../api/dto/instance.dto';
|
import { InstanceDto } from '../../../../api/dto/instance.dto';
|
||||||
import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../../api/models';
|
import { ChatwootRaw, ContactRaw, MessageRaw } from '../../../../api/models';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { CacheEngine } from '../cache/cacheengine';
|
import { CacheEngine } from '../cache/cacheengine';
|
||||||
import { configService } from '../config/env.config';
|
import { configService, ProviderSession } from '../config/env.config';
|
||||||
import { eventEmitter } from '../config/event.config';
|
import { eventEmitter } from '../config/event.config';
|
||||||
import { Logger } from '../config/logger.config';
|
import { Logger } from '../config/logger.config';
|
||||||
import { dbserver } from '../libs/db.connect';
|
import { dbserver } from '../libs/db.connect';
|
||||||
@ -110,7 +110,12 @@ export const repository = new RepositoryBroker(
|
|||||||
export const cache = new CacheService(new CacheEngine(configService, 'instance').getEngine());
|
export const cache = new CacheService(new CacheEngine(configService, 'instance').getEngine());
|
||||||
const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine());
|
const chatwootCache = new CacheService(new CacheEngine(configService, ChatwootService.name).getEngine());
|
||||||
const baileysCache = new CacheService(new CacheEngine(configService, 'baileys').getEngine());
|
const baileysCache = new CacheService(new CacheEngine(configService, 'baileys').getEngine());
|
||||||
const providerFiles = new ProviderFiles(configService);
|
|
||||||
|
let providerFiles: ProviderFiles = null;
|
||||||
|
|
||||||
|
if (configService.get<ProviderSession>('PROVIDER')?.ENABLED) {
|
||||||
|
providerFiles = new ProviderFiles(configService);
|
||||||
|
}
|
||||||
|
|
||||||
export const waMonitor = new WAMonitoringService(
|
export const waMonitor = new WAMonitoringService(
|
||||||
eventEmitter,
|
eventEmitter,
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { BufferJSON } from '@whiskeysockets/baileys';
|
import { BufferJSON } from 'baileys';
|
||||||
|
|
||||||
import { Logger } from '../../config/logger.config';
|
import { Logger } from '../../config/logger.config';
|
||||||
import { ICache } from '../abstract/abstract.cache';
|
import { ICache } from '../abstract/abstract.cache';
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { WASocket } from '@whiskeysockets/baileys';
|
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
import { WASocket } from 'baileys';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { isURL } from 'class-validator';
|
import { isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
@ -721,7 +721,9 @@ export class ChannelStartupService {
|
|||||||
autoDelete: false,
|
autoDelete: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const queueName = `${this.instanceName}.${event}`;
|
const eventName = event.replace(/_/g, '.').toLowerCase();
|
||||||
|
|
||||||
|
const queueName = `${this.instanceName}.${eventName}`;
|
||||||
|
|
||||||
await amqp.assertQueue(queueName, {
|
await amqp.assertQueue(queueName, {
|
||||||
durable: true,
|
durable: true,
|
||||||
@ -731,7 +733,7 @@ export class ChannelStartupService {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
await amqp.bindQueue(queueName, exchangeName, event);
|
await amqp.bindQueue(queueName, exchangeName, eventName);
|
||||||
|
|
||||||
const message = {
|
const message = {
|
||||||
event,
|
event,
|
||||||
@ -786,7 +788,7 @@ export class ChannelStartupService {
|
|||||||
autoDelete: false,
|
autoDelete: false,
|
||||||
});
|
});
|
||||||
|
|
||||||
const queueName = transformedWe;
|
const queueName = event;
|
||||||
|
|
||||||
await amqp.assertQueue(queueName, {
|
await amqp.assertQueue(queueName, {
|
||||||
durable: true,
|
durable: true,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
|
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
|
||||||
import { Boom } from '@hapi/boom';
|
import { Boom } from '@hapi/boom';
|
||||||
|
import axios from 'axios';
|
||||||
import makeWASocket, {
|
import makeWASocket, {
|
||||||
AnyMessageContent,
|
AnyMessageContent,
|
||||||
BufferedEventData,
|
BufferedEventData,
|
||||||
@ -19,6 +20,7 @@ import makeWASocket, {
|
|||||||
GroupMetadata,
|
GroupMetadata,
|
||||||
isJidBroadcast,
|
isJidBroadcast,
|
||||||
isJidGroup,
|
isJidGroup,
|
||||||
|
isJidNewsletter,
|
||||||
isJidUser,
|
isJidUser,
|
||||||
makeCacheableSignalKeyStore,
|
makeCacheableSignalKeyStore,
|
||||||
MessageUpsertType,
|
MessageUpsertType,
|
||||||
@ -35,10 +37,9 @@ import makeWASocket, {
|
|||||||
WAMessageUpdate,
|
WAMessageUpdate,
|
||||||
WAPresence,
|
WAPresence,
|
||||||
WASocket,
|
WASocket,
|
||||||
} from '@whiskeysockets/baileys';
|
} from 'baileys';
|
||||||
import { Label } from '@whiskeysockets/baileys/lib/Types/Label';
|
import { Label } from 'baileys/lib/Types/Label';
|
||||||
import { LabelAssociation } from '@whiskeysockets/baileys/lib/Types/LabelAssociation';
|
import { LabelAssociation } from 'baileys/lib/Types/LabelAssociation';
|
||||||
import axios from 'axios';
|
|
||||||
import { exec } from 'child_process';
|
import { exec } from 'child_process';
|
||||||
import { isBase64, isURL } from 'class-validator';
|
import { isBase64, isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
@ -253,8 +254,8 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
this.logger.verbose('Getting profile status');
|
this.logger.verbose('Getting profile status');
|
||||||
const status = await this.client.fetchStatus(this.instance.wuid);
|
const status = await this.client.fetchStatus(this.instance.wuid);
|
||||||
|
|
||||||
this.logger.verbose(`Profile status: ${status.status}`);
|
this.logger.verbose(`Profile status: ${status[0]?.status}`);
|
||||||
return status.status;
|
return status[0]?.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
public get profilePictureUrl() {
|
public get profilePictureUrl() {
|
||||||
@ -517,6 +518,143 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
return await useMultiFileAuthState(join(INSTANCE_DIR, this.instance.name));
|
return await useMultiFileAuthState(join(INSTANCE_DIR, this.instance.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async createClient(number?: string, mobile?: boolean): Promise<WASocket> {
|
||||||
|
this.instance.authState = await this.defineAuthState();
|
||||||
|
|
||||||
|
if (!mobile) {
|
||||||
|
this.mobile = false;
|
||||||
|
} else {
|
||||||
|
this.mobile = mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
const session = this.configService.get<ConfigSessionPhone>('CONFIG_SESSION_PHONE');
|
||||||
|
|
||||||
|
let browserOptions = {};
|
||||||
|
|
||||||
|
if (number || this.phoneNumber) {
|
||||||
|
this.phoneNumber = number;
|
||||||
|
|
||||||
|
this.logger.info(`Phone number: ${number}`);
|
||||||
|
} else {
|
||||||
|
const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()];
|
||||||
|
browserOptions = { browser };
|
||||||
|
|
||||||
|
this.logger.info(`Browser: ${browser}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
let version;
|
||||||
|
let log;
|
||||||
|
|
||||||
|
if (session.VERSION) {
|
||||||
|
version = session.VERSION.split(',');
|
||||||
|
log = `Baileys version env: ${version}`;
|
||||||
|
} else {
|
||||||
|
const baileysVersion = await fetchLatestBaileysVersion();
|
||||||
|
version = baileysVersion.version;
|
||||||
|
log = `Baileys version: ${version}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.logger.info(log);
|
||||||
|
|
||||||
|
let options;
|
||||||
|
|
||||||
|
if (this.localProxy.enabled) {
|
||||||
|
this.logger.info('Proxy enabled: ' + this.localProxy.proxy?.host);
|
||||||
|
|
||||||
|
if (this.localProxy?.proxy?.host?.includes('proxyscrape')) {
|
||||||
|
try {
|
||||||
|
const response = await axios.get(this.localProxy.proxy?.host);
|
||||||
|
const text = response.data;
|
||||||
|
const proxyUrls = text.split('\r\n');
|
||||||
|
const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length));
|
||||||
|
const proxyUrl = 'http://' + proxyUrls[rand];
|
||||||
|
options = {
|
||||||
|
agent: makeProxyAgent(proxyUrl),
|
||||||
|
fetchAgent: makeProxyAgent(proxyUrl),
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
this.localProxy.enabled = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
options = {
|
||||||
|
agent: makeProxyAgent(this.localProxy.proxy),
|
||||||
|
fetchAgent: makeProxyAgent(this.localProxy.proxy),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const socketConfig: UserFacingSocketConfig = {
|
||||||
|
...options,
|
||||||
|
auth: {
|
||||||
|
creds: this.instance.authState.state.creds,
|
||||||
|
keys: makeCacheableSignalKeyStore(this.instance.authState.state.keys, P({ level: 'error' }) as any),
|
||||||
|
},
|
||||||
|
logger: P({ level: this.logBaileys }),
|
||||||
|
printQRInTerminal: false,
|
||||||
|
mobile,
|
||||||
|
...browserOptions,
|
||||||
|
version,
|
||||||
|
markOnlineOnConnect: this.localSettings.always_online,
|
||||||
|
retryRequestDelayMs: 350,
|
||||||
|
maxMsgRetryCount: 4,
|
||||||
|
fireInitQueries: true,
|
||||||
|
connectTimeoutMs: 20_000,
|
||||||
|
keepAliveIntervalMs: 30_000,
|
||||||
|
qrTimeout: 45_000,
|
||||||
|
defaultQueryTimeoutMs: undefined,
|
||||||
|
emitOwnEvents: false,
|
||||||
|
shouldIgnoreJid: (jid) => {
|
||||||
|
const isGroupJid = this.localSettings.groups_ignore && isJidGroup(jid);
|
||||||
|
const isBroadcast = !this.localSettings.read_status && isJidBroadcast(jid);
|
||||||
|
const isNewsletter = isJidNewsletter(jid);
|
||||||
|
|
||||||
|
return isGroupJid || isBroadcast || isNewsletter;
|
||||||
|
},
|
||||||
|
msgRetryCounterCache: this.msgRetryCounterCache,
|
||||||
|
getMessage: async (key) => (await this.getMessage(key)) as Promise<proto.IMessage>,
|
||||||
|
generateHighQualityLinkPreview: true,
|
||||||
|
syncFullHistory: this.localSettings.sync_full_history,
|
||||||
|
shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => {
|
||||||
|
return this.historySyncNotification(msg);
|
||||||
|
},
|
||||||
|
userDevicesCache: this.userDevicesCache,
|
||||||
|
transactionOpts: { maxCommitRetries: 5, delayBetweenTriesMs: 2500 },
|
||||||
|
patchMessageBeforeSending(message) {
|
||||||
|
if (
|
||||||
|
message.deviceSentMessage?.message?.listMessage?.listType === proto.Message.ListMessage.ListType.PRODUCT_LIST
|
||||||
|
) {
|
||||||
|
message = JSON.parse(JSON.stringify(message));
|
||||||
|
|
||||||
|
message.deviceSentMessage.message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.listMessage?.listType == proto.Message.ListMessage.ListType.PRODUCT_LIST) {
|
||||||
|
message = JSON.parse(JSON.stringify(message));
|
||||||
|
|
||||||
|
message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
return message;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
this.endSession = false;
|
||||||
|
|
||||||
|
this.logger.verbose('Creating socket');
|
||||||
|
|
||||||
|
this.client = makeWASocket(socketConfig);
|
||||||
|
|
||||||
|
this.logger.verbose('Socket created');
|
||||||
|
|
||||||
|
this.eventHandler();
|
||||||
|
|
||||||
|
this.logger.verbose('Socket event handler initialized');
|
||||||
|
|
||||||
|
this.phoneNumber = number;
|
||||||
|
|
||||||
|
return this.client;
|
||||||
|
}
|
||||||
|
|
||||||
public async connectToWhatsapp(number?: string, mobile?: boolean): Promise<WASocket> {
|
public async connectToWhatsapp(number?: string, mobile?: boolean): Promise<WASocket> {
|
||||||
this.logger.verbose('Connecting to whatsapp');
|
this.logger.verbose('Connecting to whatsapp');
|
||||||
try {
|
try {
|
||||||
@ -530,126 +668,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
this.loadProxy();
|
this.loadProxy();
|
||||||
this.loadChamaai();
|
this.loadChamaai();
|
||||||
|
|
||||||
this.instance.authState = await this.defineAuthState();
|
return await this.createClient(number, mobile);
|
||||||
|
|
||||||
if (!mobile) {
|
|
||||||
this.mobile = false;
|
|
||||||
} else {
|
|
||||||
this.mobile = mobile;
|
|
||||||
}
|
|
||||||
|
|
||||||
const session = this.configService.get<ConfigSessionPhone>('CONFIG_SESSION_PHONE');
|
|
||||||
const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()];
|
|
||||||
this.logger.verbose('Browser: ' + JSON.stringify(browser));
|
|
||||||
|
|
||||||
let version;
|
|
||||||
let log;
|
|
||||||
|
|
||||||
if (session.VERSION) {
|
|
||||||
version = session.VERSION.split(',');
|
|
||||||
log = `Baileys version env: ${version}`;
|
|
||||||
} else {
|
|
||||||
const baileysVersion = await fetchLatestBaileysVersion();
|
|
||||||
version = baileysVersion.version;
|
|
||||||
log = `Baileys version: ${version}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.info(log);
|
|
||||||
|
|
||||||
let options;
|
|
||||||
|
|
||||||
if (this.localProxy.enabled) {
|
|
||||||
this.logger.info('Proxy enabled: ' + this.localProxy.proxy?.host);
|
|
||||||
|
|
||||||
if (this.localProxy?.proxy?.host?.includes('proxyscrape')) {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(this.localProxy.proxy?.host);
|
|
||||||
const text = response.data;
|
|
||||||
const proxyUrls = text.split('\r\n');
|
|
||||||
const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length));
|
|
||||||
const proxyUrl = 'http://' + proxyUrls[rand];
|
|
||||||
options = {
|
|
||||||
agent: makeProxyAgent(proxyUrl),
|
|
||||||
fetchAgent: makeProxyAgent(proxyUrl),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.localProxy.enabled = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options = {
|
|
||||||
agent: makeProxyAgent(this.localProxy.proxy),
|
|
||||||
fetchAgent: makeProxyAgent(this.localProxy.proxy),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const socketConfig: UserFacingSocketConfig = {
|
|
||||||
...options,
|
|
||||||
auth: {
|
|
||||||
creds: this.instance.authState.state.creds,
|
|
||||||
keys: makeCacheableSignalKeyStore(this.instance.authState.state.keys, P({ level: 'error' }) as any),
|
|
||||||
},
|
|
||||||
logger: P({ level: this.logBaileys }),
|
|
||||||
printQRInTerminal: false,
|
|
||||||
mobile,
|
|
||||||
browser: number ? ['Chrome (Linux)', session.NAME, release()] : browser,
|
|
||||||
version,
|
|
||||||
markOnlineOnConnect: this.localSettings.always_online,
|
|
||||||
retryRequestDelayMs: 10,
|
|
||||||
connectTimeoutMs: 60_000,
|
|
||||||
qrTimeout: 40_000,
|
|
||||||
defaultQueryTimeoutMs: undefined,
|
|
||||||
emitOwnEvents: false,
|
|
||||||
shouldIgnoreJid: (jid) => {
|
|
||||||
const isGroupJid = this.localSettings.groups_ignore && isJidGroup(jid);
|
|
||||||
const isBroadcast = !this.localSettings.read_status && isJidBroadcast(jid);
|
|
||||||
|
|
||||||
return isGroupJid || isBroadcast;
|
|
||||||
},
|
|
||||||
msgRetryCounterCache: this.msgRetryCounterCache,
|
|
||||||
getMessage: async (key) => (await this.getMessage(key)) as Promise<proto.IMessage>,
|
|
||||||
generateHighQualityLinkPreview: true,
|
|
||||||
syncFullHistory: this.localSettings.sync_full_history,
|
|
||||||
shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => {
|
|
||||||
return this.historySyncNotification(msg);
|
|
||||||
},
|
|
||||||
userDevicesCache: this.userDevicesCache,
|
|
||||||
transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 10 },
|
|
||||||
patchMessageBeforeSending(message) {
|
|
||||||
if (
|
|
||||||
message.deviceSentMessage?.message?.listMessage?.listType ===
|
|
||||||
proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
||||||
) {
|
|
||||||
message = JSON.parse(JSON.stringify(message));
|
|
||||||
|
|
||||||
message.deviceSentMessage.message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.listMessage?.listType == proto.Message.ListMessage.ListType.PRODUCT_LIST) {
|
|
||||||
message = JSON.parse(JSON.stringify(message));
|
|
||||||
|
|
||||||
message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.endSession = false;
|
|
||||||
|
|
||||||
this.logger.verbose('Creating socket');
|
|
||||||
|
|
||||||
this.client = makeWASocket(socketConfig);
|
|
||||||
|
|
||||||
this.logger.verbose('Socket created');
|
|
||||||
|
|
||||||
this.eventHandler();
|
|
||||||
|
|
||||||
this.logger.verbose('Socket event handler initialized');
|
|
||||||
|
|
||||||
this.phoneNumber = number;
|
|
||||||
|
|
||||||
return this.client;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
throw new InternalServerErrorException(error?.toString());
|
throw new InternalServerErrorException(error?.toString());
|
||||||
@ -716,106 +735,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
public async reloadConnection(): Promise<WASocket> {
|
public async reloadConnection(): Promise<WASocket> {
|
||||||
try {
|
try {
|
||||||
this.instance.authState = await this.defineAuthState();
|
return await this.createClient(this.phoneNumber, this.mobile);
|
||||||
|
|
||||||
const session = this.configService.get<ConfigSessionPhone>('CONFIG_SESSION_PHONE');
|
|
||||||
const browser: WABrowserDescription = [session.CLIENT, session.NAME, release()];
|
|
||||||
|
|
||||||
let version;
|
|
||||||
let log;
|
|
||||||
|
|
||||||
if (session.VERSION) {
|
|
||||||
version = session.VERSION.split(',');
|
|
||||||
log = `Baileys version env: ${version}`;
|
|
||||||
} else {
|
|
||||||
const baileysVersion = await fetchLatestBaileysVersion();
|
|
||||||
version = baileysVersion.version;
|
|
||||||
log = `Baileys version: ${version}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.logger.info(log);
|
|
||||||
|
|
||||||
let options;
|
|
||||||
|
|
||||||
if (this.localProxy.enabled) {
|
|
||||||
this.logger.info('Proxy enabled: ' + this.localProxy.proxy?.host);
|
|
||||||
|
|
||||||
if (this.localProxy?.proxy?.host?.includes('proxyscrape')) {
|
|
||||||
try {
|
|
||||||
const response = await axios.get(this.localProxy.proxy?.host);
|
|
||||||
const text = response.data;
|
|
||||||
const proxyUrls = text.split('\r\n');
|
|
||||||
const rand = Math.floor(Math.random() * Math.floor(proxyUrls.length));
|
|
||||||
const proxyUrl = 'http://' + proxyUrls[rand];
|
|
||||||
options = {
|
|
||||||
agent: makeProxyAgent(proxyUrl),
|
|
||||||
fetchAgent: makeProxyAgent(proxyUrl),
|
|
||||||
};
|
|
||||||
} catch (error) {
|
|
||||||
this.localProxy.enabled = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
options = {
|
|
||||||
agent: makeProxyAgent(this.localProxy.proxy),
|
|
||||||
fetchAgent: makeProxyAgent(this.localProxy.proxy),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const socketConfig: UserFacingSocketConfig = {
|
|
||||||
...options,
|
|
||||||
auth: {
|
|
||||||
creds: this.instance.authState.state.creds,
|
|
||||||
keys: makeCacheableSignalKeyStore(this.instance.authState.state.keys, P({ level: 'error' }) as any),
|
|
||||||
},
|
|
||||||
logger: P({ level: this.logBaileys }),
|
|
||||||
printQRInTerminal: false,
|
|
||||||
browser: this.phoneNumber ? ['Chrome (Linux)', session.NAME, release()] : browser,
|
|
||||||
version,
|
|
||||||
markOnlineOnConnect: this.localSettings.always_online,
|
|
||||||
retryRequestDelayMs: 10,
|
|
||||||
connectTimeoutMs: 60_000,
|
|
||||||
qrTimeout: 40_000,
|
|
||||||
defaultQueryTimeoutMs: undefined,
|
|
||||||
emitOwnEvents: false,
|
|
||||||
shouldIgnoreJid: (jid) => {
|
|
||||||
const isGroupJid = this.localSettings.groups_ignore && isJidGroup(jid);
|
|
||||||
const isBroadcast = !this.localSettings.read_status && isJidBroadcast(jid);
|
|
||||||
|
|
||||||
return isGroupJid || isBroadcast;
|
|
||||||
},
|
|
||||||
msgRetryCounterCache: this.msgRetryCounterCache,
|
|
||||||
getMessage: async (key) => (await this.getMessage(key)) as Promise<proto.IMessage>,
|
|
||||||
generateHighQualityLinkPreview: true,
|
|
||||||
syncFullHistory: this.localSettings.sync_full_history,
|
|
||||||
shouldSyncHistoryMessage: (msg: proto.Message.IHistorySyncNotification) => {
|
|
||||||
return this.historySyncNotification(msg);
|
|
||||||
},
|
|
||||||
userDevicesCache: this.userDevicesCache,
|
|
||||||
transactionOpts: { maxCommitRetries: 10, delayBetweenTriesMs: 10 },
|
|
||||||
patchMessageBeforeSending(message) {
|
|
||||||
if (
|
|
||||||
message.deviceSentMessage?.message?.listMessage?.listType ===
|
|
||||||
proto.Message.ListMessage.ListType.PRODUCT_LIST
|
|
||||||
) {
|
|
||||||
message = JSON.parse(JSON.stringify(message));
|
|
||||||
|
|
||||||
message.deviceSentMessage.message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (message.listMessage?.listType == proto.Message.ListMessage.ListType.PRODUCT_LIST) {
|
|
||||||
message = JSON.parse(JSON.stringify(message));
|
|
||||||
|
|
||||||
message.listMessage.listType = proto.Message.ListMessage.ListType.SINGLE_SELECT;
|
|
||||||
}
|
|
||||||
|
|
||||||
return message;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
this.client = makeWASocket(socketConfig);
|
|
||||||
|
|
||||||
return this.client;
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.error(error);
|
this.logger.error(error);
|
||||||
throw new InternalServerErrorException(error?.toString());
|
throw new InternalServerErrorException(error?.toString());
|
||||||
@ -1053,7 +973,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
m.messageTimestamp = m.messageTimestamp?.toNumber();
|
m.messageTimestamp = m.messageTimestamp?.toNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m.messageTimestamp <= timestampLimitToImport) {
|
if ((m.messageTimestamp as number) <= timestampLimitToImport) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1178,6 +1098,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
received?.message?.videoMessage ||
|
received?.message?.videoMessage ||
|
||||||
received?.message?.stickerMessage ||
|
received?.message?.stickerMessage ||
|
||||||
received?.message?.documentMessage ||
|
received?.message?.documentMessage ||
|
||||||
|
received?.message?.documentWithCaptionMessage ||
|
||||||
received?.message?.audioMessage;
|
received?.message?.audioMessage;
|
||||||
|
|
||||||
const contentMsg = received?.message[getContentType(received.message)] as any;
|
const contentMsg = received?.message[getContentType(received.message)] as any;
|
||||||
@ -1729,7 +1650,7 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
this.logger.verbose('Getting status');
|
this.logger.verbose('Getting status');
|
||||||
return {
|
return {
|
||||||
wuid: jid,
|
wuid: jid,
|
||||||
status: (await this.client.fetchStatus(jid))?.status,
|
status: (await this.client.fetchStatus(jid))[0]?.status,
|
||||||
};
|
};
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.logger.verbose('Status not found');
|
this.logger.verbose('Status not found');
|
||||||
@ -1939,11 +1860,9 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
} as unknown as AnyMessageContent,
|
} as unknown as AnyMessageContent,
|
||||||
{
|
{
|
||||||
...option,
|
...option,
|
||||||
cachedGroupMetadata:
|
useCachedGroupMetadata:
|
||||||
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
||||||
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
|
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
|
||||||
? null
|
|
||||||
: this.getGroupMetadataCache,
|
|
||||||
} as unknown as MiscMessageGenerationOptions,
|
} as unknown as MiscMessageGenerationOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1959,11 +1878,9 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
} as unknown as AnyMessageContent,
|
} as unknown as AnyMessageContent,
|
||||||
{
|
{
|
||||||
...option,
|
...option,
|
||||||
cachedGroupMetadata:
|
useCachedGroupMetadata:
|
||||||
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
||||||
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
|
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
|
||||||
? null
|
|
||||||
: this.getGroupMetadataCache,
|
|
||||||
} as unknown as MiscMessageGenerationOptions,
|
} as unknown as MiscMessageGenerationOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -1981,11 +1898,9 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
...option,
|
...option,
|
||||||
cachedGroupMetadata:
|
useCachedGroupMetadata:
|
||||||
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
||||||
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
|
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
|
||||||
? null
|
|
||||||
: this.getGroupMetadataCache,
|
|
||||||
} as unknown as MiscMessageGenerationOptions,
|
} as unknown as MiscMessageGenerationOptions,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -2009,11 +1924,9 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
message as unknown as AnyMessageContent,
|
message as unknown as AnyMessageContent,
|
||||||
{
|
{
|
||||||
...option,
|
...option,
|
||||||
cachedGroupMetadata:
|
useCachedGroupMetadata:
|
||||||
!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
!!this.configService.get<CacheConf>('CACHE').REDIS.ENABLED &&
|
||||||
!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED
|
!!this.configService.get<CacheConf>('CACHE').LOCAL.ENABLED,
|
||||||
? null
|
|
||||||
: this.getGroupMetadataCache,
|
|
||||||
} as unknown as MiscMessageGenerationOptions,
|
} as unknown as MiscMessageGenerationOptions,
|
||||||
);
|
);
|
||||||
})();
|
})();
|
||||||
@ -3347,6 +3260,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async findGroup(id: GroupJid, reply: 'inner' | 'out' = 'out') {
|
public async findGroup(id: GroupJid, reply: 'inner' | 'out' = 'out') {
|
||||||
|
if (this.localSettings.groups_ignore === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.logger.verbose('Fetching group');
|
this.logger.verbose('Fetching group');
|
||||||
try {
|
try {
|
||||||
const group = await this.client.groupMetadata(id.groupJid);
|
const group = await this.client.groupMetadata(id.groupJid);
|
||||||
@ -3377,6 +3294,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public async fetchAllGroups(getParticipants: GetParticipant) {
|
public async fetchAllGroups(getParticipants: GetParticipant) {
|
||||||
|
if (this.localSettings.groups_ignore === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
this.logger.verbose('Fetching all groups');
|
this.logger.verbose('Fetching all groups');
|
||||||
try {
|
try {
|
||||||
const fetch = Object.values(await this.client.groupFetchAllParticipating());
|
const fetch = Object.values(await this.client.groupFetchAllParticipating());
|
||||||
|
@ -323,7 +323,7 @@ export class WAMonitoringService {
|
|||||||
this.logger.verbose('Loading instances');
|
this.logger.verbose('Loading instances');
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (this.providerSession.ENABLED) {
|
if (this.providerSession?.ENABLED) {
|
||||||
await this.loadInstancesFromProvider();
|
await this.loadInstancesFromProvider();
|
||||||
} else if (this.redis.REDIS.ENABLED && this.redis.REDIS.SAVE_INSTANCES) {
|
} else if (this.redis.REDIS.ENABLED && this.redis.REDIS.SAVE_INSTANCES) {
|
||||||
await this.loadInstancesFromRedis();
|
await this.loadInstancesFromRedis();
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-namespace */
|
/* eslint-disable @typescript-eslint/no-namespace */
|
||||||
import { AuthenticationState, WAConnectionState } from '@whiskeysockets/baileys';
|
import { AuthenticationState, WAConnectionState } from 'baileys';
|
||||||
|
|
||||||
export enum Events {
|
export enum Events {
|
||||||
APPLICATION_STARTUP = 'application.startup',
|
APPLICATION_STARTUP = 'application.startup',
|
||||||
|
2
src/cache/rediscache.ts
vendored
2
src/cache/rediscache.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import { BufferJSON } from '@whiskeysockets/baileys';
|
import { BufferJSON } from 'baileys';
|
||||||
import { RedisClientType } from 'redis';
|
import { RedisClientType } from 'redis';
|
||||||
|
|
||||||
import { ICache } from '../api/abstract/abstract.cache';
|
import { ICache } from '../api/abstract/abstract.cache';
|
||||||
|
@ -366,9 +366,9 @@ export class ConfigService {
|
|||||||
GLOBAL_EVENTS: process.env?.WEBSOCKET_GLOBAL_EVENTS === 'true',
|
GLOBAL_EVENTS: process.env?.WEBSOCKET_GLOBAL_EVENTS === 'true',
|
||||||
},
|
},
|
||||||
WA_BUSINESS: {
|
WA_BUSINESS: {
|
||||||
TOKEN_WEBHOOK: process.env.WA_BUSINESS_TOKEN_WEBHOOK || '',
|
TOKEN_WEBHOOK: process.env.WA_BUSINESS_TOKEN_WEBHOOK || 'evolution',
|
||||||
URL: process.env.WA_BUSINESS_URL || '',
|
URL: process.env.WA_BUSINESS_URL || 'https://graph.facebook.com',
|
||||||
VERSION: process.env.WA_BUSINESS_VERSION || '',
|
VERSION: process.env.WA_BUSINESS_VERSION || 'v19.0',
|
||||||
LANGUAGE: process.env.WA_BUSINESS_LANGUAGE || 'en',
|
LANGUAGE: process.env.WA_BUSINESS_LANGUAGE || 'en',
|
||||||
},
|
},
|
||||||
LOG: {
|
LOG: {
|
||||||
|
@ -25,7 +25,7 @@ info:
|
|||||||
</font>
|
</font>
|
||||||
|
|
||||||
[](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442)
|
[](https://god.gw.postman.com/run-collection/26869335-5546d063-156b-4529-915f-909dd628c090?action=collection%2Ffork&source=rip_markdown&collection-url=entityId%3D26869335-5546d063-156b-4529-915f-909dd628c090%26entityType%3Dcollection%26workspaceId%3D339a4ee7-378b-45c9-b5b8-fd2c0a9c2442)
|
||||||
version: 1.8.0
|
version: 1.8.2
|
||||||
contact:
|
contact:
|
||||||
name: DavidsonGomes
|
name: DavidsonGomes
|
||||||
email: contato@agenciadgcode.com
|
email: contato@agenciadgcode.com
|
||||||
|
12
src/main.ts
12
src/main.ts
@ -12,7 +12,7 @@ import { initIO } from './api/integrations/websocket/libs/socket.server';
|
|||||||
import { ProviderFiles } from './api/provider/sessions';
|
import { ProviderFiles } from './api/provider/sessions';
|
||||||
import { HttpStatus, router } from './api/routes/index.router';
|
import { HttpStatus, router } from './api/routes/index.router';
|
||||||
import { waMonitor } from './api/server.module';
|
import { waMonitor } from './api/server.module';
|
||||||
import { Auth, configService, Cors, HttpServer, Rabbitmq, Sqs, Webhook } from './config/env.config';
|
import { Auth, configService, Cors, HttpServer, ProviderSession, Rabbitmq, Sqs, Webhook } from './config/env.config';
|
||||||
import { onUnexpectedError } from './config/error.config';
|
import { onUnexpectedError } from './config/error.config';
|
||||||
import { Logger } from './config/logger.config';
|
import { Logger } from './config/logger.config';
|
||||||
import { ROOT_DIR } from './config/path.config';
|
import { ROOT_DIR } from './config/path.config';
|
||||||
@ -27,9 +27,13 @@ async function bootstrap() {
|
|||||||
const logger = new Logger('SERVER');
|
const logger = new Logger('SERVER');
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
const providerFiles = new ProviderFiles(configService);
|
let providerFiles: ProviderFiles = null;
|
||||||
await providerFiles.onModuleInit();
|
|
||||||
logger.info('Provider:Files - ON');
|
if (configService.get<ProviderSession>('PROVIDER')?.ENABLED) {
|
||||||
|
providerFiles = new ProviderFiles(configService);
|
||||||
|
await providerFiles.onModuleInit();
|
||||||
|
logger.info('Provider:Files - ON');
|
||||||
|
}
|
||||||
|
|
||||||
app.use(
|
app.use(
|
||||||
cors({
|
cors({
|
||||||
|
@ -1,29 +1,55 @@
|
|||||||
import {
|
import { AuthenticationState, BufferJSON, initAuthCreds, WAProto as proto } from 'baileys';
|
||||||
AuthenticationCreds,
|
import fs from 'fs/promises';
|
||||||
AuthenticationState,
|
import path from 'path';
|
||||||
BufferJSON,
|
|
||||||
initAuthCreds,
|
|
||||||
proto,
|
|
||||||
SignalDataTypeMap,
|
|
||||||
} from '@whiskeysockets/baileys';
|
|
||||||
|
|
||||||
import { configService, Database } from '../config/env.config';
|
import { configService, Database } from '../config/env.config';
|
||||||
import { Logger } from '../config/logger.config';
|
import { Logger } from '../config/logger.config';
|
||||||
|
import { INSTANCE_DIR } from '../config/path.config';
|
||||||
import { dbserver } from '../libs/db.connect';
|
import { dbserver } from '../libs/db.connect';
|
||||||
|
|
||||||
|
const fixFileName = (file) => {
|
||||||
|
if (!file) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const replacedSlash = file.replace(/\//g, '__');
|
||||||
|
const replacedColon = replacedSlash.replace(/:/g, '-');
|
||||||
|
return replacedColon;
|
||||||
|
};
|
||||||
|
|
||||||
|
async function fileExists(file) {
|
||||||
|
try {
|
||||||
|
const stat = await fs.stat(file);
|
||||||
|
if (stat.isFile()) return true;
|
||||||
|
} catch (error) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function useMultiFileAuthStateDb(
|
export async function useMultiFileAuthStateDb(
|
||||||
coll: string,
|
coll: string,
|
||||||
): Promise<{ state: AuthenticationState; saveCreds: () => Promise<void> }> {
|
): Promise<{ state: AuthenticationState; saveCreds: () => Promise<void> }> {
|
||||||
const logger = new Logger(useMultiFileAuthStateDb.name);
|
|
||||||
|
|
||||||
const client = dbserver.getClient();
|
const client = dbserver.getClient();
|
||||||
|
|
||||||
|
const logger = new Logger(useMultiFileAuthStateDb.name);
|
||||||
|
|
||||||
const collection = client
|
const collection = client
|
||||||
.db(configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME + '-instances')
|
.db(configService.get<Database>('DATABASE').CONNECTION.DB_PREFIX_NAME + '-instances')
|
||||||
.collection(coll);
|
.collection(coll);
|
||||||
|
|
||||||
const writeData = async (data: any, key: string): Promise<any> => {
|
const sessionId = coll;
|
||||||
|
|
||||||
|
const localFolder = path.join(INSTANCE_DIR, sessionId);
|
||||||
|
const localFile = (key: string) => path.join(localFolder, fixFileName(key) + '.json');
|
||||||
|
await fs.mkdir(localFolder, { recursive: true });
|
||||||
|
|
||||||
|
async function writeData(data: any, key: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
|
const dataString = JSON.stringify(data, BufferJSON.replacer);
|
||||||
|
|
||||||
|
if (key != 'creds') {
|
||||||
|
await fs.writeFile(localFile(key), dataString);
|
||||||
|
return;
|
||||||
|
}
|
||||||
await client.connect();
|
await client.connect();
|
||||||
let msgParsed = JSON.parse(JSON.stringify(data, BufferJSON.replacer));
|
let msgParsed = JSON.parse(JSON.stringify(data, BufferJSON.replacer));
|
||||||
if (Array.isArray(msgParsed)) {
|
if (Array.isArray(msgParsed)) {
|
||||||
@ -37,42 +63,59 @@ export async function useMultiFileAuthStateDb(
|
|||||||
});
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const readData = async (key: string): Promise<any> => {
|
async function readData(key: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
await client.connect();
|
if (key != 'creds') {
|
||||||
let data = (await collection.findOne({ _id: key })) as any;
|
if (!(await fileExists(localFile(key)))) return null;
|
||||||
if (data?.content_array) {
|
const rawData = await fs.readFile(localFile(key), { encoding: 'utf-8' });
|
||||||
data = data.content_array;
|
|
||||||
|
const parsedData = JSON.parse(rawData, BufferJSON.reviver);
|
||||||
|
return parsedData;
|
||||||
|
} else {
|
||||||
|
await client.connect();
|
||||||
|
let data = (await collection.findOne({ _id: key })) as any;
|
||||||
|
if (data?.content_array) {
|
||||||
|
data = data.content_array;
|
||||||
|
}
|
||||||
|
const creds = JSON.stringify(data);
|
||||||
|
return JSON.parse(creds, BufferJSON.reviver);
|
||||||
}
|
}
|
||||||
const creds = JSON.stringify(data);
|
|
||||||
return JSON.parse(creds, BufferJSON.reviver);
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const removeData = async (key: string) => {
|
async function removeData(key: string): Promise<any> {
|
||||||
try {
|
try {
|
||||||
await client.connect();
|
if (key != 'creds') {
|
||||||
return await collection.deleteOne({ _id: key });
|
await fs.unlink(localFile(key));
|
||||||
|
} else {
|
||||||
|
await client.connect();
|
||||||
|
return await collection.deleteOne({ _id: key });
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
logger.error(error);
|
logger.error(error);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
const creds: AuthenticationCreds = (await readData('creds')) || initAuthCreds();
|
let creds = await readData('creds');
|
||||||
|
if (!creds) {
|
||||||
|
creds = initAuthCreds();
|
||||||
|
await writeData(creds, 'creds');
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
state: {
|
state: {
|
||||||
creds,
|
creds,
|
||||||
keys: {
|
keys: {
|
||||||
get: async (type, ids: string[]) => {
|
get: async (type, ids) => {
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
const data = {};
|
||||||
// @ts-ignore
|
|
||||||
const data: { [_: string]: SignalDataTypeMap[type] } = {};
|
|
||||||
await Promise.all(
|
await Promise.all(
|
||||||
ids.map(async (id) => {
|
ids.map(async (id) => {
|
||||||
let value = await readData(`${type}-${id}`);
|
let value = await readData(`${type}-${id}`);
|
||||||
@ -83,25 +126,24 @@ export async function useMultiFileAuthStateDb(
|
|||||||
data[id] = value;
|
data[id] = value;
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
},
|
},
|
||||||
set: async (data: any) => {
|
set: async (data) => {
|
||||||
const tasks: Promise<void>[] = [];
|
const tasks = [];
|
||||||
for (const category in data) {
|
for (const category in data) {
|
||||||
for (const id in data[category]) {
|
for (const id in data[category]) {
|
||||||
const value = data[category][id];
|
const value = data[category][id];
|
||||||
const key = `${category}-${id}`;
|
const key = `${category}-${id}`;
|
||||||
|
|
||||||
tasks.push(value ? writeData(value, key) : removeData(key));
|
tasks.push(value ? writeData(value, key) : removeData(key));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all(tasks);
|
await Promise.all(tasks);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
saveCreds: async () => {
|
saveCreds: () => {
|
||||||
return await writeData(creds, 'creds');
|
return writeData(creds, 'creds');
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -34,14 +34,7 @@
|
|||||||
* └──────────────────────────────────────────────────────────────────────────────┘
|
* └──────────────────────────────────────────────────────────────────────────────┘
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import { AuthenticationCreds, AuthenticationState, BufferJSON, initAuthCreds, proto, SignalDataTypeMap } from 'baileys';
|
||||||
AuthenticationCreds,
|
|
||||||
AuthenticationState,
|
|
||||||
BufferJSON,
|
|
||||||
initAuthCreds,
|
|
||||||
proto,
|
|
||||||
SignalDataTypeMap,
|
|
||||||
} from '@whiskeysockets/baileys';
|
|
||||||
import { isNotEmpty } from 'class-validator';
|
import { isNotEmpty } from 'class-validator';
|
||||||
|
|
||||||
import { ProviderFiles } from '../api/provider/sessions';
|
import { ProviderFiles } from '../api/provider/sessions';
|
||||||
|
@ -1,10 +1,4 @@
|
|||||||
import {
|
import { AuthenticationCreds, AuthenticationState, initAuthCreds, proto, SignalDataTypeMap } from 'baileys';
|
||||||
AuthenticationCreds,
|
|
||||||
AuthenticationState,
|
|
||||||
initAuthCreds,
|
|
||||||
proto,
|
|
||||||
SignalDataTypeMap,
|
|
||||||
} from '@whiskeysockets/baileys';
|
|
||||||
|
|
||||||
import { CacheService } from '../api/services/cache.service';
|
import { CacheService } from '../api/services/cache.service';
|
||||||
import { Logger } from '../config/logger.config';
|
import { Logger } from '../config/logger.config';
|
||||||
|
Loading…
Reference in New Issue
Block a user