mirror of
https://github.com/EvolutionAPI/evolution-api.git
synced 2025-07-14 01:41:24 -06:00
feat: send media with form-data
This commit is contained in:
parent
44e152bea2
commit
ec2d7e349f
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
* Sync lost messages on chatwoot
|
* Sync lost messages on chatwoot
|
||||||
* Set the maximum number of listeners that can be registered for events
|
* Set the maximum number of listeners that can be registered for events
|
||||||
|
* Now is possible send medias with form-data
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ version: "3.7"
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
evolution_v2:
|
evolution_v2:
|
||||||
image: atendai/evolution-api:v2.0.10
|
image: atendai/evolution-api:v2.1.2
|
||||||
volumes:
|
volumes:
|
||||||
- evolution_instances:/evolution/instances
|
- evolution_instances:/evolution/instances
|
||||||
networks:
|
networks:
|
||||||
|
@ -80,6 +80,7 @@
|
|||||||
"long": "^5.2.3",
|
"long": "^5.2.3",
|
||||||
"mime": "^3.0.0",
|
"mime": "^3.0.0",
|
||||||
"minio": "^8.0.1",
|
"minio": "^8.0.1",
|
||||||
|
"multer": "^1.4.5-lts.1",
|
||||||
"node-cache": "^5.1.2",
|
"node-cache": "^5.1.2",
|
||||||
"node-cron": "^3.0.3",
|
"node-cron": "^3.0.3",
|
||||||
"node-windows": "^1.0.0-beta.8",
|
"node-windows": "^1.0.0-beta.8",
|
||||||
|
9
src/@types/express.d.ts
vendored
Normal file
9
src/@types/express.d.ts
vendored
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Multer } from 'multer';
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
namespace Express {
|
||||||
|
interface Request {
|
||||||
|
file?: Multer.File;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -28,27 +28,27 @@ export class SendMessageController {
|
|||||||
return await this.waMonitor.waInstances[instanceName].textMessage(data);
|
return await this.waMonitor.waInstances[instanceName].textMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendMedia({ instanceName }: InstanceDto, data: SendMediaDto) {
|
public async sendMedia({ instanceName }: InstanceDto, data: SendMediaDto, file?: any) {
|
||||||
if (isBase64(data?.media) && !data?.fileName && data?.mediatype === 'document') {
|
if (isBase64(data?.media) && !data?.fileName && data?.mediatype === 'document') {
|
||||||
throw new BadRequestException('For base64 the file name must be informed.');
|
throw new BadRequestException('For base64 the file name must be informed.');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isURL(data?.media) || isBase64(data?.media)) {
|
if (file || isURL(data?.media) || isBase64(data?.media)) {
|
||||||
return await this.waMonitor.waInstances[instanceName].mediaMessage(data);
|
return await this.waMonitor.waInstances[instanceName].mediaMessage(data, file);
|
||||||
}
|
}
|
||||||
throw new BadRequestException('Owned media must be a url or base64');
|
throw new BadRequestException('Owned media must be a url or base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendSticker({ instanceName }: InstanceDto, data: SendStickerDto) {
|
public async sendSticker({ instanceName }: InstanceDto, data: SendStickerDto, file?: any) {
|
||||||
if (isURL(data.sticker) || isBase64(data.sticker)) {
|
if (file || isURL(data.sticker) || isBase64(data.sticker)) {
|
||||||
return await this.waMonitor.waInstances[instanceName].mediaSticker(data);
|
return await this.waMonitor.waInstances[instanceName].mediaSticker(data, file);
|
||||||
}
|
}
|
||||||
throw new BadRequestException('Owned media must be a url or base64');
|
throw new BadRequestException('Owned media must be a url or base64');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto) {
|
public async sendWhatsAppAudio({ instanceName }: InstanceDto, data: SendAudioDto, file?: any) {
|
||||||
if (isURL(data.audio) || isBase64(data.audio)) {
|
if (file || isURL(data.audio) || isBase64(data.audio)) {
|
||||||
return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data);
|
return await this.waMonitor.waInstances[instanceName].audioWhatsapp(data, file);
|
||||||
}
|
}
|
||||||
throw new BadRequestException('Owned media must be a url or base64');
|
throw new BadRequestException('Owned media must be a url or base64');
|
||||||
}
|
}
|
||||||
@ -80,7 +80,7 @@ export class SendMessageController {
|
|||||||
return await this.waMonitor.waInstances[instanceName].pollMessage(data);
|
return await this.waMonitor.waInstances[instanceName].pollMessage(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto) {
|
public async sendStatus({ instanceName }: InstanceDto, data: SendStatusDto, file?: any) {
|
||||||
return await this.waMonitor.waInstances[instanceName].statusMessage(data);
|
return await this.waMonitor.waInstances[instanceName].statusMessage(data, file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ import { ChannelStartupService } from '@api/services/channel.service';
|
|||||||
import { Events, wa } from '@api/types/wa.types';
|
import { Events, wa } from '@api/types/wa.types';
|
||||||
import { Chatwoot, ConfigService, Openai } from '@config/env.config';
|
import { Chatwoot, ConfigService, Openai } from '@config/env.config';
|
||||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||||
|
import { deleteTempFile, getTempFile } from '@utils/getTempFile';
|
||||||
import { isURL } from 'class-validator';
|
import { isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
import mime from 'mime';
|
import mime from 'mime';
|
||||||
@ -164,7 +165,7 @@ export class EvolutionStartupService extends ChannelStartupService {
|
|||||||
|
|
||||||
await this.updateContact({
|
await this.updateContact({
|
||||||
remoteJid: messageRaw.key.remoteJid,
|
remoteJid: messageRaw.key.remoteJid,
|
||||||
pushName: messageRaw.key.fromMe ? '' : (messageRaw.key.fromMe == null ? '' : received.pushName),
|
pushName: messageRaw.key.fromMe ? '' : messageRaw.key.fromMe == null ? '' : received.pushName,
|
||||||
profilePicUrl: received.profilePicUrl,
|
profilePicUrl: received.profilePicUrl,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -433,11 +434,14 @@ export class EvolutionStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async mediaMessage(data: SendMediaDto, isIntegration = false) {
|
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
|
||||||
const message = await this.prepareMediaMessage(data);
|
const mediaData: SendMediaDto = { ...data };
|
||||||
|
|
||||||
console.log('message', message);
|
if (file) mediaData.media = await getTempFile(file, this.instanceId);
|
||||||
return await this.sendMessageWithTyping(
|
|
||||||
|
const message = await this.prepareMediaMessage(mediaData);
|
||||||
|
|
||||||
|
const mediaSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
{ ...message },
|
{ ...message },
|
||||||
{
|
{
|
||||||
@ -450,6 +454,10 @@ export class EvolutionStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return mediaSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async processAudio(audio: string, number: string) {
|
public async processAudio(audio: string, number: string) {
|
||||||
@ -475,10 +483,14 @@ export class EvolutionStartupService extends ChannelStartupService {
|
|||||||
return prepareMedia;
|
return prepareMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async audioWhatsapp(data: SendAudioDto, isIntegration = false) {
|
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
|
||||||
const message = await this.processAudio(data.audio, data.number);
|
const mediaData: SendAudioDto = { ...data };
|
||||||
|
|
||||||
return await this.sendMessageWithTyping(
|
if (file) mediaData.audio = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
const message = await this.processAudio(mediaData.audio, data.number);
|
||||||
|
|
||||||
|
const audioSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
{ ...message },
|
{ ...message },
|
||||||
{
|
{
|
||||||
@ -491,6 +503,10 @@ export class EvolutionStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return audioSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async buttonMessage() {
|
public async buttonMessage() {
|
||||||
|
@ -22,6 +22,7 @@ import { ChannelStartupService } from '@api/services/channel.service';
|
|||||||
import { Events, wa } from '@api/types/wa.types';
|
import { Events, wa } from '@api/types/wa.types';
|
||||||
import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@config/env.config';
|
import { Chatwoot, ConfigService, Database, Openai, S3, WaBusiness } from '@config/env.config';
|
||||||
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
import { BadRequestException, InternalServerErrorException } from '@exceptions';
|
||||||
|
import { deleteTempFile, getTempFile } from '@utils/getTempFile';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { arrayUnique, isURL } from 'class-validator';
|
import { arrayUnique, isURL } from 'class-validator';
|
||||||
import EventEmitter2 from 'eventemitter2';
|
import EventEmitter2 from 'eventemitter2';
|
||||||
@ -1026,10 +1027,14 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async mediaMessage(data: SendMediaDto, isIntegration = false) {
|
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
|
||||||
const message = await this.prepareMediaMessage(data);
|
const mediaData: SendMediaDto = { ...data };
|
||||||
|
|
||||||
return await this.sendMessageWithTyping(
|
if (file) mediaData.media = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
const message = await this.prepareMediaMessage(mediaData);
|
||||||
|
|
||||||
|
const mediaSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
{ ...message },
|
{ ...message },
|
||||||
{
|
{
|
||||||
@ -1042,6 +1047,10 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return mediaSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async processAudio(audio: string, number: string) {
|
public async processAudio(audio: string, number: string) {
|
||||||
@ -1072,10 +1081,14 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
return prepareMedia;
|
return prepareMedia;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async audioWhatsapp(data: SendAudioDto, isIntegration = false) {
|
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
|
||||||
const message = await this.processAudio(data.audio, data.number);
|
const mediaData: SendAudioDto = { ...data };
|
||||||
|
|
||||||
return await this.sendMessageWithTyping(
|
if (file) mediaData.audio = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
const message = await this.processAudio(mediaData.audio, data.number);
|
||||||
|
|
||||||
|
const audioSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
{ ...message },
|
{ ...message },
|
||||||
{
|
{
|
||||||
@ -1088,6 +1101,10 @@ export class BusinessStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return audioSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async buttonMessage(data: SendButtonDto) {
|
public async buttonMessage(data: SendButtonDto) {
|
||||||
|
@ -70,6 +70,7 @@ import { BadRequestException, InternalServerErrorException, NotFoundException }
|
|||||||
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
|
import ffmpegPath from '@ffmpeg-installer/ffmpeg';
|
||||||
import { Boom } from '@hapi/boom';
|
import { Boom } from '@hapi/boom';
|
||||||
import { Instance } from '@prisma/client';
|
import { Instance } from '@prisma/client';
|
||||||
|
import { deleteTempFile, getTempFile } from '@utils/getTempFile';
|
||||||
import { makeProxyAgent } from '@utils/makeProxyAgent';
|
import { makeProxyAgent } from '@utils/makeProxyAgent';
|
||||||
import { getOnWhatsappCache, saveOnWhatsappCache } from '@utils/onWhatsappCache';
|
import { getOnWhatsappCache, saveOnWhatsappCache } from '@utils/onWhatsappCache';
|
||||||
import useMultiFileAuthStatePrisma from '@utils/use-multi-file-auth-state-prisma';
|
import useMultiFileAuthStatePrisma from '@utils/use-multi-file-auth-state-prisma';
|
||||||
@ -2266,12 +2267,20 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
throw new BadRequestException('Type not found');
|
throw new BadRequestException('Type not found');
|
||||||
}
|
}
|
||||||
|
|
||||||
public async statusMessage(data: SendStatusDto) {
|
public async statusMessage(data: SendStatusDto, file?: any) {
|
||||||
const status = await this.formatStatusMessage(data);
|
const mediaData: SendStatusDto = { ...data };
|
||||||
|
|
||||||
return await this.sendMessageWithTyping('status@broadcast', {
|
if (file) mediaData.content = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
const status = await this.formatStatusMessage(mediaData);
|
||||||
|
|
||||||
|
const statusSent = await this.sendMessageWithTyping('status@broadcast', {
|
||||||
status,
|
status,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return statusSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async prepareMediaMessage(mediaMessage: MediaMessage) {
|
private async prepareMediaMessage(mediaMessage: MediaMessage) {
|
||||||
@ -2395,7 +2404,11 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public async mediaSticker(data: SendStickerDto) {
|
public async mediaSticker(data: SendStickerDto, file?: any) {
|
||||||
|
const mediaData: SendStickerDto = { ...data };
|
||||||
|
|
||||||
|
if (file) mediaData.sticker = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
const convert = await this.convertToWebP(data.sticker);
|
const convert = await this.convertToWebP(data.sticker);
|
||||||
const gifPlayback = data.sticker.includes('.gif');
|
const gifPlayback = data.sticker.includes('.gif');
|
||||||
const result = await this.sendMessageWithTyping(
|
const result = await this.sendMessageWithTyping(
|
||||||
@ -2413,13 +2426,19 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async mediaMessage(data: SendMediaDto, isIntegration = false) {
|
public async mediaMessage(data: SendMediaDto, file?: any, isIntegration = false) {
|
||||||
const generate = await this.prepareMediaMessage(data);
|
const mediaData: SendMediaDto = { ...data };
|
||||||
|
|
||||||
return await this.sendMessageWithTyping(
|
if (file) mediaData.media = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
const generate = await this.prepareMediaMessage(mediaData);
|
||||||
|
|
||||||
|
const mediaSent = await this.sendMessageWithTyping(
|
||||||
data.number,
|
data.number,
|
||||||
{ ...generate.message },
|
{ ...generate.message },
|
||||||
{
|
{
|
||||||
@ -2431,6 +2450,10 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
},
|
},
|
||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
|
return mediaSent;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async processAudioMp4(audio: string) {
|
public async processAudioMp4(audio: string) {
|
||||||
@ -2534,13 +2557,17 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public async audioWhatsapp(data: SendAudioDto, isIntegration = false) {
|
public async audioWhatsapp(data: SendAudioDto, file?: any, isIntegration = false) {
|
||||||
|
const mediaData: SendAudioDto = { ...data };
|
||||||
|
|
||||||
|
if (file) mediaData.audio = await getTempFile(file, this.instanceId);
|
||||||
|
|
||||||
if (!data?.encoding && data?.encoding !== false) {
|
if (!data?.encoding && data?.encoding !== false) {
|
||||||
data.encoding = true;
|
data.encoding = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data?.encoding) {
|
if (data?.encoding) {
|
||||||
const convert = await this.processAudio(data.audio);
|
const convert = await this.processAudio(mediaData.audio);
|
||||||
|
|
||||||
if (Buffer.isBuffer(convert)) {
|
if (Buffer.isBuffer(convert)) {
|
||||||
const result = this.sendMessageWithTyping<AnyMessageContent>(
|
const result = this.sendMessageWithTyping<AnyMessageContent>(
|
||||||
@ -2554,6 +2581,8 @@ export class BaileysStartupService extends ChannelStartupService {
|
|||||||
isIntegration,
|
isIntegration,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if (file) await deleteTempFile(file, this.instanceId);
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
} else {
|
} else {
|
||||||
throw new InternalServerErrorException('Failed to convert audio');
|
throw new InternalServerErrorException('Failed to convert audio');
|
||||||
|
@ -105,4 +105,35 @@ const getObjectUrl = async (fileName: string, expiry?: number) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export { BUCKET, getObjectUrl, uploadFile };
|
const uploadTempFile = async (
|
||||||
|
folder: string,
|
||||||
|
fileName: string,
|
||||||
|
file: Buffer | Transform | Readable,
|
||||||
|
size: number,
|
||||||
|
metadata: Metadata,
|
||||||
|
) => {
|
||||||
|
if (minioClient) {
|
||||||
|
const objectName = join(folder, fileName);
|
||||||
|
try {
|
||||||
|
metadata['custom-header-application'] = 'evolution-api';
|
||||||
|
return await minioClient.putObject(bucketName, objectName, file, size, metadata);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const deleteFile = async (folder: string, fileName: string) => {
|
||||||
|
if (minioClient) {
|
||||||
|
const objectName = join(folder, fileName);
|
||||||
|
try {
|
||||||
|
return await minioClient.removeObject(bucketName, objectName);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error(error);
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export { BUCKET, deleteFile, getObjectUrl, uploadFile, uploadTempFile };
|
||||||
|
@ -29,9 +29,12 @@ import {
|
|||||||
textMessageSchema,
|
textMessageSchema,
|
||||||
} from '@validate/validate.schema';
|
} from '@validate/validate.schema';
|
||||||
import { RequestHandler, Router } from 'express';
|
import { RequestHandler, Router } from 'express';
|
||||||
|
import multer from 'multer';
|
||||||
|
|
||||||
import { HttpStatus } from './index.router';
|
import { HttpStatus } from './index.router';
|
||||||
|
|
||||||
|
const upload = multer({ storage: multer.memoryStorage() });
|
||||||
|
|
||||||
export class MessageRouter extends RouterBroker {
|
export class MessageRouter extends RouterBroker {
|
||||||
constructor(...guards: RequestHandler[]) {
|
constructor(...guards: RequestHandler[]) {
|
||||||
super();
|
super();
|
||||||
@ -56,43 +59,51 @@ export class MessageRouter extends RouterBroker {
|
|||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
})
|
})
|
||||||
.post(this.routerPath('sendMedia'), ...guards, async (req, res) => {
|
.post(this.routerPath('sendMedia'), ...guards, upload.single('file'), async (req, res) => {
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
const response = await this.dataValidate<SendMediaDto>({
|
const response = await this.dataValidate<SendMediaDto>({
|
||||||
request: req,
|
request: req,
|
||||||
schema: mediaMessageSchema,
|
schema: mediaMessageSchema,
|
||||||
ClassRef: SendMediaDto,
|
ClassRef: SendMediaDto,
|
||||||
execute: (instance, data) => sendMessageController.sendMedia(instance, data),
|
execute: (instance) => sendMessageController.sendMedia(instance, bodyData, req.file as any),
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
})
|
})
|
||||||
.post(this.routerPath('sendWhatsAppAudio'), ...guards, async (req, res) => {
|
.post(this.routerPath('sendWhatsAppAudio'), ...guards, upload.single('file'), async (req, res) => {
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
const response = await this.dataValidate<SendAudioDto>({
|
const response = await this.dataValidate<SendAudioDto>({
|
||||||
request: req,
|
request: req,
|
||||||
schema: audioMessageSchema,
|
schema: audioMessageSchema,
|
||||||
ClassRef: SendMediaDto,
|
ClassRef: SendMediaDto,
|
||||||
execute: (instance, data) => sendMessageController.sendWhatsAppAudio(instance, data),
|
execute: (instance) => sendMessageController.sendWhatsAppAudio(instance, bodyData, req.file as any),
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
})
|
})
|
||||||
// TODO: Revisar funcionamento do envio de Status
|
// TODO: Revisar funcionamento do envio de Status
|
||||||
.post(this.routerPath('sendStatus'), ...guards, async (req, res) => {
|
.post(this.routerPath('sendStatus'), ...guards, upload.single('file'), async (req, res) => {
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
const response = await this.dataValidate<SendStatusDto>({
|
const response = await this.dataValidate<SendStatusDto>({
|
||||||
request: req,
|
request: req,
|
||||||
schema: statusMessageSchema,
|
schema: statusMessageSchema,
|
||||||
ClassRef: SendStatusDto,
|
ClassRef: SendStatusDto,
|
||||||
execute: (instance, data) => sendMessageController.sendStatus(instance, data),
|
execute: (instance) => sendMessageController.sendStatus(instance, bodyData, req.file as any),
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
})
|
})
|
||||||
.post(this.routerPath('sendSticker'), ...guards, async (req, res) => {
|
.post(this.routerPath('sendSticker'), ...guards, upload.single('file'), async (req, res) => {
|
||||||
|
const bodyData = req.body;
|
||||||
|
|
||||||
const response = await this.dataValidate<SendStickerDto>({
|
const response = await this.dataValidate<SendStickerDto>({
|
||||||
request: req,
|
request: req,
|
||||||
schema: stickerMessageSchema,
|
schema: stickerMessageSchema,
|
||||||
ClassRef: SendStickerDto,
|
ClassRef: SendStickerDto,
|
||||||
execute: (instance, data) => sendMessageController.sendSticker(instance, data),
|
execute: (instance) => sendMessageController.sendSticker(instance, bodyData, req.file as any),
|
||||||
});
|
});
|
||||||
|
|
||||||
return res.status(HttpStatus.CREATED).json(response);
|
return res.status(HttpStatus.CREATED).json(response);
|
||||||
|
34
src/utils/getTempFile.ts
Normal file
34
src/utils/getTempFile.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import * as s3Service from '@api/integrations/storage/s3/libs/minio.server';
|
||||||
|
import mime from 'mime-types';
|
||||||
|
|
||||||
|
export const getTempFile = async (file: any, instanceId: string): Promise<string> => {
|
||||||
|
const fileName = file.originalname;
|
||||||
|
const mimetype = mime.lookup(fileName) || 'application/octet-stream';
|
||||||
|
const folder = `${process.env.S3_BUCKET}/${instanceId}/temp`;
|
||||||
|
const fileUrl = `https://${process.env.S3_ENDPOINT}/${process.env.S3_BUCKET}/${folder}/${fileName}`;
|
||||||
|
|
||||||
|
if (!process.env.S3_ENABLED || process.env.S3_ENABLED !== 'true') {
|
||||||
|
return file.buffer.toString('base64');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (file.buffer) {
|
||||||
|
await s3Service.uploadTempFile(folder, fileName, file.buffer, file.size, {
|
||||||
|
'Content-Type': mimetype,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Erro ao fazer upload do arquivo ${fileName}:`, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return fileUrl;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteTempFile = async (file: any, instanceId: string): Promise<void> => {
|
||||||
|
if (!process.env.S3_ENABLED) return;
|
||||||
|
|
||||||
|
const fileName = file.originalname;
|
||||||
|
const folder = `${process.env.S3_BUCKET}/${instanceId}/temp`;
|
||||||
|
|
||||||
|
await s3Service.deleteFile(folder, fileName);
|
||||||
|
};
|
@ -108,7 +108,7 @@ export const mediaMessageSchema: JSONSchema7 = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ['number', 'mediatype', 'media'],
|
required: ['number', 'mediatype'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const audioMessageSchema: JSONSchema7 = {
|
export const audioMessageSchema: JSONSchema7 = {
|
||||||
@ -134,7 +134,7 @@ export const audioMessageSchema: JSONSchema7 = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ['number', 'audio'],
|
required: ['number'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const statusMessageSchema: JSONSchema7 = {
|
export const statusMessageSchema: JSONSchema7 = {
|
||||||
@ -158,7 +158,7 @@ export const statusMessageSchema: JSONSchema7 = {
|
|||||||
},
|
},
|
||||||
allContacts: { type: 'boolean', enum: [true, false] },
|
allContacts: { type: 'boolean', enum: [true, false] },
|
||||||
},
|
},
|
||||||
required: ['type', 'content'],
|
required: ['type'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const stickerMessageSchema: JSONSchema7 = {
|
export const stickerMessageSchema: JSONSchema7 = {
|
||||||
@ -184,7 +184,7 @@ export const stickerMessageSchema: JSONSchema7 = {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
required: ['number', 'sticker'],
|
required: ['number'],
|
||||||
};
|
};
|
||||||
|
|
||||||
export const locationMessageSchema: JSONSchema7 = {
|
export const locationMessageSchema: JSONSchema7 = {
|
||||||
|
Loading…
Reference in New Issue
Block a user