Skip to content

Commit 5e3537b

Browse files
kay0ramonclaude
andcommitted
fix(baileys): never let the S3 upload step drop the message webhook
The S3 block in `messages.upsert` and `sendMessageWithTyping` uses `return` to skip the upload, but it sits before `sendDataWebhook(...)` — so skipping the upload drops the webhook with it. And `return`, not `continue`, inside `for (const received of messages)` aborts the whole handler. Media sent from the phone linked to the instance (`fromMe`, LID addressing) reaches `getBase64FromMediaMessage`, whose MessageSubtype unwrap leaves only `messageContextInfo`; it returns null and the handler exits before announcing the message. Text is unaffected (`isMedia` false), and so is media received from the contact. Skip only the upload, never the handler. Behaviour is unchanged when the upload succeeds. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent e273b90 commit 5e3537b

1 file changed

Lines changed: 84 additions & 73 deletions

File tree

src/api/integrations/channel/whatsapp/whatsapp.baileys.service.ts

Lines changed: 84 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -1576,52 +1576,55 @@ export class BaileysStartupService extends ChannelStartupService {
15761576
if (isMedia) {
15771577
if (this.configService.get<S3>('S3').ENABLE) {
15781578
try {
1579+
// Skip only the S3 upload here — NOT the whole handler. The previous `return`
1580+
// statements exited messages.upsert before sendDataWebhook(Events.MESSAGES_UPSERT)
1581+
// below, silently dropping the message. Webhook delivery must never depend on the
1582+
// outcome of the storage step.
15791583
if (isVideo && !this.configService.get<S3>('S3').SAVE_VIDEO) {
15801584
this.logger.warn('Video upload is disabled. Skipping video upload.');
1581-
// Skip video upload by returning early from this block
1582-
return;
1583-
}
1584-
1585-
const message: any = received;
1586-
1587-
// Verificação adicional para garantir que há conteúdo de mídia real
1588-
const hasRealMedia = this.hasValidMediaContent(message);
1589-
1590-
if (!hasRealMedia) {
1591-
this.logger.warn('Message detected as media but contains no valid media content');
15921585
} else {
1593-
const media = await this.getBase64FromMediaMessage({ message }, true);
1594-
1595-
if (!media) {
1596-
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
1597-
return;
1586+
const message: any = received;
1587+
1588+
// Verificação adicional para garantir que há conteúdo de mídia real
1589+
const hasRealMedia = this.hasValidMediaContent(message);
1590+
1591+
if (!hasRealMedia) {
1592+
this.logger.warn('Message detected as media but contains no valid media content');
1593+
} else {
1594+
const media = await this.getBase64FromMediaMessage({ message }, true);
1595+
1596+
if (!media) {
1597+
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
1598+
} else {
1599+
const { buffer, mediaType, fileName, size } = media;
1600+
const mimetype = mimeTypes.lookup(fileName).toString();
1601+
const fullName = join(
1602+
`${this.instance.id}`,
1603+
received.key.remoteJid,
1604+
mediaType,
1605+
`${Date.now()}_${fileName}`,
1606+
);
1607+
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, {
1608+
'Content-Type': mimetype,
1609+
});
1610+
1611+
await this.prismaRepository.media.create({
1612+
data: {
1613+
messageId: msg.id,
1614+
instanceId: this.instanceId,
1615+
type: mediaType,
1616+
fileName: fullName,
1617+
mimetype,
1618+
},
1619+
});
1620+
1621+
const mediaUrl = await s3Service.getObjectUrl(fullName);
1622+
1623+
(messageRaw.message as any).mediaUrl = mediaUrl;
1624+
1625+
await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw });
1626+
}
15981627
}
1599-
1600-
const { buffer, mediaType, fileName, size } = media;
1601-
const mimetype = mimeTypes.lookup(fileName).toString();
1602-
const fullName = join(
1603-
`${this.instance.id}`,
1604-
received.key.remoteJid,
1605-
mediaType,
1606-
`${Date.now()}_${fileName}`,
1607-
);
1608-
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype });
1609-
1610-
await this.prismaRepository.media.create({
1611-
data: {
1612-
messageId: msg.id,
1613-
instanceId: this.instanceId,
1614-
type: mediaType,
1615-
fileName: fullName,
1616-
mimetype,
1617-
},
1618-
});
1619-
1620-
const mediaUrl = await s3Service.getObjectUrl(fullName);
1621-
1622-
(messageRaw.message as any).mediaUrl = mediaUrl;
1623-
1624-
await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw });
16251628
}
16261629
} catch (error) {
16271630
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);
@@ -2770,48 +2773,56 @@ export class BaileysStartupService extends ChannelStartupService {
27702773

27712774
if (isMedia && this.configService.get<S3>('S3').ENABLE) {
27722775
try {
2776+
// Skip only the S3 upload here — NOT the whole method. The previous `return` exited
2777+
// sendMessageWithTyping before sendDataWebhook(Events.SEND_MESSAGE) and the
2778+
// `return messageRaw` below, making POST /message/sendMedia respond empty.
27732779
if (isVideo && !this.configService.get<S3>('S3').SAVE_VIDEO) {
2774-
throw new Error('Video upload is disabled.');
2775-
}
2776-
2777-
const message: any = messageRaw;
2778-
2779-
// Verificação adicional para garantir que há conteúdo de mídia real
2780-
const hasRealMedia = this.hasValidMediaContent(message);
2781-
2782-
if (!hasRealMedia) {
2783-
this.logger.warn('Message detected as media but contains no valid media content');
2780+
this.logger.warn('Video upload is disabled. Skipping video upload.');
27842781
} else {
2785-
const media = await this.getBase64FromMediaMessage({ message }, true);
2782+
const message: any = messageRaw;
27862783

2787-
if (!media) {
2788-
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
2789-
return;
2790-
}
2784+
// Verificação adicional para garantir que há conteúdo de mídia real
2785+
const hasRealMedia = this.hasValidMediaContent(message);
27912786

2792-
const { buffer, mediaType, fileName, size } = media;
2787+
if (!hasRealMedia) {
2788+
this.logger.warn('Message detected as media but contains no valid media content');
2789+
} else {
2790+
const media = await this.getBase64FromMediaMessage({ message }, true);
27932791

2794-
const mimetype = mimeTypes.lookup(fileName).toString();
2792+
if (!media) {
2793+
this.logger.verbose('No valid media to upload (messageContextInfo only), skipping MinIO');
2794+
} else {
2795+
const { buffer, mediaType, fileName, size } = media;
27952796

2796-
const fullName = join(
2797-
`${this.instance.id}`,
2798-
messageRaw.key.remoteJid,
2799-
`${messageRaw.key.id}`,
2800-
mediaType,
2801-
fileName,
2802-
);
2797+
const mimetype = mimeTypes.lookup(fileName).toString();
28032798

2804-
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype });
2799+
const fullName = join(
2800+
`${this.instance.id}`,
2801+
messageRaw.key.remoteJid,
2802+
`${messageRaw.key.id}`,
2803+
mediaType,
2804+
fileName,
2805+
);
28052806

2806-
await this.prismaRepository.media.create({
2807-
data: { messageId: msg.id, instanceId: this.instanceId, type: mediaType, fileName: fullName, mimetype },
2808-
});
2807+
await s3Service.uploadFile(fullName, buffer, size.fileLength?.low, { 'Content-Type': mimetype });
2808+
2809+
await this.prismaRepository.media.create({
2810+
data: {
2811+
messageId: msg.id,
2812+
instanceId: this.instanceId,
2813+
type: mediaType,
2814+
fileName: fullName,
2815+
mimetype,
2816+
},
2817+
});
28092818

2810-
const mediaUrl = await s3Service.getObjectUrl(fullName);
2819+
const mediaUrl = await s3Service.getObjectUrl(fullName);
28112820

2812-
messageRaw.message.mediaUrl = mediaUrl;
2821+
messageRaw.message.mediaUrl = mediaUrl;
28132822

2814-
await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw });
2823+
await this.prismaRepository.message.update({ where: { id: msg.id }, data: messageRaw });
2824+
}
2825+
}
28152826
}
28162827
} catch (error) {
28172828
this.logger.error(['Error on upload file to minio', error?.message, error?.stack]);

0 commit comments

Comments
 (0)