Initial: Pixelpöbel Discord Bot
Some checks failed
Auto Build and Push Docker Image / build (push) Failing after 8s
Some checks failed
Auto Build and Push Docker Image / build (push) Failing after 8s
- Modular Discord Bot mit TypeScript und discord.js - Grouped Commands (/admin, /owner subcommands) - SQLite Datenbank mit Persistenz - Twitch Monitoring mit Stream-ID Tracking - Konfigurierbares Warn-System (Auto-Kick/Mute/Ban) - Mute mit verschiedenen Zeiteinheiten (sec, min, hour, day, week, month, year, perm) - Auto-Deploy beim Start (Option 3) - Docker Support Features: - /ping, /help, /twitch (online, add, remove, list) - /admin (kick, warn, unwarn, mute, unmute, ban, unban, config) - /owner (deploy, stats, servers) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
121
src/commands/utility/twitch.ts
Normal file
121
src/commands/utility/twitch.ts
Normal file
@@ -0,0 +1,121 @@
|
||||
import { SlashCommandBuilder, PermissionFlagsBits, EmbedBuilder } from 'discord.js';
|
||||
import { Command } from '../../structures/Command.js';
|
||||
import { TwitchManager } from '../../structures/TwitchManager.js';
|
||||
|
||||
const command: Command = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('twitch')
|
||||
.setDescription('Twitch-Befehle.')
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('online')
|
||||
.setDescription('Prüft, ob ein Kanal online ist.')
|
||||
.addStringOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('Der Name des Twitch-Kanals')
|
||||
.setRequired(true)))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('add')
|
||||
.setDescription('Kanal überwachen (Admin).')
|
||||
.addStringOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('Der Name des Twitch-Kanals')
|
||||
.setRequired(true))
|
||||
.addStringOption(option =>
|
||||
option.setName('message')
|
||||
.setDescription('Optionale Nachricht')))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('remove')
|
||||
.setDescription('Kanal aus Überwachung entfernen (Admin).')
|
||||
.addStringOption(option =>
|
||||
option.setName('channel')
|
||||
.setDescription('Der Name des Twitch-Kanals')
|
||||
.setRequired(true)))
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('list')
|
||||
.setDescription('Listet überwachte Kanäle.')),
|
||||
category: 'Public',
|
||||
async execute(interaction: any) {
|
||||
const subcommand = interaction.options.getSubcommand();
|
||||
const guildId = interaction.guildId;
|
||||
const isAdmin = interaction.memberPermissions?.has(PermissionFlagsBits.Administrator);
|
||||
const DB = interaction.client.DB;
|
||||
|
||||
if (subcommand === 'online') {
|
||||
const channelName = interaction.options.getString('channel')!.toLowerCase();
|
||||
await interaction.deferReply();
|
||||
|
||||
const stream = await TwitchManager.fetchStreamData(channelName);
|
||||
|
||||
if (!stream) {
|
||||
await interaction.editReply(`🔴 Der Kanal **${channelName}** ist offline.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const thumbnailUrl = stream.thumbnail_url
|
||||
.replace('{width}', '1280')
|
||||
.replace('{height}', '720') + `?t=${Date.now()}`;
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`🟢 ${stream.user_name} ist ONLINE!`)
|
||||
.setURL(`https://twitch.tv/${stream.user_login}`)
|
||||
.setColor(0x00FF00)
|
||||
.setImage(thumbnailUrl)
|
||||
.addFields(
|
||||
{ name: 'Titel', value: stream.title || 'Kein Titel', inline: false },
|
||||
{ name: 'Kategorie', value: stream.game_name || 'Unbekannt', inline: true },
|
||||
{ name: 'Zuschauer', value: stream.viewer_count.toString(), inline: true }
|
||||
)
|
||||
.setTimestamp();
|
||||
|
||||
await interaction.editReply({ embeds: [embed] });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'list') {
|
||||
const monitors: any[] = DB.all('SELECT * FROM twitch_monitors WHERE guild_id = ? AND discord_channel_id = ?', guildId, interaction.channelId);
|
||||
if (monitors.length === 0) {
|
||||
await interaction.reply('Keine Twitch-Kanäle überwacht.');
|
||||
return;
|
||||
}
|
||||
|
||||
const list = monitors.map((m: any) => `• **${m.channel_name}**`).join('\n');
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle('📺 Überwachte Twitch-Kanäle')
|
||||
.setColor(0x6441a5)
|
||||
.setDescription(list);
|
||||
|
||||
await interaction.reply({ embeds: [embed] });
|
||||
return;
|
||||
}
|
||||
|
||||
// Admin only
|
||||
if (!isAdmin) {
|
||||
await interaction.reply({ content: '❌ Keine Berechtigung.', ephemeral: true });
|
||||
return;
|
||||
}
|
||||
|
||||
if (subcommand === 'add') {
|
||||
const channelName = interaction.options.getString('channel')!.toLowerCase();
|
||||
const message = interaction.options.getString('message');
|
||||
const discordChannelId = interaction.channelId;
|
||||
|
||||
DB.run(
|
||||
'INSERT INTO twitch_monitors (guild_id, channel_name, discord_channel_id, custom_message) VALUES (?, ?, ?, ?) ON CONFLICT(guild_id, channel_name) DO UPDATE SET discord_channel_id = ?, custom_message = ?',
|
||||
guildId, channelName, discordChannelId, message, discordChannelId, message
|
||||
);
|
||||
await interaction.reply(`✅ Kanal **${channelName}** wird überwacht.`);
|
||||
}
|
||||
|
||||
if (subcommand === 'remove') {
|
||||
const channelName = interaction.options.getString('channel')!.toLowerCase();
|
||||
DB.run('DELETE FROM twitch_monitors WHERE guild_id = ? AND channel_name = ?', guildId, channelName);
|
||||
await interaction.reply(`✅ Kanal **${channelName}** entfernt.`);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
export default command;
|
||||
Reference in New Issue
Block a user