feat(whatsapp): optimizar notificacion de aprobacion y rechazo interactivo en WhatsApp

This commit is contained in:
AI Bot 2026-08-24 12:43:27 -05:00
parent 886db53cab
commit 7ff2dd41fb

View File

@ -48,7 +48,13 @@ export async function POST(req: Request) {
// Ignorar mensajes generados por el bot para evitar bucle infinito,
// pero permitir tests que el administrador envíe desde el mismo celular del bot.
if (fromMe && (rawText.includes('📰 *Publicación Procesada') || rawText.includes('✅ La publicación ha sido aprobada') || rawText.includes('❌ Error al publicar'))) {
if (fromMe && (
rawText.includes('SOLICITUD DE APROBACIÓN') ||
rawText.includes('Publicación Procesada') ||
rawText.includes('PUBLICACIÓN APROBADA') ||
rawText.includes('PUBLICACIÓN RECHAZADA') ||
rawText.includes('Error al publicar')
)) {
return NextResponse.json({ success: true, message: 'Ignored bot self-message loop' }, { status: 200 });
}
@ -72,7 +78,7 @@ export async function POST(req: Request) {
console.log(`[WhatsApp Webhook] Chat autorizado detectado: "${filterResult.resolvedName}" (JID: ${remoteJid})`);
// Extraer texto del mensaje (ya guardado en rawText, lo mantenemos como text para retrocompatibilidad interna)
// Extraer texto del mensaje
const text = rawText;
const lowerText = text.trim().toLowerCase();
@ -82,27 +88,71 @@ export async function POST(req: Request) {
const { databases, storage } = await createAdminClient();
// LOGIC 1: APROBAR PUBLICACIÓN
if (isReply && lowerText.includes('aprobar')) {
// Extraer ID de la referencia en el mensaje del bot
const refMatch = quotedText.match(/Ref:\s*([a-zA-Z0-9_-]+)/);
if (refMatch && refMatch[1]) {
const postId = refMatch[1];
// LOGIC 1: RESPUESTA DE APROBACIÓN O RECHAZO
const isApprovalWord = lowerText.includes('aprobar') || lowerText.includes('publicar') || lowerText === 'si' || lowerText === 'sí' || lowerText === 'ok';
const isRejectionWord = lowerText.includes('rechazar') || lowerText.includes('descartar') || lowerText.includes('cancelar') || lowerText === 'no';
if (isApprovalWord || isRejectionWord) {
// Intentar extraer el ID de la referencia en el mensaje citado o en el texto
let postId: string | null = null;
const refMatch = quotedText.match(/Ref:\s*([a-zA-Z0-9_-]+)/) || rawText.match(/Ref:\s*([a-zA-Z0-9_-]+)/);
if (refMatch && refMatch[1]) {
postId = refMatch[1];
} else {
// Fallback: buscar el borrador más reciente
try {
// Actualizar Appwrite
await databases.updateDocument(
const drafts = await databases.listDocuments(
APPWRITE_ALMEIRA_CONFIG.databaseId,
APPWRITE_ALMEIRA_CONFIG.collections.posts,
postId,
{ estado: 'publicado' }
[
Query.equal('estado', 'borrador'),
Query.orderDesc('$createdAt'),
Query.limit(1)
]
);
if (drafts.documents.length > 0) {
postId = drafts.documents[0].$id;
}
} catch (e) {
console.warn('No se pudo consultar el borrador más reciente:', e);
}
}
await sendWhatsAppMessage(remoteJid, `✅ La publicación ha sido aprobada y publicada exitosamente.\n(ID: ${postId})`);
return NextResponse.json({ success: true, message: 'Post aprobado' }, { status: 200 });
if (postId) {
try {
if (isApprovalWord) {
const updatedPost = await databases.updateDocument(
APPWRITE_ALMEIRA_CONFIG.databaseId,
APPWRITE_ALMEIRA_CONFIG.collections.posts,
postId,
{ estado: 'publicado' }
);
const approvalMsg = `✅ *¡PUBLICACIÓN APROBADA Y EN VIVO!*\n\n`
+ `📌 *${updatedPost.titulo}*\n`
+ `🌐 *Ver en el portal:* https://almeira.com.co/${updatedPost.slug}\n\n`
+ `(ID: ${postId})`;
await sendWhatsAppMessage(remoteJid, approvalMsg);
return NextResponse.json({ success: true, message: 'Post aprobado y publicado' }, { status: 200 });
} else if (isRejectionWord) {
await databases.updateDocument(
APPWRITE_ALMEIRA_CONFIG.databaseId,
APPWRITE_ALMEIRA_CONFIG.collections.posts,
postId,
{ estado: 'archivado' }
);
const rejectionMsg = `🚫 *PUBLICACIÓN RECHAZADA*\n\n`
+ `El borrador ha sido descartado y no será publicado en Almeira Web.\n\n`
+ `(ID: ${postId})`;
await sendWhatsAppMessage(remoteJid, rejectionMsg);
return NextResponse.json({ success: true, message: 'Post rechazado y archivado' }, { status: 200 });
}
} catch (e: any) {
console.error("Error approving post:", e);
await sendWhatsAppMessage(remoteJid, `❌ Error al publicar: ${e.message}`);
console.error('Error al actualizar estado del post:', e);
await sendWhatsAppMessage(remoteJid, `❌ Error al procesar tu decisión: ${e.message}`);
return NextResponse.json({ success: false, error: e.message }, { status: 500 });
}
}
@ -244,22 +294,27 @@ export async function POST(req: Request) {
}
);
// Notificar al grupo de WhatsApp pidiendo aprobación
// Notificar al grupo de WhatsApp pidiendo aprobación explícita
let imageNotice = '';
if (candidateMediaList.length > 1) {
const chosenNum = (parsed.selected_image_index ?? 0) + 1;
imageNotice = `*Imagen Destacada:* Foto #${chosenNum} de ${candidateMediaList.length} analizadas`
imageNotice = `🖼️ *Imagen Destacada:* Foto #${chosenNum} de ${candidateMediaList.length} analizadas`
+ (parsed.image_selection_reason ? ` (${parsed.image_selection_reason})\n` : '\n');
} else if (candidateMediaList.length === 1) {
imageNotice = `*Imagen Destacada:* 1 foto procesada (${isSquare ? 'Formato 640x640' : 'Formato 640x360'})\n`;
imageNotice = `🖼️ *Imagen Destacada:* 1 foto procesada (${isSquare ? 'Formato 640x640' : 'Formato 640x360'})\n`;
}
const requestText = `📰 *Publicación Procesada (Pendiente de Aprobación)*\n\n`
+ `*Título:* ${parsed.titulo}\n`
+ `*Tipo:* ${parsed.tipo.toUpperCase()} (${isSquare ? 'Cuadrado 640x640' : 'Panorámico 640x360'})\n`
const requestText = `🔔 *SOLICITUD DE APROBACIÓN DE PUBLICACIÓN* 🔔\n`
+ `_Almeira Web • Asistente Editorial con IA_\n\n`
+ `📌 *Título:* ${parsed.titulo}\n`
+ `📂 *Categoría:* ${parsed.tipo.toUpperCase()} (${isSquare ? 'Cuadrado 640x640' : 'Panorámico 640x360'})\n`
+ (imageNotice ? `${imageNotice}` : '')
+ `*SEO:* ${parsed.seo_descripcion}\n\n`
+ `Para aprobar esta publicación, responde a este mismo mensaje con la palabra "Aprobar".\n\n`
+ `📝 *Resumen:* ${parsed.seo_descripcion}\n\n`
+ `━━━━━━━━━━━━━━━━━━━━━━\n`
+ `¿Autorizas la publicación en el portal?\n\n`
+ `👉 Responde a este mensaje con:\n`
+ `✅ *Aprobar* (para publicar en vivo en la web)\n`
+ `❌ *Rechazar* (para descartar el borrador)\n\n`
+ `(Ref: ${newPost.$id})`;
await sendWhatsAppMessage(remoteJid, requestText);