Carl-Bot-Paket: Moderation, Auto-/Sticky-Roles, Level-System, Tags, geplante Posts

- Moderation: /warn (DM + Mod-Log), /warns (Historie + löschen), /timeout (max 28d),
  /purge (bulk, 14-Tage-Limit sauber gemeldet); Mod-Log erweitert um Join/Leave
  und Nick-/Rollen-Änderungen
- Auto-Rolle bei Join + Sticky-Roles (Rollen bei Leave gesichert, bei Rejoin
  wiederhergestellt; managed/@everyone ausgenommen) — Rollen-Tab
- Level-System (opt-in): 15-25 XP/Nachricht mit 60s-Cooldown, MEE6-Formel,
  Level-Up-Announce, Rollen-Belohnungen (Level=RolleID), /rank mit Fortschritt,
  öffentliche Bestenliste /level; Community-Tab
- Tags: /tag mit Autocomplete, Verwaltung im Composer-Tab (/api/tags)
- Geplante Posts: einmalig/täglich/wöchentlich, Minuten-Scheduler, DST-sicher
  über Neuberechnung aus Zeitfeldern; Composer-Tab (/api/scheduled)
- Autocomplete-Dispatch im InteractionCreate; alles smoke-getestet

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 00:30:23 +02:00
co-authored by Claude Fable 5
parent a27a594a07
commit db9c7d07c9
19 changed files with 1066 additions and 5 deletions
+44
View File
@@ -0,0 +1,44 @@
// /warns — Verwarnungs-Historie eines Members einsehen / Eintrag löschen (Moderatoren)
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, EmbedBuilder } from 'discord.js';
import { warnsOf, deleteWarn } from '../../db.js';
export const data = new SlashCommandBuilder()
.setName('warns')
.setDescription('Verwarnungen eines Members anzeigen (oder eine löschen)')
.setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers)
.addUserOption((o) => o.setName('member').setDescription('Wessen Verwarnungen?').setRequired(true))
.addIntegerOption((o) => o.setName('loeschen').setDescription('Optional: Verwarnungs-ID entfernen'));
export async function execute(interaction) {
const user = interaction.options.getUser('member');
const removeId = interaction.options.getInteger('loeschen');
if (removeId) {
const removed = deleteWarn(removeId);
await interaction.reply({
content: removed ? `🗑️ Verwarnung #${removeId} entfernt.` : `❌ Verwarnung #${removeId} nicht gefunden.`,
flags: MessageFlags.Ephemeral,
});
return;
}
const warns = warnsOf(user.id);
if (warns.length === 0) {
await interaction.reply({ content: `✅ **${user.username}** hat keine Verwarnungen.`, flags: MessageFlags.Ephemeral });
return;
}
const lines = warns
.slice(-15)
.map((w) => `\`#${w.id}\` ${w.created_at.slice(0, 10)}${w.reason} *(${w.moderator ?? '—'})*`);
await interaction.reply({
embeds: [
new EmbedBuilder()
.setColor(0xf5c518)
.setTitle(`⚠️ Verwarnungen: ${user.username} (${warns.length})`)
.setDescription(lines.join('\n'))
.setFooter({ text: 'Löschen: /warns member:<user> loeschen:<ID>' }),
],
flags: MessageFlags.Ephemeral,
});
}