Files
worst-scan-web/src/lib/discord-moderation.ts
T

48 lines
1.8 KiB
TypeScript

import type { Post } from "./db"
// Notificación de CUARENTENA a Discord (webhook de moderación, separado del
// de novedades). El embed trae links de decisión: ✅ Aprobar / 🗑️ Rechazar.
// Al tocar un link se publica (approve) o se borra (reject) el manga.
const MOD_WEBHOOK_URL = process.env.DISCORD_MODERATION_WEBHOOK_URL || ""
const MOD_TOKEN = process.env.DISCORD_MOD_TOKEN || ""
export async function notifyQuarantine(post: Post, reason: string): Promise<boolean> {
if (!MOD_WEBHOOK_URL) return false
const base = `https://worstscan.xyz/api/review/${post.id}?token=${encodeURIComponent(MOD_TOKEN)}`
const approveUrl = `${base}&action=approve`
const rejectUrl = `${base}&action=reject`
const payload = {
content: `🛡️ **Manga en cuarentena** — ${reason}`,
embeds: [
{
title: post.title,
url: `https://worstscan.xyz/api/cover/${post.gid}`,
description: [
`${post.num_pages} páginas${post.artist ? ` por ${post.artist}` : ""}`,
"",
`**¿Qué hacés con este manga?**`,
`✅ [Aprobar y publicar](${approveUrl})`,
`🗑️ [Rechazar y eliminar](${rejectUrl})`,
].join("\n"),
color: 0xef4444, // rojo = requiere atención
thumbnail: { url: `https://worstscan.xyz/api/cover/${post.gid}` },
footer: { text: "worst-scan · revisión de contenido (un click decide)" },
timestamp: new Date().toISOString(),
},
],
}
try {
const res = await fetch(MOD_WEBHOOK_URL, {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(payload),
signal: AbortSignal.timeout(8000),
})
return res.ok
} catch {
return false // nunca romper el poller por un webhook caído
}
}