From 17dbff00a806ceee2565cb4db9f0959f4de6104d Mon Sep 17 00:00:00 2001 From: Louis Mazin Date: Thu, 16 Apr 2026 01:04:30 +0200 Subject: [PATCH] test --- index.js | 12 +++- src/pterodactyl/displayer.js | 129 ++++++++++++++++++++++++----------- 2 files changed, 100 insertions(+), 41 deletions(-) diff --git a/index.js b/index.js index 37e81df..07ff2e9 100644 --- a/index.js +++ b/index.js @@ -2,9 +2,9 @@ require('dotenv').config(); const fs = require('node:fs'); const path = require('node:path'); const deploy = require('./src/discord/deploy_command.js') -const update = require('./src/pterodactyl/displayer.js'); +const { update, handlePinboardSelection } = require('./src/pterodactyl/displayer.js'); const clean = require('./src/pterodactyl/cleaner.js'); -const { Client, GatewayIntentBits, Collection, Events, Partials, EmbedBuilder } = require('discord.js'); +const { Client, GatewayIntentBits, Collection, Events, Partials } = require('discord.js'); const intents = [GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.GuildMessageReactions]; @@ -55,6 +55,11 @@ client.once('clientReady', async () => { }); client.on(Events.InteractionCreate, async interaction => { + if (interaction.isStringSelectMenu()) { + await handlePinboardSelection(interaction); + return; + } + if (!interaction.isChatInputCommand()) return; // Vรฉrifier que la commande provient du bon serveur @@ -90,4 +95,5 @@ client.on(Events.InteractionCreate, async interaction => { client.login(process.env.DISCORD_TOKEN); -setInterval(() => { update(client); }, 1000); \ No newline at end of file +const displayerIntervalMs = Number(process.env.DISPLAYER_INTERVAL_MS || 120000); +setInterval(() => { update(client); }, displayerIntervalMs); \ No newline at end of file diff --git a/src/pterodactyl/displayer.js b/src/pterodactyl/displayer.js index 6accc7e..0e3df36 100644 --- a/src/pterodactyl/displayer.js +++ b/src/pterodactyl/displayer.js @@ -1,39 +1,44 @@ -const { EmbedBuilder } = require('discord.js'); +const { EmbedBuilder, ActionRowBuilder, StringSelectMenuBuilder } = require('discord.js'); -let pinboardCursor = 0; +const PINBOARD_SELECT_CUSTOM_ID = 'pinboard-image-select'; +const selectedImageIndexByMessage = new Map(); const parsePinboardImageUrls = () => { - const raw = process.env.PINBOARD_IMAGE_URLS; - console.log(`๐Ÿ” URLs brutes du pinboard: ${raw}`); - console.log(raw.split(',')); - return raw.split(',').map(url => url.trim()).filter(url => url.length > 0); + const raw = process.env.PINBOARD_IMAGE_URLS || ''; + return raw + .split(',') + .map(url => url.trim()) + .filter(url => /^https?:\/\//i.test(url)); }; -const selectPinboardWindow = (urls, maxCount) => { - if (urls.length === 0 || maxCount <= 0) { - return []; - } - - const count = Math.min(maxCount, urls.length); - const selected = []; - - for (let i = 0; i < count; i += 1) { - const index = (pinboardCursor + i) % urls.length; - selected.push(urls[index]); - } - - pinboardCursor = (pinboardCursor + count) % urls.length; - return selected; +const clampIndex = (index, length) => { + if (length <= 0) return 0; + if (Number.isNaN(index) || index < 0) return 0; + if (index >= length) return length - 1; + return index; }; -const buildPinboardEmbeds = (urls) => { - const selectedUrls = selectPinboardWindow(urls, 4); - return selectedUrls.map((url, index) => ( - new EmbedBuilder() - .setColor('#f59e0b') - .setTitle(`Pin board ${index + 1}`) - .setImage(url) - )); +const buildSelectedImageEmbed = (url, index, total) => ( + new EmbedBuilder() + .setColor('#f59e0b') + .setTitle(`Image selectionnee (${index + 1}/${total})`) + .setImage(url) +); + +const buildImageSelectorRow = (urls, selectedIndex) => { + const options = urls.slice(0, 25).map((url, index) => ({ + label: `Image ${index + 1}`, + value: String(index), + description: url.length > 95 ? `${url.slice(0, 92)}...` : url, + default: index === selectedIndex + })); + + const selectMenu = new StringSelectMenuBuilder() + .setCustomId(PINBOARD_SELECT_CUSTOM_ID) + .setPlaceholder('Choisis une image') + .addOptions(options); + + return new ActionRowBuilder().addComponents(selectMenu); }; const getMinecraftStatus = async () => { @@ -78,6 +83,27 @@ const buildPanelEmbed = (status) => { return message; }; +const buildPanelPayload = (status, messageId) => { + const panelEmbed = buildPanelEmbed(status); + const pinboardUrls = parsePinboardImageUrls(); + + if (pinboardUrls.length === 0) { + return { content: '', embeds: [panelEmbed], components: [] }; + } + + const currentIndex = clampIndex(selectedImageIndexByMessage.get(messageId) ?? 0, pinboardUrls.length); + selectedImageIndexByMessage.set(messageId, currentIndex); + + const selectedImageEmbed = buildSelectedImageEmbed(pinboardUrls[currentIndex], currentIndex, pinboardUrls.length); + const selectorRow = buildImageSelectorRow(pinboardUrls, currentIndex); + + return { + content: '', + embeds: [panelEmbed, selectedImageEmbed], + components: [selectorRow] + }; +}; + const resolvePanelMessage = async (client, channelId, messageId) => { const channel = await client.channels.fetch(channelId); if (!channel || !channel.isTextBased()) { @@ -114,21 +140,48 @@ const update = async (client) => { } const status = await getMinecraftStatus(); - const panelEmbed = buildPanelEmbed(status); - const pinboardUrls = parsePinboardImageUrls(); - const pinboardEmbeds = buildPinboardEmbeds(pinboardUrls); const { message } = await resolvePanelMessage(client, channelId, messageId); + const payload = buildPanelPayload(status, message.id); - await message.edit({ - content: "", - embeds: [panelEmbed, ...pinboardEmbeds] - }); + await message.edit(payload); - console.log(`๐Ÿ“Š Panneau Minecraft mis a jour (${status.playersOnline}/${status.playersMax}) | Images: ${pinboardEmbeds.length}`); + console.log(`๐Ÿ“Š Panneau Minecraft mis a jour (${status.playersOnline}/${status.playersMax})`); } catch (error) { console.log(`โŒ Erreur displayer: ${error.message}`); } }; -module.exports = update; \ No newline at end of file +const handlePinboardSelection = async (interaction) => { + if (!interaction.isStringSelectMenu() || interaction.customId !== PINBOARD_SELECT_CUSTOM_ID) { + return false; + } + + try { + const pinboardUrls = parsePinboardImageUrls(); + + if (pinboardUrls.length === 0) { + await interaction.reply({ content: 'Aucune image configuree dans PINBOARD_IMAGE_URLS.', ephemeral: true }); + return true; + } + + const selectedRaw = Number.parseInt(interaction.values?.[0] || '0', 10); + const selectedIndex = clampIndex(selectedRaw, pinboardUrls.length); + selectedImageIndexByMessage.set(interaction.message.id, selectedIndex); + + const status = await getMinecraftStatus(); + const payload = buildPanelPayload(status, interaction.message.id); + await interaction.update(payload); + return true; + } catch (error) { + console.log(`โŒ Erreur selection pinboard: ${error.message}`); + if (interaction.replied || interaction.deferred) { + await interaction.followUp({ content: 'Erreur lors de la mise a jour de l image.', ephemeral: true }); + } else { + await interaction.reply({ content: 'Erreur lors de la mise a jour de l image.', ephemeral: true }); + } + return true; + } +}; + +module.exports = { update, handlePinboardSelection }; \ No newline at end of file