Devlog-Löschung: Discord-Delete-Sync + Admin-Button im Webinterface

- MessageDelete-Listener (mit Partials): in Discord gelöschte Devlogs verschwinden
  automatisch aus dem Archiv, inkl. lokaler Bilder
- DELETE /api/devlogs/:id (nur Admin) + ✕-Button auf den Karten (nur für Admin sichtbar)
- Anlass: Test-Post mit Commit-Liste von vor der Prosa-Sperre stand noch im Archiv

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-23 01:16:44 +02:00
co-authored by Claude Opus 4.8
parent bf0eca3546
commit 71d2bb07f1
8 changed files with 97 additions and 12 deletions
+16 -2
View File
@@ -1,7 +1,7 @@
// Discord-Client: Commands laden, registrieren und Interactions verarbeiten
import { Client, Collection, Events, GatewayIntentBits, REST, Routes } from 'discord.js';
import { Client, Collection, Events, GatewayIntentBits, Partials, REST, Routes } from 'discord.js';
import { config } from '../config.js';
import { archiveDevlogMessage } from './devlog-archive.js';
import { archiveDevlogMessage, removeDevlog } from './devlog-archive.js';
import * as ping from './commands/ping.js';
import * as devlogBackfill from './commands/devlog-backfill.js';
@@ -17,6 +17,8 @@ export async function startBot() {
GatewayIntentBits.GuildMessages,
GatewayIntentBits.MessageContent,
],
// Partials, damit MessageDelete auch für ungecachte (ältere) Nachrichten feuert
partials: [Partials.Message],
});
// Commands in Collection ablegen für schnellen Zugriff im Interaction-Handler
@@ -42,6 +44,18 @@ export async function startBot() {
}
});
// In Discord gelöscht = im Archiv gelöscht (inkl. lokaler Bilder)
client.on(Events.MessageDelete, async (message) => {
if (message.channelId !== config.devlogChannelId) return;
try {
if (await removeDevlog(message.id)) {
console.log(`[devlog] Archiv-Eintrag entfernt (Discord-Nachricht ${message.id} gelöscht)`);
}
} catch (error) {
console.error('[devlog] Archiv-Löschung fehlgeschlagen:', error);
}
});
client.on(Events.InteractionCreate, async (interaction) => {
if (!interaction.isChatInputCommand()) return;
+14 -2
View File
@@ -3,9 +3,9 @@
// Webserver unter /devlog-assets/ ausgeliefert.
// Wird vom Live-Listener (MessageCreate) und vom /devlog-backfill-Command genutzt.
import { mkdirSync } from 'node:fs';
import { writeFile } from 'node:fs/promises';
import { writeFile, rm } from 'node:fs/promises';
import { join, dirname, resolve } from 'node:path';
import { saveDevlog, hasDevlog } from '../db.js';
import { saveDevlog, hasDevlog, deleteDevlog } from '../db.js';
import { config } from '../config.js';
const MAX_IMAGES = 4;
@@ -49,6 +49,18 @@ async function downloadImages(message) {
return files;
}
/**
* Devlog aus dem Archiv entfernen (inkl. lokal gespeicherter Bilder).
* @returns {Promise<boolean>} true, wenn ein Eintrag gelöscht wurde
*/
export async function removeDevlog(messageId) {
const { deleted, images } = deleteDevlog(messageId);
for (const file of images) {
await rm(join(imagesDir, file), { force: true });
}
return deleted;
}
/**
* Nachricht archivieren, falls sie ein Devlog ist (Webhook-/Bot-Post mit Text).
* @param {import('discord.js').Message} message