chore: Simplified payloads and endpoints

This commit is contained in:
Davidson Gomes
2024-06-07 13:00:35 -03:00
parent a578384e85
commit 8fd082ad80
25 changed files with 1329 additions and 1403 deletions

View File

@@ -21,47 +21,40 @@ import { WAMonitoringService } from '../services/monitor.service';
export class SendMessageController {
constructor(private readonly waMonitor: WAMonitoringService) {}
public async sendText({ instanceName }: InstanceDto, data: SendTextDto) {
return await this.waMonitor.waInstances[instanceName].textMessage(data);
}
public async sendTemplate({ instanceName }: InstanceDto, data: SendTemplateDto) {
return await this.waMonitor.waInstances[instanceName].templateMessage(data);
}
public async sendText({ instanceName }: InstanceDto, data: SendTextDto) {
return await this.waMonitor.waInstances[instanceName].textMessage(data);
}
public async sendMedia({ instanceName }: InstanceDto, data: SendMediaDto) {
if (
isBase64(data?.mediaMessage?.media) &&
!data?.mediaMessage?.fileName &&
data?.mediaMessage?.mediatype === 'document'
) {
if (isBase64(data?.media) && !data?.fileName && data?.mediatype === 'document') {
throw new BadRequestException('For base64 the file name must be informed.');
}
if (isURL(data?.mediaMessage?.media) || isBase64(data?.mediaMessage?.media)) {
if (isURL(data?.media) || isBase64(data?.media)) {
return await this.waMonitor.waInstances[instanceName].mediaMessage(data);
}
throw new BadRequestException('Owned media must be a url or base64');
}
public async sendSticker({ instanceName }: InstanceDto, data: SendStickerDto) {
if (isURL(data.stickerMessage.image) || isBase64(data.stickerMessage.image)) {
if (isURL(data.sticker) || isBase64(data.sticker)) {
return await this.waMonitor.waInstances[instanceName].mediaSticker(data);
}
throw new BadRequestException('Owned media must be a url or base64');
}
public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto) {
if (isURL(data.audioMessage.audio) || isBase64(data.audioMessage.audio)) {
if (isURL(data.audio) || isBase64(data.audio)) {
return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data);
}
throw new BadRequestException('Owned media must be a url or base64');
}
public async sendButtons({ instanceName }: InstanceDto, data: SendButtonDto) {
if (isBase64(data.buttonMessage.mediaMessage?.media) && !data.buttonMessage.mediaMessage?.fileName) {
throw new BadRequestException('For bse64 the file name must be informed.');
}
return await this.waMonitor.waInstances[instanceName].buttonMessage(data);
}
@@ -78,7 +71,7 @@ export class SendMessageController {
}
public async sendReaction({ instanceName }: InstanceDto, data: SendReactionDto) {
if (!data.reactionMessage.reaction.match(/[^()\w\sà-ú"-+]+/)) {
if (!data.reaction.match(/[^()\w\sà-ú"-+]+/)) {
throw new BadRequestException('"reaction" must be an emoji');
}
return await this.waMonitor.waInstances[instanceName].reactionMessage(data);

View File

@@ -1,6 +1,7 @@
import { isURL } from 'class-validator';
import { BadRequestException } from '../../exceptions';
import { Events } from '../../validate/validate.schema';
import { InstanceDto } from '../dto/instance.dto';
import { WebhookDto } from '../dto/webhook.dto';
import { WAMonitoringService } from '../services/monitor.service';
@@ -20,32 +21,7 @@ export class WebhookController {
data.url = '';
data.events = [];
} else if (data.events.length === 0) {
data.events = [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
];
data.events = Events;
}
return this.webhookService.create(instance, data);

View File

@@ -109,10 +109,8 @@ export class Metadata extends OptionsMessage {
}
export class SendPresenceDto extends Metadata {
options: {
presence: WAPresence;
delay: number;
};
presence: WAPresence;
delay: number;
}
export class UpdateMessageDto extends Metadata {

View File

@@ -18,16 +18,15 @@ export class Options {
linkPreview?: boolean;
encoding?: boolean;
}
class OptionsMessage {
options: Options;
}
export class Metadata extends OptionsMessage {
number: string;
}
class TextMessage {
text: string;
export class MediaMessage {
mediatype: MediaType;
mimetype?: string;
caption?: string;
// for document
fileName?: string;
// url or base64
media: string;
}
export class StatusMessage {
@@ -40,30 +39,43 @@ export class StatusMessage {
font?: number;
}
class PollMessage {
export class Metadata {
number: string;
delay?: number;
quoted?: Quoted;
linkPreview?: boolean;
everyOne: boolean;
mentioned: string[];
encoding?: boolean;
}
export class SendTextDto extends Metadata {
text: string;
}
export class SendPresence extends Metadata {
text: string;
}
export class SendStatusDto extends Metadata {
type: string;
content: string;
statusJidList?: string[];
allContacts?: boolean;
caption?: string;
backgroundColor?: string;
font?: number;
}
export class SendPollDto extends Metadata {
name: string;
selectableCount: number;
values: string[];
messageSecret?: Uint8Array;
}
export class SendTextDto extends Metadata {
textMessage: TextMessage;
}
export class SendPresence extends Metadata {
textMessage: TextMessage;
}
export class SendStatusDto extends Metadata {
statusMessage: StatusMessage;
}
export class SendPollDto extends Metadata {
pollMessage: PollMessage;
}
export type MediaType = 'image' | 'document' | 'video' | 'audio';
export class MediaMessage {
export class SendMediaDto extends Metadata {
mediatype: MediaType;
mimetype?: string;
caption?: string;
@@ -72,21 +84,13 @@ export class MediaMessage {
// url or base64
media: string;
}
export class SendMediaDto extends Metadata {
mediaMessage: MediaMessage;
}
class Sticker {
image: string;
}
export class SendStickerDto extends Metadata {
stickerMessage: Sticker;
sticker: string;
}
class Audio {
audio: string;
}
export class SendAudioDto extends Metadata {
audioMessage: Audio;
audio: string;
}
class Button {
@@ -98,21 +102,17 @@ class ButtonMessage {
description: string;
footerText?: string;
buttons: Button[];
mediaMessage?: MediaMessage;
}
export class SendButtonDto extends Metadata {
buttonMessage: ButtonMessage;
}
class LocationMessage {
export class SendLocationDto extends Metadata {
latitude: number;
longitude: number;
name?: string;
address?: string;
}
export class SendLocationDto extends Metadata {
locationMessage: LocationMessage;
}
class Row {
title: string;
@@ -123,16 +123,13 @@ class Section {
title: string;
rows: Row[];
}
class ListMessage {
export class SendListDto extends Metadata {
title: string;
description: string;
description?: string;
footerText?: string;
buttonText: string;
sections: Section[];
}
export class SendListDto extends Metadata {
listMessage: ListMessage;
}
export class ContactMessage {
fullName: string;
@@ -143,23 +140,16 @@ export class ContactMessage {
url?: string;
}
export class TemplateMessage {
export class SendTemplateDto extends Metadata {
name: string;
language: string;
components: any;
}
export class SendTemplateDto extends Metadata {
templateMessage: TemplateMessage;
}
export class SendContactDto extends Metadata {
contactMessage: ContactMessage[];
contact: ContactMessage[];
}
class ReactionMessage {
export class SendReactionDto {
key: proto.IMessageKey;
reaction: string;
}
export class SendReactionDto {
reactionMessage: ReactionMessage;
}

View File

@@ -25,20 +25,20 @@ export const chatwootSchema: JSONSchema7 = {
type: 'object',
properties: {
enabled: { type: 'boolean', enum: [true, false] },
account_id: { type: 'string' },
accountId: { type: 'string' },
token: { type: 'string' },
url: { type: 'string' },
sign_msg: { type: 'boolean', enum: [true, false] },
sign_delimiter: { type: ['string', 'null'] },
name_inbox: { type: ['string', 'null'] },
reopen_conversation: { type: 'boolean', enum: [true, false] },
signMsg: { type: 'boolean', enum: [true, false] },
signDelimiter: { type: ['string', 'null'] },
nameInbox: { type: ['string', 'null'] },
reopenConversation: { type: 'boolean', enum: [true, false] },
conversation_pending: { type: 'boolean', enum: [true, false] },
auto_create: { type: 'boolean', enum: [true, false] },
import_contacts: { type: 'boolean', enum: [true, false] },
merge_brazil_contacts: { type: 'boolean', enum: [true, false] },
import_messages: { type: 'boolean', enum: [true, false] },
days_limit_import_messages: { type: 'number' },
autoCreate: { type: 'boolean', enum: [true, false] },
importContacts: { type: 'boolean', enum: [true, false] },
mergeBrazilContacts: { type: 'boolean', enum: [true, false] },
importMessages: { type: 'boolean', enum: [true, false] },
daysLimitImportMessages: { type: 'number' },
},
required: ['enabled', 'account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'],
...isNotEmpty('account_id', 'token', 'url', 'sign_msg', 'reopen_conversation', 'conversation_pending'),
required: ['enabled', 'accountId', 'token', 'url', 'signMsg', 'reopenConversation', 'conversation_pending'],
...isNotEmpty('enabled', 'accountId', 'token', 'url', 'signMsg', 'reopenConversation', 'conversation_pending'),
};

View File

@@ -1,6 +1,8 @@
import { JSONSchema7 } from 'json-schema';
import { v4 } from 'uuid';
import { Events } from '../../../../validate/validate.schema';
const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => {
const properties = {};
propertyNames.forEach(
@@ -30,32 +32,7 @@ export const rabbitmqSchema: JSONSchema7 = {
minItems: 0,
items: {
type: 'string',
enum: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
],
enum: Events,
},
},
},

View File

@@ -1,6 +1,8 @@
import { JSONSchema7 } from 'json-schema';
import { v4 } from 'uuid';
import { Events } from '../../../../validate/validate.schema';
const isNotEmpty = (...propertyNames: string[]): JSONSchema7 => {
const properties = {};
propertyNames.forEach(
@@ -30,32 +32,7 @@ export const sqsSchema: JSONSchema7 = {
minItems: 0,
items: {
type: 'string',
enum: [
'APPLICATION_STARTUP',
'QRCODE_UPDATED',
'MESSAGES_SET',
'MESSAGES_UPSERT',
'MESSAGES_UPDATE',
'MESSAGES_DELETE',
'SEND_MESSAGE',
'CONTACTS_SET',
'CONTACTS_UPSERT',
'CONTACTS_UPDATE',
'PRESENCE_UPDATE',
'CHATS_SET',
'CHATS_UPSERT',
'CHATS_UPDATE',
'CHATS_DELETE',
'GROUPS_UPSERT',
'GROUP_UPDATE',
'GROUP_PARTICIPANTS_UPDATE',
'CONNECTION_UPDATE',
'LABELS_EDIT',
'LABELS_ASSOCIATION',
'CALL',
'TYPEBOT_START',
'TYPEBOT_CHANGE_STATUS',
],
enum: Events,
},
},
},

View File

@@ -28,12 +28,12 @@ export const typebotSchema: JSONSchema7 = {
url: { type: 'string' },
typebot: { type: 'string' },
expire: { type: 'integer' },
delay_message: { type: 'integer' },
unknown_message: { type: 'string' },
listening_from_me: { type: 'boolean', enum: [true, false] },
delayMessage: { type: 'integer' },
unknownMessage: { type: 'string' },
listeningFromMe: { type: 'boolean', enum: [true, false] },
},
required: ['enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'],
...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delay_message', 'unknown_message', 'listening_from_me'),
required: ['enabled', 'url', 'typebot', 'expire', 'delayMessage', 'unknownMessage', 'listeningFromMe'],
...isNotEmpty('enabled', 'url', 'typebot', 'expire', 'delayMessage', 'unknownMessage', 'listeningFromMe'),
};
export const typebotStatusSchema: JSONSchema7 = {

View File

@@ -55,7 +55,7 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('markMessageAsRead'), ...guards, async (req, res) => {
.post(this.routerPath('markMessageAsRead'), ...guards, async (req, res) => {
const response = await this.dataValidate<ReadMessageDto>({
request: req,
schema: readMessageSchema,
@@ -65,7 +65,7 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('archiveChat'), ...guards, async (req, res) => {
.post(this.routerPath('archiveChat'), ...guards, async (req, res) => {
const response = await this.dataValidate<ArchiveChatDto>({
request: req,
schema: archiveChatSchema,
@@ -75,7 +75,7 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('markChatUnread'), ...guards, async (req, res) => {
.post(this.routerPath('markChatUnread'), ...guards, async (req, res) => {
const response = await this.dataValidate<MarkChatUnreadDto>({
request: req,
schema: markChatUnreadSchema,
@@ -105,16 +105,46 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('fetchProfile'), ...guards, async (req, res) => {
const response = await this.dataValidate<NumberDto>({
.post(this.routerPath('getBase64FromMediaMessage'), ...guards, async (req, res) => {
const response = await this.dataValidate<getBase64FromMediaMessageDto>({
request: req,
schema: profileSchema,
ClassRef: NumberDto,
execute: (instance, data) => chatController.fetchProfile(instance, data),
schema: null,
ClassRef: getBase64FromMediaMessageDto,
execute: (instance, data) => chatController.getBase64FromMediaMessage(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('updateMessage'), ...guards, async (req, res) => {
const response = await this.dataValidate<UpdateMessageDto>({
request: req,
schema: updateMessageSchema,
ClassRef: UpdateMessageDto,
execute: (instance, data) => chatController.updateMessage(instance, data),
});
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('sendPresence'), ...guards, async (req, res) => {
const response = await this.dataValidate<null>({
request: req,
schema: presenceSchema,
ClassRef: SendPresenceDto,
execute: (instance, data) => chatController.sendPresence(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('updateBlockStatus'), ...guards, async (req, res) => {
const response = await this.dataValidate<BlockUserDto>({
request: req,
schema: blockUserSchema,
ClassRef: BlockUserDto,
execute: (instance, data) => chatController.blockUser(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('findContacts'), ...guards, async (req, res) => {
const response = await this.dataValidate<Query<Contact>>({
request: req,
@@ -125,16 +155,6 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('getBase64FromMediaMessage'), ...guards, async (req, res) => {
const response = await this.dataValidate<getBase64FromMediaMessageDto>({
request: req,
schema: null,
ClassRef: getBase64FromMediaMessageDto,
execute: (instance, data) => chatController.getBase64FromMediaMessage(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('findMessages'), ...guards, async (req, res) => {
const response = await this.dataValidate<Query<Message>>({
request: req,
@@ -165,37 +185,7 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('sendPresence'), ...guards, async (req, res) => {
const response = await this.dataValidate<null>({
request: req,
schema: presenceSchema,
ClassRef: SendPresenceDto,
execute: (instance, data) => chatController.sendPresence(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
// Profile routes
.get(this.routerPath('fetchPrivacySettings'), ...guards, async (req, res) => {
const response = await this.dataValidate<InstanceDto>({
request: req,
schema: null,
ClassRef: InstanceDto,
execute: (instance) => chatController.fetchPrivacySettings(instance),
});
return res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('updatePrivacySettings'), ...guards, async (req, res) => {
const response = await this.dataValidate<PrivacySettingDto>({
request: req,
schema: privacySettingsSchema,
ClassRef: PrivacySettingDto,
execute: (instance, data) => chatController.updatePrivacySettings(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('fetchBusinessProfile'), ...guards, async (req, res) => {
const response = await this.dataValidate<ProfilePictureDto>({
request: req,
@@ -206,6 +196,17 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('fetchProfile'), ...guards, async (req, res) => {
const response = await this.dataValidate<NumberDto>({
request: req,
schema: profileSchema,
ClassRef: NumberDto,
execute: (instance, data) => chatController.fetchProfile(instance, data),
});
return res.status(HttpStatus.OK).json(response);
})
.post(this.routerPath('updateProfileName'), ...guards, async (req, res) => {
const response = await this.dataValidate<ProfileNameDto>({
request: req,
@@ -246,22 +247,22 @@ export class ChatRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('updateMessage'), ...guards, async (req, res) => {
const response = await this.dataValidate<UpdateMessageDto>({
.get(this.routerPath('fetchPrivacySettings'), ...guards, async (req, res) => {
const response = await this.dataValidate<InstanceDto>({
request: req,
schema: updateMessageSchema,
ClassRef: UpdateMessageDto,
execute: (instance, data) => chatController.updateMessage(instance, data),
schema: null,
ClassRef: InstanceDto,
execute: (instance) => chatController.fetchPrivacySettings(instance),
});
return res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('updateBlockStatus'), ...guards, async (req, res) => {
const response = await this.dataValidate<BlockUserDto>({
.post(this.routerPath('updatePrivacySettings'), ...guards, async (req, res) => {
const response = await this.dataValidate<PrivacySettingDto>({
request: req,
schema: blockUserSchema,
ClassRef: BlockUserDto,
execute: (instance, data) => chatController.blockUser(instance, data),
schema: privacySettingsSchema,
ClassRef: PrivacySettingDto,
execute: (instance, data) => chatController.updatePrivacySettings(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);

View File

@@ -46,7 +46,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('updateGroupSubject'), ...guards, async (req, res) => {
.post(this.routerPath('updateGroupSubject'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupSubjectDto>({
request: req,
schema: updateGroupSubjectSchema,
@@ -56,7 +56,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('updateGroupPicture'), ...guards, async (req, res) => {
.post(this.routerPath('updateGroupPicture'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupPictureDto>({
request: req,
schema: updateGroupPictureSchema,
@@ -66,7 +66,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('updateGroupDescription'), ...guards, async (req, res) => {
.post(this.routerPath('updateGroupDescription'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupDescriptionDto>({
request: req,
schema: updateGroupDescriptionSchema,
@@ -146,7 +146,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('revokeInviteCode'), ...guards, async (req, res) => {
.post(this.routerPath('revokeInviteCode'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupJid>({
request: req,
schema: groupJidSchema,
@@ -156,7 +156,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('updateParticipant'), ...guards, async (req, res) => {
.post(this.routerPath('updateParticipant'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupUpdateParticipantDto>({
request: req,
schema: updateParticipantsSchema,
@@ -166,7 +166,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('updateSetting'), ...guards, async (req, res) => {
.post(this.routerPath('updateSetting'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupUpdateSettingDto>({
request: req,
schema: updateSettingsSchema,
@@ -176,7 +176,7 @@ export class GroupRouter extends RouterBroker {
res.status(HttpStatus.CREATED).json(response);
})
.put(this.routerPath('toggleEphemeral'), ...guards, async (req, res) => {
.post(this.routerPath('toggleEphemeral'), ...guards, async (req, res) => {
const response = await this.groupValidate<GroupToggleEphemeralDto>({
request: req,
schema: toggleEphemeralSchema,

View File

@@ -20,7 +20,7 @@ export class LabelRouter extends RouterBroker {
return res.status(HttpStatus.OK).json(response);
})
.put(this.routerPath('handleLabel'), ...guards, async (req, res) => {
.post(this.routerPath('handleLabel'), ...guards, async (req, res) => {
const response = await this.dataValidate<HandleLabelDto>({
request: req,
schema: handleLabelSchema,

View File

@@ -2,7 +2,6 @@ import { RequestHandler, Router } from 'express';
import {
audioMessageSchema,
buttonMessageSchema,
contactMessageSchema,
listMessageSchema,
locationMessageSchema,
@@ -17,7 +16,6 @@ import {
import { RouterBroker } from '../abstract/abstract.router';
import {
SendAudioDto,
SendButtonDto,
SendContactDto,
SendListDto,
SendLocationDto,
@@ -36,6 +34,16 @@ export class MessageRouter extends RouterBroker {
constructor(...guards: RequestHandler[]) {
super();
this.router
.post(this.routerPath('sendTemplate'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendTemplateDto>({
request: req,
schema: templateMessageSchema,
ClassRef: SendTemplateDto,
execute: (instance, data) => sendMessageController.sendTemplate(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendText'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendTextDto>({
request: req,
@@ -66,22 +74,22 @@ export class MessageRouter extends RouterBroker {
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendTemplate'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendTemplateDto>({
.post(this.routerPath('sendStatus'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendStatusDto>({
request: req,
schema: templateMessageSchema,
ClassRef: SendTemplateDto,
execute: (instance, data) => sendMessageController.sendTemplate(instance, data),
schema: statusMessageSchema,
ClassRef: SendStatusDto,
execute: (instance, data) => sendMessageController.sendStatus(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendButtons'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendButtonDto>({
.post(this.routerPath('sendSticker'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendStickerDto>({
request: req,
schema: buttonMessageSchema,
ClassRef: SendButtonDto,
execute: (instance, data) => sendMessageController.sendButtons(instance, data),
schema: stickerMessageSchema,
ClassRef: SendStickerDto,
execute: (instance, data) => sendMessageController.sendSticker(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
@@ -96,16 +104,6 @@ export class MessageRouter extends RouterBroker {
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendList'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendListDto>({
request: req,
schema: listMessageSchema,
ClassRef: SendListDto,
execute: (instance, data) => sendMessageController.sendList(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendContact'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendContactDto>({
request: req,
@@ -136,26 +134,26 @@ export class MessageRouter extends RouterBroker {
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendStatus'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendStatusDto>({
.post(this.routerPath('sendList'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendListDto>({
request: req,
schema: statusMessageSchema,
ClassRef: SendStatusDto,
execute: (instance, data) => sendMessageController.sendStatus(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
})
.post(this.routerPath('sendSticker'), ...guards, async (req, res) => {
const response = await this.dataValidate<SendStickerDto>({
request: req,
schema: stickerMessageSchema,
ClassRef: SendStickerDto,
execute: (instance, data) => sendMessageController.sendSticker(instance, data),
schema: listMessageSchema,
ClassRef: SendListDto,
execute: (instance, data) => sendMessageController.sendList(instance, data),
});
return res.status(HttpStatus.CREATED).json(response);
});
// .post(this.routerPath('sendButtons'), ...guards, async (req, res) => {
// const response = await this.dataValidate<SendButtonDto>({
// request: req,
// schema: buttonMessageSchema,
// ClassRef: SendButtonDto,
// execute: (instance, data) => sendMessageController.sendButtons(instance, data),
// });
// return res.status(HttpStatus.CREATED).json(response);
// })
}
public readonly router = Router();

View File

@@ -1,6 +1,6 @@
import { RequestHandler, Router } from 'express';
import { instanceSchema, settingsSchema } from '../../validate/validate.schema';
import { settingsSchema } from '../../validate/validate.schema';
import { RouterBroker } from '../abstract/abstract.router';
import { InstanceDto } from '../dto/instance.dto';
import { SettingsDto } from '../dto/settings.dto';
@@ -24,7 +24,7 @@ export class SettingsRouter extends RouterBroker {
.get(this.routerPath('find'), ...guards, async (req, res) => {
const response = await this.dataValidate<InstanceDto>({
request: req,
schema: instanceSchema,
schema: null,
ClassRef: InstanceDto,
execute: (instance) => settingsController.findSettings(instance),
});

View File

@@ -1921,12 +1921,12 @@ export class BaileysStartupService extends ChannelStartupService {
const sender = isWA.jid;
if (data?.options?.delay && data?.options?.delay > 20000) {
let remainingDelay = data?.options.delay;
if (data?.delay && data?.delay > 20000) {
let remainingDelay = data?.delay;
while (remainingDelay > 20000) {
await this.client.presenceSubscribe(sender);
await this.client.sendPresenceUpdate((data?.options?.presence as WAPresence) ?? 'composing', sender);
await this.client.sendPresenceUpdate((data?.presence as WAPresence) ?? 'composing', sender);
await delay(20000);
@@ -1937,7 +1937,7 @@ export class BaileysStartupService extends ChannelStartupService {
if (remainingDelay > 0) {
await this.client.presenceSubscribe(sender);
await this.client.sendPresenceUpdate((data?.options?.presence as WAPresence) ?? 'composing', sender);
await this.client.sendPresenceUpdate((data?.presence as WAPresence) ?? 'composing', sender);
await delay(remainingDelay);
@@ -1946,9 +1946,9 @@ export class BaileysStartupService extends ChannelStartupService {
} else {
await this.client.presenceSubscribe(sender);
await this.client.sendPresenceUpdate((data?.options?.presence as WAPresence) ?? 'composing', sender);
await this.client.sendPresenceUpdate((data?.presence as WAPresence) ?? 'composing', sender);
await delay(data?.options?.delay);
await delay(data?.delay);
await this.client.sendPresenceUpdate('paused', sender);
}
@@ -1973,9 +1973,18 @@ export class BaileysStartupService extends ChannelStartupService {
return await this.sendMessageWithTyping(
data.number,
{
conversation: data.textMessage.text,
conversation: data.text,
},
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
linkPreview: data?.linkPreview,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
data?.options,
isChatwoot,
);
}
@@ -1985,12 +1994,21 @@ export class BaileysStartupService extends ChannelStartupService {
data.number,
{
poll: {
name: data.pollMessage.name,
selectableCount: data.pollMessage.selectableCount,
values: data.pollMessage.values,
name: data.name,
selectableCount: data.selectableCount,
values: data.values,
},
},
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
linkPreview: data?.linkPreview,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
data?.options,
);
}
@@ -2093,7 +2111,7 @@ export class BaileysStartupService extends ChannelStartupService {
}
public async statusMessage(data: SendStatusDto) {
const status = await this.formatStatusMessage(data.statusMessage);
const status = await this.formatStatusMessage(data);
return await this.sendMessageWithTyping('status@broadcast', {
status,
@@ -2233,13 +2251,21 @@ export class BaileysStartupService extends ChannelStartupService {
}
public async mediaSticker(data: SendStickerDto) {
const convert = await this.convertToWebP(data.stickerMessage.image, data.number);
const convert = await this.convertToWebP(data.sticker, data.number);
const result = await this.sendMessageWithTyping(
data.number,
{
sticker: { url: convert },
},
data?.options,
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
);
fs.unlinkSync(convert);
@@ -2248,9 +2274,22 @@ export class BaileysStartupService extends ChannelStartupService {
}
public async mediaMessage(data: SendMediaDto, isChatwoot = false) {
const generate = await this.prepareMediaMessage(data.mediaMessage);
const generate = await this.prepareMediaMessage(data);
return await this.sendMessageWithTyping(data.number, { ...generate.message }, data?.options, isChatwoot);
return await this.sendMessageWithTyping(
data.number,
{ ...generate.message },
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
isChatwoot,
);
}
public async processAudio(audio: string, number: string) {
@@ -2290,12 +2329,12 @@ export class BaileysStartupService extends ChannelStartupService {
}
public async audioWhatsapp(data: SendAudioDto, isChatwoot = false) {
if (!data.options?.encoding && data.options?.encoding !== false) {
data.options.encoding = true;
if (!data?.encoding && data?.encoding !== false) {
data.encoding = true;
}
if (data.options?.encoding) {
const convert = await this.processAudio(data.audioMessage.audio, data.number);
if (data?.encoding) {
const convert = await this.processAudio(data.audio, data.number);
if (typeof convert === 'string') {
const audio = fs.readFileSync(convert).toString('base64');
const result = this.sendMessageWithTyping<AnyMessageContent>(
@@ -2305,7 +2344,7 @@ export class BaileysStartupService extends ChannelStartupService {
ptt: true,
mimetype: 'audio/mp4',
},
{ presence: 'recording', delay: data?.options?.delay },
{ presence: 'recording', delay: data?.delay },
isChatwoot,
);
@@ -2320,13 +2359,11 @@ export class BaileysStartupService extends ChannelStartupService {
return await this.sendMessageWithTyping<AnyMessageContent>(
data.number,
{
audio: isURL(data.audioMessage.audio)
? { url: data.audioMessage.audio }
: Buffer.from(data.audioMessage.audio, 'base64'),
audio: isURL(data.audio) ? { url: data.audio } : Buffer.from(data.audio, 'base64'),
ptt: true,
mimetype: 'audio/ogg; codecs=opus',
},
{ presence: 'recording', delay: data?.options?.delay },
{ presence: 'recording', delay: data?.delay },
isChatwoot,
);
}
@@ -2340,13 +2377,21 @@ export class BaileysStartupService extends ChannelStartupService {
data.number,
{
locationMessage: {
degreesLatitude: data.locationMessage.latitude,
degreesLongitude: data.locationMessage.longitude,
name: data.locationMessage?.name,
address: data.locationMessage?.address,
degreesLatitude: data.latitude,
degreesLongitude: data.longitude,
name: data?.name,
address: data?.address,
},
},
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
data?.options,
);
}
@@ -2355,15 +2400,23 @@ export class BaileysStartupService extends ChannelStartupService {
data.number,
{
listMessage: {
title: data.listMessage.title,
description: data.listMessage.description,
buttonText: data.listMessage?.buttonText,
footerText: data.listMessage?.footerText,
sections: data.listMessage.sections,
title: data.title,
description: data?.description,
buttonText: data?.buttonText,
footerText: data?.footerText,
sections: data.sections,
listType: 2,
},
},
data?.options,
{
delay: data?.delay,
presence: 'composing',
quoted: data?.quoted,
mentions: {
everyOne: data?.everyOne,
mentioned: data?.mentioned,
},
},
);
}
@@ -2394,15 +2447,15 @@ export class BaileysStartupService extends ChannelStartupService {
return result;
};
if (data.contactMessage.length === 1) {
if (data.contact.length === 1) {
message.contactMessage = {
displayName: data.contactMessage[0].fullName,
vcard: vcard(data.contactMessage[0]),
displayName: data.contact[0].fullName,
vcard: vcard(data.contact[0]),
};
} else {
message.contactsArrayMessage = {
displayName: `${data.contactMessage.length} contacts`,
contacts: data.contactMessage.map((contact) => {
displayName: `${data.contact.length} contacts`,
contacts: data.contact.map((contact) => {
return {
displayName: contact.fullName,
vcard: vcard(contact),
@@ -2411,14 +2464,14 @@ export class BaileysStartupService extends ChannelStartupService {
};
}
return await this.sendMessageWithTyping(data.number, { ...message }, data?.options);
return await this.sendMessageWithTyping(data.number, { ...message }, {});
}
public async reactionMessage(data: SendReactionDto) {
return await this.sendMessageWithTyping(data.reactionMessage.key.remoteJid, {
return await this.sendMessageWithTyping(data.key.remoteJid, {
reactionMessage: {
key: data.reactionMessage.key,
text: data.reactionMessage.reaction,
key: data.key,
text: data.reaction,
},
});
}

View File

@@ -1047,9 +1047,9 @@ export class BusinessStartupService extends ChannelStartupService {
data.number,
{
template: {
name: data.templateMessage.name,
language: data.templateMessage.language,
components: data.templateMessage.components,
name: data.name,
language: data.language,
components: data.components,
},
},
data?.options,