Files
whatsappNucleo/server/services/media/sticker-processor.ts
josedario87 ec40cd6826
All checks were successful
build-and-deploy / build-and-deploy (push) Successful in 2m28s
Unificar endpoint de envío y agregar soporte para stickers
- Consolidar send.post.ts y send-media.post.ts en un único endpoint /send
- Agregar servicio sticker-processor.ts para convertir imágenes a WebP 512x512
- Agregar toggle Imagen/Sticker en MediaPreview para enviar imágenes como stickers
- Actualizar MessageInput y página de mensajes para usar endpoint unificado
- Instalar dependencia sharp para procesamiento de imágenes
2025-12-04 09:33:03 -06:00

96 lines
2.5 KiB
TypeScript

/**
* Sticker Processor Service
* Converts images to WhatsApp-compatible stickers (512x512 WebP)
*/
import sharp from 'sharp'
// WhatsApp sticker requirements
const STICKER_SIZE = 512
const MAX_STICKER_KB = 100 // WhatsApp limit for static stickers
export interface StickerResult {
buffer: Buffer
mimetype: string
}
/**
* Convert an image buffer to a WhatsApp-compatible sticker
* Requirements:
* - WebP format
* - 512x512 pixels (will resize maintaining aspect ratio and add padding)
* - Max 100KB for static stickers
*/
export async function convertToSticker(
inputBuffer: Buffer,
inputMimetype: string
): Promise<StickerResult> {
// Validate input is an image
if (!inputMimetype.startsWith('image/')) {
throw new Error('Input must be an image')
}
// Process with sharp - resize to fit 512x512 with transparent padding
let quality = 100
let buffer = await sharp(inputBuffer)
.resize(STICKER_SIZE, STICKER_SIZE, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 } // Transparent background
})
.webp({ quality, lossless: false })
.toBuffer()
// If too large, reduce quality iteratively
while (buffer.length > MAX_STICKER_KB * 1024 && quality > 10) {
quality -= 10
buffer = await sharp(inputBuffer)
.resize(STICKER_SIZE, STICKER_SIZE, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.webp({ quality, lossless: false })
.toBuffer()
}
// If still too large after quality reduction, try resizing smaller
if (buffer.length > MAX_STICKER_KB * 1024) {
let size = STICKER_SIZE
while (buffer.length > MAX_STICKER_KB * 1024 && size > 128) {
size -= 64
buffer = await sharp(inputBuffer)
.resize(size, size, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.webp({ quality: 80, lossless: false })
.toBuffer()
}
// Resize back to 512x512 for WhatsApp compatibility
if (size < STICKER_SIZE) {
buffer = await sharp(buffer)
.resize(STICKER_SIZE, STICKER_SIZE, {
fit: 'contain',
background: { r: 0, g: 0, b: 0, alpha: 0 }
})
.toBuffer()
}
}
return {
buffer,
mimetype: 'image/webp'
}
}
/**
* Check if an image can be converted to a sticker
*/
export function canConvertToSticker(mimetype: string): boolean {
const supportedTypes = [
'image/jpeg',
'image/png',
'image/webp',
'image/gif' // Will take first frame
]
return supportedTypes.includes(mimetype)
}