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
+45
View File
@@ -0,0 +1,45 @@
// /purge — Nachrichten im aktuellen Kanal massenlöschen (max 100, jünger als 14 Tage)
import { SlashCommandBuilder, PermissionFlagsBits, MessageFlags, EmbedBuilder } from 'discord.js';
import { modlogChannelId } from '../../runtime-settings.js';
export const data = new SlashCommandBuilder()
.setName('purge')
.setDescription('Löscht die letzten N Nachrichten in diesem Kanal')
.setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages)
.addIntegerOption((o) =>
o.setName('anzahl').setDescription('Wie viele? (1100)').setRequired(true).setMinValue(1).setMaxValue(100)
);
export async function execute(interaction) {
const count = interaction.options.getInteger('anzahl');
await interaction.deferReply({ flags: MessageFlags.Ephemeral });
let deleted;
try {
// true = Nachrichten >14 Tage still überspringen (Discord-API-Limit)
deleted = await interaction.channel.bulkDelete(count, true);
} catch {
await interaction.editReply('❌ Löschen fehlgeschlagen — Bot braucht „Nachrichten verwalten" hier.');
return;
}
const logChannelId = modlogChannelId();
if (logChannelId && deleted.size > 0) {
const channel = await interaction.client.channels.fetch(logChannelId).catch(() => null);
await channel?.send({
embeds: [
new EmbedBuilder()
.setColor(0xff4d00)
.setTitle('🧹 Purge')
.setDescription(
`**${deleted.size}** Nachrichten in <#${interaction.channelId}> gelöscht von **${interaction.user.username}**`
)
.setTimestamp(),
],
}).catch(() => {});
}
await interaction.editReply(
`🧹 **${deleted.size}** Nachrichten gelöscht.${deleted.size < count ? ' (ältere als 14 Tage kann Discord nicht massenlöschen)' : ''}`
);
}