Initiales Setup: minimaler Discord-Bot mit /ping, Docker-Deployment und README
- discord.js v14 Bot mit Slash-Command-Registry (Guild oder global) - Konfiguration über .env mit Validierung (config.js) - Dockerfile + docker-compose.yml für Portainer-Deployment - README mit Schritt-für-Schritt-Anleitung (Discord Developer Portal) Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
// Discord-Client: Commands laden, registrieren und Interactions verarbeiten
|
||||
import { Client, Collection, Events, GatewayIntentBits, REST, Routes } from 'discord.js';
|
||||
import { config } from '../config.js';
|
||||
import * as ping from './commands/ping.js';
|
||||
|
||||
// Alle Commands hier eintragen — jedes Modul exportiert { data, execute }
|
||||
const commandModules = [ping];
|
||||
|
||||
export async function startBot() {
|
||||
const client = new Client({
|
||||
intents: [GatewayIntentBits.Guilds],
|
||||
});
|
||||
|
||||
// Commands in Collection ablegen für schnellen Zugriff im Interaction-Handler
|
||||
client.commands = new Collection();
|
||||
for (const command of commandModules) {
|
||||
client.commands.set(command.data.name, command);
|
||||
}
|
||||
|
||||
client.once(Events.ClientReady, async (readyClient) => {
|
||||
console.log(`[bot] Eingeloggt als ${readyClient.user.tag}`);
|
||||
await registerCommands();
|
||||
});
|
||||
|
||||
client.on(Events.InteractionCreate, async (interaction) => {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
const command = client.commands.get(interaction.commandName);
|
||||
if (!command) return;
|
||||
|
||||
try {
|
||||
await command.execute(interaction);
|
||||
} catch (error) {
|
||||
console.error(`[bot] Fehler bei /${interaction.commandName}:`, error);
|
||||
const reply = { content: '❌ Da ist etwas schiefgelaufen.', ephemeral: true };
|
||||
if (interaction.replied || interaction.deferred) {
|
||||
await interaction.followUp(reply).catch(() => {});
|
||||
} else {
|
||||
await interaction.reply(reply).catch(() => {});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
await client.login(config.discordToken);
|
||||
return client;
|
||||
}
|
||||
|
||||
/** Slash-Commands bei Discord registrieren (Guild = sofort sichtbar, global = bis zu 1h Delay) */
|
||||
async function registerCommands() {
|
||||
const rest = new REST().setToken(config.discordToken);
|
||||
const body = commandModules.map((c) => c.data.toJSON());
|
||||
|
||||
const route = config.discordGuildId
|
||||
? Routes.applicationGuildCommands(config.discordClientId, config.discordGuildId)
|
||||
: Routes.applicationCommands(config.discordClientId);
|
||||
|
||||
await rest.put(route, { body });
|
||||
console.log(
|
||||
`[bot] ${body.length} Slash-Command(s) registriert (${config.discordGuildId ? 'Guild' : 'global'})`
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
// Lebenszeichen-Command: /ping → antwortet mit Latenz
|
||||
import { SlashCommandBuilder } from 'discord.js';
|
||||
|
||||
export const data = new SlashCommandBuilder()
|
||||
.setName('ping')
|
||||
.setDescription('Lebenszeichen — zeigt die Bot-Latenz');
|
||||
|
||||
export async function execute(interaction) {
|
||||
const sent = await interaction.reply({ content: '🏓 Pong!', withResponse: true });
|
||||
const latency = sent.resource.message.createdTimestamp - interaction.createdTimestamp;
|
||||
await interaction.editReply(
|
||||
`🏓 Pong! Latenz: **${latency}ms** | API: **${Math.round(interaction.client.ws.ping)}ms**`
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user