diff --git a/Dockerfile b/Dockerfile index 53fb0458..4838fd37 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ FROM node:20-alpine AS builder RUN apk update && \ - apk add --no-cache git ffmpeg wget curl bash openssl dos2unix + apk add --no-cache git ffmpeg wget curl bash openssl LABEL version="2.3.1" description="Api to control whatsapp features through http requests." LABEL maintainer="Davidson Gomes" git="https://github.com/DavidsonGomes" @@ -10,24 +10,19 @@ LABEL contact="contato@evolution-api.com" WORKDIR /evolution # Define variáveis de ambiente padrão para o build -ENV DOCKER_ENV=true -ENV DATABASE_PROVIDER=postgresql -ENV DATABASE_URL=postgresql://user:password@localhost:5432/evolution - -# Copia arquivos de configuração primeiro -COPY ./package*.json ./ -COPY ./tsconfig.json ./ -COPY ./tsup.config.ts ./ +COPY ./package.json ./tsconfig.json ./ # Instala todas as dependências (incluindo dev para build) -RUN npm ci --silent +RUN npm install # Copia código fonte COPY ./src ./src COPY ./public ./public COPY ./prisma ./prisma COPY ./manager ./manager +COPY ./.env.example ./.env COPY ./runWithProvider.js ./ +COPY ./tsup.config.ts ./ # Copia scripts Docker COPY ./Docker ./Docker @@ -45,9 +40,6 @@ RUN ./Docker/scripts/generate_database.sh # Build do projeto RUN npm run build -# Remove devDependencies para reduzir tamanho -RUN npm prune --production - FROM node:20-alpine AS final RUN apk update && \ @@ -66,13 +58,13 @@ COPY --from=builder /evolution/dist ./dist COPY --from=builder /evolution/prisma ./prisma COPY --from=builder /evolution/manager ./manager COPY --from=builder /evolution/public ./public +COPY --from=builder /evolution/.env ./.env COPY --from=builder /evolution/Docker ./Docker COPY --from=builder /evolution/runWithProvider.js ./runWithProvider.js COPY --from=builder /evolution/tsup.config.ts ./tsup.config.ts -# Cria arquivo .env vazio - as variáveis virão do Railway -RUN touch .env +ENV DOCKER_ENV=true EXPOSE 8080 -ENTRYPOINT ["/bin/bash", "-c", ". ./Docker/scripts/deploy_database.sh && npm run start:prod" ] +ENTRYPOINT ["/bin/bash", "-c", ". ./Docker/scripts/deploy_database.sh && npm run start:prod" ] diff --git a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts index de31b503..7a967a6c 100644 --- a/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts +++ b/src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts @@ -1226,33 +1226,41 @@ export class BaileysStartupService extends ChannelStartupService { if (this.configService.get('S3').ENABLE) { try { const message: any = received; - const media = await this.getBase64FromMediaMessage({ message }, true); - const { buffer, mediaType, fileName, size } = media; - const mimetype = mimeTypes.lookup(fileName).toString(); - const fullName = join( - `${this.instance.id}`, - received.key.remoteJid, - mediaType, - `${Date.now()}_${fileName}`, - ); - await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype }); + // Verificação adicional para garantir que há conteúdo de mídia real + const hasRealMedia = this.hasValidMediaContent(message); - await this.prismaRepository.media.create({ - data: { - messageId: msg.id, - instanceId: this.instanceId, - type: mediaType, - fileName: fullName, - mimetype, - }, - }); + if (!hasRealMedia) { + this.logger.warn('Message detected as media but contains no valid media content'); + } else { + const media = await this.getBase64FromMediaMessage({ message }, true); - const mediaUrl = await s3Service.getObjectUrl(fullName); + const { buffer, mediaType, fileName, size } = media; + const mimetype = mimeTypes.lookup(fileName).toString(); + const fullName = join( + `${this.instance.id}`, + received.key.remoteJid, + mediaType, + `${Date.now()}_${fileName}`, + ); + await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype }); - messageRaw.message.mediaUrl = mediaUrl; + await this.prismaRepository.media.create({ + data: { + messageId: msg.id, + instanceId: this.instanceId, + type: mediaType, + fileName: fullName, + mimetype, + }, + }); - await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw }); + const mediaUrl = await s3Service.getObjectUrl(fullName); + + messageRaw.message.mediaUrl = mediaUrl; + + await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw }); + } } catch (error) { this.logger.error(['Error on upload file to minio', error?.message, error?.stack]); } @@ -2121,31 +2129,39 @@ export class BaileysStartupService extends ChannelStartupService { if (isMedia && this.configService.get('S3').ENABLE) { try { const message: any = messageRaw; - const media = await this.getBase64FromMediaMessage({ message }, true); - const { buffer, mediaType, fileName, size } = media; + // Verificação adicional para garantir que há conteúdo de mídia real + const hasRealMedia = this.hasValidMediaContent(message); - const mimetype = mimeTypes.lookup(fileName).toString(); + if (!hasRealMedia) { + this.logger.warn('Message detected as media but contains no valid media content'); + } else { + const media = await this.getBase64FromMediaMessage({ message }, true); - const fullName = join( - `${this.instance.id}`, - messageRaw.key.remoteJid, - `${messageRaw.key.id}`, - mediaType, - fileName, - ); + const { buffer, mediaType, fileName, size } = media; - await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype }); + const mimetype = mimeTypes.lookup(fileName).toString(); - await this.prismaRepository.media.create({ - data: { messageId: msg.id, instanceId: this.instanceId, type: mediaType, fileName: fullName, mimetype }, - }); + const fullName = join( + `${this.instance.id}`, + messageRaw.key.remoteJid, + `${messageRaw.key.id}`, + mediaType, + fileName, + ); - const mediaUrl = await s3Service.getObjectUrl(fullName); + await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype }); - messageRaw.message.mediaUrl = mediaUrl; + await this.prismaRepository.media.create({ + data: { messageId: msg.id, instanceId: this.instanceId, type: mediaType, fileName: fullName, mimetype }, + }); - await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw }); + const mediaUrl = await s3Service.getObjectUrl(fullName); + + messageRaw.message.mediaUrl = mediaUrl; + + await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw }); + } } catch (error) { this.logger.error(['Error on upload file to minio', error?.message, error?.stack]); } diff --git a/src/api/services/channel.service.ts b/src/api/services/channel.service.ts index edc54e62..d5cd976f 100644 --- a/src/api/services/channel.service.ts +++ b/src/api/services/channel.service.ts @@ -814,4 +814,28 @@ export class ChannelStartupService { return []; } + + public hasValidMediaContent(message: any): boolean { + if (!message?.message) return false; + + const msg = message.message; + + // Se só tem messageContextInfo, não é mídia válida + if (Object.keys(msg).length === 1 && 'messageContextInfo' in msg) { + return false; + } + + // Verifica se tem pelo menos um tipo de mídia válido + const mediaTypes = [ + 'imageMessage', + 'videoMessage', + 'stickerMessage', + 'documentMessage', + 'documentWithCaptionMessage', + 'ptvMessage', + 'audioMessage', + ]; + + return mediaTypes.some((type) => msg[type] && Object.keys(msg[type]).length > 0); + } }