feat: moderacion lolicon - cuarentena + decision desde Discord (webhook links aprobar/rechazar)

This commit is contained in:
Renato
2026-08-05 03:14:53 +08:00
parent 702c6a5781
commit cebb026564
11 changed files with 378 additions and 16 deletions
+48
View File
@@ -0,0 +1,48 @@
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
}
}