feat(album): add album message sending with intelligent retry and adaptive delay

Implements WhatsApp album messages (grouped media) with the following features:

- Send 2-10 images/videos grouped as a single album message
- Adaptive delay between sends based on media type (videos get 2x delay)
- Intelligent retry with exponential backoff for failed items
- parentMessageKey reference to album root (as suggested by maintainer)
- Complete result structure with success/failure tracking per item
- Validation for min (2) and max (10) media items

Types added:
- AlbumMediaItem: Single image/video with caption, mentions, dimensions
- AlbumMessageOptions: Configuration for delay, retry, continueOnFailure
- AlbumMediaResult: Per-item result with latency and retry attempts
- AlbumSendResult: Complete result with albumKey and statistics

Based on PR #2058 from WhiskeySockets/Baileys with improvements.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Renato Alcara
2026-01-23 14:41:19 -03:00
parent 32d8b57605
commit 6e0694e72a
3 changed files with 395 additions and 0 deletions
+39
View File
@@ -477,6 +477,45 @@ export const generateWAMessageContent = async (
m.interactiveMessage = interactiveMessage
options.logger?.warn('[EXPERIMENTAL] Sending carouselMessage - this may not work and can cause bans')
} else if (hasNonNullishProperty(message, 'album')) {
// Album message validation - actual sending is handled in messages-send.ts
const { medias } = message.album
// Validate minimum items (WhatsApp requirement)
if (!medias || medias.length < 2) {
throw new Boom('Album must have at least 2 media items', { statusCode: 400 })
}
// Validate maximum items (WhatsApp limit)
if (medias.length > 10) {
throw new Boom('Album cannot have more than 10 media items (WhatsApp limit)', { statusCode: 400 })
}
// Count and validate each media item
let expectedImageCount = 0
let expectedVideoCount = 0
for (let i = 0; i < medias.length; i++) {
const media = medias[i]
if (hasNonNullishProperty(media, 'image')) {
expectedImageCount++
} else if (hasNonNullishProperty(media, 'video')) {
expectedVideoCount++
} else {
throw new Boom(`Album media at index ${i} must have 'image' or 'video' property`, { statusCode: 400 })
}
}
// Create album root message
m.albumMessage = WAProto.Message.AlbumMessage.create({
expectedImageCount,
expectedVideoCount
})
options.logger?.info(
{ expectedImageCount, expectedVideoCount, totalItems: medias.length },
'Album message validated - sending will be handled by relayMessage'
)
} else if (hasNonNullishProperty(message, 'text')) {
// Normal text message processing
const extContent = { text: message.text } as WATextMessage