Merge branch 'release/1.7.0'

This commit is contained in:
Davidson Gomes 2024-03-27 12:30:11 -03:00
commit ad4f5e5e65
10 changed files with 64 additions and 11 deletions

View File

@ -56,7 +56,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",
"evolution-manager": "^0.4.11", "evolution-manager": "^0.4.13",
"exiftool-vendored": "^22.0.0", "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",

View File

@ -10,6 +10,7 @@ let amqpChannel: amqp.Channel | null = null;
export const initAMQP = () => { export const initAMQP = () => {
return new Promise<void>((resolve, reject) => { return new Promise<void>((resolve, reject) => {
const uri = configService.get<Rabbitmq>('RABBITMQ').URI; const uri = configService.get<Rabbitmq>('RABBITMQ').URI;
const exchangeName = configService.get<Rabbitmq>('RABBITMQ').EXCHANGE_NAME ?? 'evolution_exchange';
amqp.connect(uri, (error, connection) => { amqp.connect(uri, (error, connection) => {
if (error) { if (error) {
reject(error); reject(error);
@ -22,8 +23,6 @@ export const initAMQP = () => {
return; return;
} }
const exchangeName = 'evolution_exchange';
channel.assertExchange(exchangeName, 'topic', { channel.assertExchange(exchangeName, 'topic', {
durable: true, durable: true,
autoDelete: false, autoDelete: false,
@ -51,7 +50,7 @@ export const initQueues = (instanceName: string, events: string[]) => {
queues.forEach((event) => { queues.forEach((event) => {
const amqp = getAMQP(); const amqp = getAMQP();
const exchangeName = instanceName ?? 'evolution_exchange'; const exchangeName = configService.get<Rabbitmq>('RABBITMQ').EXCHANGE_NAME ?? instanceName;
amqp.assertExchange(exchangeName, 'topic', { amqp.assertExchange(exchangeName, 'topic', {
durable: true, durable: true,
@ -81,7 +80,7 @@ export const removeQueues = (instanceName: string, events: string[]) => {
return `${event.replace(/_/g, '.').toLowerCase()}`; return `${event.replace(/_/g, '.').toLowerCase()}`;
}); });
const exchangeName = instanceName ?? 'evolution_exchange'; const exchangeName = configService.get<Rabbitmq>('RABBITMQ').EXCHANGE_NAME ?? instanceName;
queues.forEach((event) => { queues.forEach((event) => {
const amqp = getAMQP(); const amqp = getAMQP();

View File

@ -161,6 +161,18 @@ export const presenceSchema: JSONSchema7 = {
required: ['options', 'number'], required: ['options', 'number'],
}; };
export const presenceOnlySchema: JSONSchema7 = {
$id: v4(),
type: 'object',
properties: {
presence: {
type: 'string',
enum: ['unavailable', 'available', 'composing', 'recording', 'paused'],
},
},
required: ['presence'],
};
export const pollMessageSchema: JSONSchema7 = { export const pollMessageSchema: JSONSchema7 = {
$id: v4(), $id: v4(),
type: 'object', type: 'object',

View File

@ -7,7 +7,7 @@ import { ConfigService, HttpServer, WaBusiness } from '../../config/env.config';
import { Logger } from '../../config/logger.config'; import { Logger } from '../../config/logger.config';
import { BadRequestException, InternalServerErrorException } from '../../exceptions'; import { BadRequestException, InternalServerErrorException } from '../../exceptions';
import { RedisCache } from '../../libs/redis.client'; import { RedisCache } from '../../libs/redis.client';
import { InstanceDto } from '../dto/instance.dto'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto';
import { RepositoryBroker } from '../repository/repository.manager'; import { RepositoryBroker } from '../repository/repository.manager';
import { AuthService, OldToken } from '../services/auth.service'; import { AuthService, OldToken } from '../services/auth.service';
import { CacheService } from '../services/cache.service'; import { CacheService } from '../services/cache.service';
@ -656,6 +656,11 @@ export class InstanceController {
return this.waMonitor.instanceInfo(); return this.waMonitor.instanceInfo();
} }
public async setPresence({ instanceName }: InstanceDto, data: SetPresenceDto) {
this.logger.verbose('requested sendPresence from ' + instanceName + ' instance');
return await this.waMonitor.waInstances[instanceName].setPresence(data);
}
public async logout({ instanceName }: InstanceDto) { public async logout({ instanceName }: InstanceDto) {
this.logger.verbose('requested logout from ' + instanceName + ' instance'); this.logger.verbose('requested logout from ' + instanceName + ' instance');
const { instance } = await this.connectionState({ instanceName }); const { instance } = await this.connectionState({ instanceName });

View File

@ -1,3 +1,5 @@
import { WAPresence } from "@whiskeysockets/baileys";
export class InstanceDto { export class InstanceDto {
instanceName: string; instanceName: string;
instanceId?: string; instanceId?: string;
@ -40,3 +42,7 @@ export class InstanceDto {
typebot_listening_from_me?: boolean; typebot_listening_from_me?: boolean;
proxy?: string; proxy?: string;
} }
export class SetPresenceDto {
presence: WAPresence;
}

View File

@ -9,6 +9,7 @@ import {
messageUpSchema, messageUpSchema,
messageValidateSchema, messageValidateSchema,
presenceSchema, presenceSchema,
presenceOnlySchema,
privacySettingsSchema, privacySettingsSchema,
profileNameSchema, profileNameSchema,
profilePictureSchema, profilePictureSchema,

View File

@ -3,9 +3,9 @@ import { RequestHandler, Router } from 'express';
import { Auth, ConfigService, Database } from '../../config/env.config'; import { Auth, ConfigService, Database } from '../../config/env.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';
import { instanceNameSchema, oldTokenSchema } from '../../validate/validate.schema'; import {instanceNameSchema, oldTokenSchema, presenceOnlySchema} from '../../validate/validate.schema';
import { RouterBroker } from '../abstract/abstract.router'; import { RouterBroker } from '../abstract/abstract.router';
import { InstanceDto } from '../dto/instance.dto'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto';
import { OldToken } from '../services/auth.service'; import { OldToken } from '../services/auth.service';
import { instanceController } from '../whatsapp.module'; import { instanceController } from '../whatsapp.module';
import { HttpStatus } from './index.router'; import { HttpStatus } from './index.router';
@ -98,6 +98,22 @@ export class InstanceRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response); return res.status(HttpStatus.OK).json(response);
}) })
.post(this.routerPath('setPresence'), ...guards, async (req, res) => {
logger.verbose('request received in setPresence');
logger.verbose('request body: ');
logger.verbose(req.body);
logger.verbose('request query: ');
logger.verbose(req.query);
const response = await this.dataValidate<null>({
request: req,
schema: presenceOnlySchema,
ClassRef: SetPresenceDto,
execute: (instance, data) => instanceController.setPresence(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.delete(this.routerPath('logout'), ...guards, async (req, res) => { .delete(this.routerPath('logout'), ...guards, async (req, res) => {
logger.verbose('request received in logoutInstances'); logger.verbose('request received in logoutInstances');
logger.verbose('request body: '); logger.verbose('request body: ');

View File

@ -89,7 +89,7 @@ import {
GroupUpdateParticipantDto, GroupUpdateParticipantDto,
GroupUpdateSettingDto, GroupUpdateSettingDto,
} from '../dto/group.dto'; } from '../dto/group.dto';
import { InstanceDto } from '../dto/instance.dto'; import { InstanceDto, SetPresenceDto } from '../dto/instance.dto';
import { HandleLabelDto, LabelDto } from '../dto/label.dto'; import { HandleLabelDto, LabelDto } from '../dto/label.dto';
import { import {
ContactMessage, ContactMessage,
@ -1830,7 +1830,6 @@ export class BaileysStartupService extends WAStartupService {
} }
// Instance Controller // Instance Controller
public async sendPresence(data: SendPresenceDto) { public async sendPresence(data: SendPresenceDto) {
try { try {
const { number } = data; const { number } = data;
@ -1863,6 +1862,17 @@ export class BaileysStartupService extends WAStartupService {
} }
} }
// Presence Controller
public async setPresence(data: SetPresenceDto) {
try {
await this.client.sendPresenceUpdate(data.presence);
this.logger.verbose('Sending presence update: ' + data.presence);
} catch (error) {
this.logger.error(error);
throw new BadRequestException(error.toString());
}
}
// Send Message Controller // Send Message Controller
public async textMessage(data: SendTextDto, isChatwoot = false) { public async textMessage(data: SendTextDto, isChatwoot = false) {
this.logger.verbose('Sending text message'); this.logger.verbose('Sending text message');

View File

@ -1185,6 +1185,9 @@ export class BusinessStartupService extends WAStartupService {
public async sendPresence() { public async sendPresence() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
} }
public async setPresence() {
throw new BadRequestException('Method not available on WhatsApp Business API');
}
public async fetchPrivacySettings() { public async fetchPrivacySettings() {
throw new BadRequestException('Method not available on WhatsApp Business API'); throw new BadRequestException('Method not available on WhatsApp Business API');
} }

View File

@ -13,6 +13,7 @@ import {
Database, Database,
HttpServer, HttpServer,
Log, Log,
Rabbitmq,
Sqs, Sqs,
Webhook, Webhook,
Websocket, Websocket,
@ -685,7 +686,7 @@ export class WAStartupService {
if (amqp) { if (amqp) {
if (Array.isArray(rabbitmqLocal) && rabbitmqLocal.includes(we)) { if (Array.isArray(rabbitmqLocal) && rabbitmqLocal.includes(we)) {
const exchangeName = this.instanceName ?? 'evolution_exchange'; const exchangeName = this.configService.get<Rabbitmq>('RABBITMQ').EXCHANGE_NAME ?? this.instanceName;
amqp.assertExchange(exchangeName, 'topic', { amqp.assertExchange(exchangeName, 'topic', {
durable: true, durable: true,