const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle, PermissionFlagsBits, ChatInputCommandInteraction } = require('discord.js'); const db = require('../../../db/status'); const ExtendedClient = require('../../../class/ExtendedClient'); const MAX_EMBED_LENGTH = 4096; // Discord maximum embed length const MAX_FIELD_LENGTH = 1024; // Discord maximum field length module.exports = { structure: new SlashCommandBuilder() .setName('setmoderatorstatus') .setDescription('Erstellt ein Embed zur Anzeige des Moderatorstatus.') .setDefaultMemberPermissions(PermissionFlagsBits.Administrator), /** * @param {ExtendedClient} client * @param {ChatInputCommandInteraction} interaction */ run: async (client, interaction) => { const teamRoleIds = { 'Administration': ['827894055685586985'], 'Verifizierung': ['1251156119405985885'], 'Text- und Voicemoderation': ['1251156238645985330'], 'Ticket Team': ['1251156419424555058'], 'Event': ['1251155855618084864'], 'Entwicklung': ['1251155986345889812'], 'Social Media': ['1251155678819651675'] }; const guild = interaction.guild; const allMembers = guild.members.cache; // Mitglieder in verschiedenen Kategorien gruppieren const categorizedMembers = {}; for (const [category, roleIds] of Object.entries(teamRoleIds)) { categorizedMembers[category] = allMembers.filter(member => roleIds.some(roleId => member.roles.cache.has(roleId))); } const allowedRoleIDs = ['827894055685586985', '1251152367567638589']; const allowedMemberIDs = ['580022368924336128', '401387927751491585']; const member = interaction.member; const hasAllowedRoles = member.roles.cache.some(role => allowedRoleIDs.includes(role.id)); const isAllowedMember = allowedMemberIDs.includes(interaction.user.id); if (!hasAllowedRoles && !isAllowedMember) { return interaction.reply({ content: 'Du hast nicht die erforderlichen Rollen oder Berechtigungen, um diesen Befehl auszuführen.', ephemeral: true }); } await interaction.deferReply(); const createEmbed = async (fields, title) => { return new EmbedBuilder() .setTitle(title) .addFields(fields) .setColor('Blurple') .setThumbnail(guild.iconURL({ dynamic: true })); }; const updateEmbeds = async () => { let embeds = []; for (const [category, members] of Object.entries(categorizedMembers)) { if (members.size === 0) continue; // Überspringe leere Kategorien let fields = []; let currentEmbedLength = 0; for (const member of members.values()) { await new Promise((resolve) => { db.get("SELECT status, timestamp FROM statuses WHERE user_id = ?", [member.id], (err, row) => { if (err) { console.error('DB Error:', err); // Fehlerprotokollierung } else { const status = row ? row.status : 'Nicht stören'; const timestamp = row ? new Date(row.timestamp).toLocaleString() : 'N/A'; const memberInfo = `<@${member.id}>:\n**Status:** ${status}\n**Zeit:** ${timestamp}\n\n`; if (currentEmbedLength + memberInfo.length > MAX_EMBED_LENGTH) { embeds.push(createEmbed(fields, `Moderator Status - ${category}`)); fields = []; currentEmbedLength = 0; } if (memberInfo.length > MAX_FIELD_LENGTH) { const chunks = memberInfo.match(/[\s\S]{1,1024}/g) || []; for (const chunk of chunks) { fields.push({ name: category, value: chunk, inline: false }); currentEmbedLength += chunk.length; } } else { fields.push({ name: category, value: memberInfo, inline: false }); currentEmbedLength += memberInfo.length; } } resolve(); }); }); } if (fields.length > 0) { embeds.push(await createEmbed(fields, `Moderator Status - ${category}`)); } } // Erklärungen der Status hinzufügen if (embeds.length > 0) { for (const embed of embeds) { embed.addFields({ name: 'Erklärungen der Status:', value: '**🟩 Anwesend:** Ich bin anwesend und erreichbar.\n' + '**🟥 Nicht stören:** Ich bin anwesend, aber momentan beschäftigt.\n' + '**⬜ Abgemeldet:** Ich bin abgemeldet und nicht erreichbar.', inline: false }); embed.setFooter({ text: 'Die Buttons zum Setzen des Status erscheinen hier.' }); } } else { embeds.push(await createEmbed([], 'Moderator Status').addFields({ name: 'Erklärungen der Status:', value: '**🟩 Anwesend:** Ich bin anwesend und erreichbar.\n' + '**🟥 Nicht stören:** Ich bin anwesend, aber momentan beschäftigt.\n' + '**⬜ Abgemeldet:** Ich bin abgemeldet und nicht erreichbar.', inline: false }).setFooter({ text: 'Die Buttons zum Setzen des Status erscheinen hier.' })); } return embeds; }; const embeds = await updateEmbeds(); const row = new ActionRowBuilder() .addComponents( new ButtonBuilder() .setCustomId('present') .setLabel('Anwesend') .setStyle(ButtonStyle.Success) .setEmoji('🟩'), new ButtonBuilder() .setCustomId('dnd') .setLabel('Nicht stören') .setStyle(ButtonStyle.Danger) .setEmoji('🟥'), new ButtonBuilder() .setCustomId('busy') .setLabel('Abgemeldet') .setStyle(ButtonStyle.Secondary) .setEmoji('⬜') ); const message = await interaction.editReply({ embeds: [embeds[0]], components: [row] }); const filter = i => i.customId === 'present' || i.customId === 'busy' || i.customId === 'dnd'; const collector = message.createMessageComponentCollector({ filter }); collector.on('collect', async i => { if (!i.member.roles.cache.some(role => Object.values(teamRoleIds).flat().includes(role.id))) { return i.reply({ content: 'Du bist nicht berechtigt, diesen Button zu benutzen.', ephemeral: true }); } let status; switch (i.customId) { case 'present': status = 'Anwesend'; break; case 'busy': status = 'Beschäftigt'; break; case 'dnd': status = 'Nicht stören'; break; } const timestamp = Date.now(); db.run("INSERT INTO statuses (user_id, status, timestamp) VALUES (?, ?, ?) ON CONFLICT(user_id) DO UPDATE SET status = ?, timestamp = ?", [i.user.id, status, timestamp, status, timestamp], err => { if (err) { console.error(err); } }); const updatedEmbeds = await updateEmbeds(); if (updatedEmbeds.length > 0) { await i.update({ embeds: [updatedEmbeds[0]], components: [row] }); } }); // Schedule updates every minute setInterval(async () => { const updatedEmbeds = await updateEmbeds(); if (updatedEmbeds.length > 0) { await message.edit({ embeds: [updatedEmbeds[0]] }); } }, 60000); // 60000ms = 1 minute } };