Add: Timer and Trigger modules with help subcommands
All checks were successful
Auto Build and Push Docker Image / build (push) Successful in 6s

- Add /timer command: add, remove, list, listall, help
- Add /trigger command: add, remove, list, help
- Add /admin help and /owner help subcommands
- Add /twitch help subcommand
- Add ReminderManager for timer notifications
- Add reminders table to database
- Update README.md and AGENTS-BOT.md documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-22 18:53:33 +01:00
parent f78636447b
commit 5c6188ea13
10 changed files with 716 additions and 33 deletions

View File

@@ -0,0 +1,131 @@
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder, MessageFlags } from 'discord.js';
import { Command } from '../../structures/Command.js';
const command: Command = {
data: new SlashCommandBuilder()
.setName('trigger')
.setDescription('Auto-Antworten verwalten.')
.addSubcommand(subcommand =>
subcommand
.setName('add')
.setDescription('Fügt einen neuen Trigger hinzu.')
.addStringOption(option =>
option.setName('trigger')
.setDescription('Das Trigger-Wort')
.setRequired(true))
.addStringOption(option =>
option.setName('antwort')
.setDescription('Die Antwort-Nachricht')
.setRequired(true)))
.addSubcommand(subcommand =>
subcommand
.setName('remove')
.setDescription('Entfernt einen Trigger.')
.addStringOption(option =>
option.setName('trigger')
.setDescription('Das Trigger-Wort')
.setRequired(true)))
.addSubcommand(subcommand =>
subcommand
.setName('list')
.setDescription('Listet alle Trigger auf.'))
.addSubcommand(subcommand =>
subcommand
.setName('help')
.setDescription('Zeigt Hilfe zu den Trigger-Befehlen an.')),
category: 'Admin',
async execute(interaction: any) {
const subcommand = interaction.options.getSubcommand();
const guildId = interaction.guildId;
const isAdmin = interaction.memberPermissions?.has(PermissionFlagsBits.ModerateMembers);
const DB = interaction.client.DB;
if (subcommand === 'help') {
const embed = new EmbedBuilder()
.setTitle('🎯 Trigger Hilfe')
.setColor(0x3498db)
.setDescription('Automatische Antworten auf Trigger-Wörter.')
.addFields(
{ name: '`/trigger add <wort> <antwort>`', value: 'Fügt einen neuen Trigger hinzu (Mod).\nTrigger-Wörter werden automatisch klein geschrieben.', inline: false },
{ name: '`/trigger remove <wort>`', value: 'Entfernt einen Trigger (Mod).', inline: false },
{ name: '`/trigger list`', value: 'Zeigt alle Trigger auf diesem Server an.', inline: false },
{ name: 'Beispiel', value: '`/trigger add hallo Hallo! Wie kann ich helfen?`', inline: false }
)
.setTimestamp();
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
return;
}
if (subcommand === 'list') {
const triggers: any[] = DB.all('SELECT * FROM auto_responses WHERE guild_id = ? ORDER BY trigger_word ASC', guildId);
if (triggers.length === 0) {
await interaction.reply({ content: 'Keine Trigger konfiguriert.', flags: [MessageFlags.Ephemeral] });
return;
}
const embed = new EmbedBuilder()
.setTitle('🎯 Auto-Antworten')
.setColor(0x3498db)
.setTimestamp();
const chunks: string[] = [];
const chunkSize = 10;
for (let i = 0; i < triggers.length; i += chunkSize) {
const chunk = triggers.slice(i, i + chunkSize).map((t: any) =>
`• **${t.trigger_word}** → ${t.response_text}`
).join('\n');
chunks.push(chunk);
}
embed.setDescription(chunks[0]);
await interaction.reply({ embeds: [embed], flags: [MessageFlags.Ephemeral] });
for (let i = 1; i < chunks.length; i++) {
const nextEmbed = new EmbedBuilder()
.setColor(0x3498db)
.setDescription(chunks[i]);
await interaction.followUp({ embeds: [nextEmbed], flags: [MessageFlags.Ephemeral] });
}
return;
}
// Admin only for add/remove
if (!isAdmin) {
await interaction.reply({ content: '❌ Keine Berechtigung. Moderatoren erforderlich.', flags: [MessageFlags.Ephemeral] });
return;
}
if (subcommand === 'add') {
const triggerWord = interaction.options.getString('trigger')!.toLowerCase();
const responseText = interaction.options.getString('antwort')!;
DB.run(
'INSERT INTO auto_responses (guild_id, trigger_word, response_text) VALUES (?, ?, ?) ON CONFLICT(guild_id, trigger_word) DO UPDATE SET response_text = ?',
guildId,
triggerWord,
responseText,
responseText
);
await interaction.reply({ content: `✅ Trigger **${triggerWord}** hinzugefügt/aktualisiert.`, flags: [MessageFlags.Ephemeral] });
return;
}
if (subcommand === 'remove') {
const triggerWord = interaction.options.getString('trigger')!.toLowerCase();
const result = DB.run('DELETE FROM auto_responses WHERE guild_id = ? AND trigger_word = ?', guildId, triggerWord);
if (result.changes === 0) {
await interaction.reply({ content: `❌ Trigger **${triggerWord}** nicht gefunden.`, flags: [MessageFlags.Ephemeral] });
return;
}
await interaction.reply({ content: `✅ Trigger **${triggerWord}** entfernt.`, flags: [MessageFlags.Ephemeral] });
}
},
};
export default command;