This commit is contained in:
Louis Mazin 2026-04-16 17:30:09 +02:00
parent abc5b3890f
commit f9d7f48947
2 changed files with 60 additions and 9 deletions

View File

@ -56,9 +56,11 @@ client.once('clientReady', async () => {
}); });
client.on(Events.InteractionCreate, async interaction => { client.on(Events.InteractionCreate, async interaction => {
if (interaction.isStringSelectMenu()) { if (interaction.isStringSelectMenu() || interaction.isButton()) {
await handlePinboardSelection(interaction); const handled = await handlePinboardSelection(interaction);
return; if (handled) {
return;
}
} }
if (!interaction.isChatInputCommand()) return; if (!interaction.isChatInputCommand()) return;

View File

@ -1,8 +1,11 @@
const { EmbedBuilder, ActionRowBuilder, StringSelectMenuBuilder, AttachmentBuilder } = require('discord.js'); const { EmbedBuilder, ActionRowBuilder, StringSelectMenuBuilder, AttachmentBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
const fs = require('node:fs'); const fs = require('node:fs');
const path = require('node:path'); const path = require('node:path');
const PINBOARD_SELECT_CUSTOM_ID = 'pinboard-image-select'; const PINBOARD_SELECT_CUSTOM_ID = 'pinboard-image-select';
const PINBOARD_PREV_CUSTOM_ID = 'pinboard-image-prev';
const PINBOARD_NEXT_CUSTOM_ID = 'pinboard-image-next';
const PINBOARD_INDEX_CUSTOM_ID = 'pinboard-image-index';
const selectedImageIndexByMessage = new Map(); const selectedImageIndexByMessage = new Map();
const preloadedImagesByUrl = new Map(); const preloadedImagesByUrl = new Map();
const warmedMessageIds = new Set(); const warmedMessageIds = new Set();
@ -99,6 +102,12 @@ const clampIndex = (index, length) => {
return index; return index;
}; };
const shiftIndex = (currentIndex, delta, length) => {
if (length <= 0) return 0;
const normalizedCurrent = clampIndex(currentIndex, length);
return (normalizedCurrent + delta + length) % length;
};
const sanitizeAttachmentName = (name) => ( const sanitizeAttachmentName = (name) => (
(name || 'pinboard-image') (name || 'pinboard-image')
.toLowerCase() .toLowerCase()
@ -217,7 +226,7 @@ const buildSelectedImageEmbed = (item, imageReference, options = {}) => {
return new EmbedBuilder() return new EmbedBuilder()
.setColor('#f59e0b') .setColor('#f59e0b')
.setTitle(item.name) .setTitle('Stats du Serveur')
.setImage(imageUrl); .setImage(imageUrl);
}; };
@ -236,6 +245,31 @@ const buildImageSelectorRow = (items, selectedIndex) => {
return new ActionRowBuilder().addComponents(selectMenu); return new ActionRowBuilder().addComponents(selectMenu);
}; };
const buildImageNavigationRow = (items, selectedIndex) => {
const hasItems = items.length > 0;
const indexLabel = hasItems ? `${selectedIndex + 1}/${items.length}` : '0/0';
const previousButton = new ButtonBuilder()
.setCustomId(PINBOARD_PREV_CUSTOM_ID)
.setLabel('<<')
.setStyle(ButtonStyle.Secondary)
.setDisabled(!hasItems);
const indexButton = new ButtonBuilder()
.setCustomId(PINBOARD_INDEX_CUSTOM_ID)
.setLabel(indexLabel)
.setStyle(ButtonStyle.Secondary)
.setDisabled(true);
const nextButton = new ButtonBuilder()
.setCustomId(PINBOARD_NEXT_CUSTOM_ID)
.setLabel('>>')
.setStyle(ButtonStyle.Secondary)
.setDisabled(!hasItems);
return new ActionRowBuilder().addComponents(previousButton, indexButton, nextButton);
};
const getMinecraftStatus = async () => { const getMinecraftStatus = async () => {
const address = process.env.MINECRAFT_SERVER_ADDRESS; const address = process.env.MINECRAFT_SERVER_ADDRESS;
@ -296,6 +330,7 @@ const buildPanelPayload = (status, messageId, pinboardItems = null, options = {}
disableCacheBust: options.disableCacheBustForSelected disableCacheBust: options.disableCacheBustForSelected
}); });
const selectorRow = buildImageSelectorRow(items, currentIndex); const selectorRow = buildImageSelectorRow(items, currentIndex);
const navigationRow = buildImageNavigationRow(items, currentIndex);
const shouldIncludeFiles = options.includeFiles !== false; const shouldIncludeFiles = options.includeFiles !== false;
const files = shouldIncludeFiles && cachedImage?.buffer const files = shouldIncludeFiles && cachedImage?.buffer
@ -305,7 +340,7 @@ const buildPanelPayload = (status, messageId, pinboardItems = null, options = {}
return { return {
content: '', content: '',
embeds: [panelEmbed, selectedImageEmbed], embeds: [panelEmbed, selectedImageEmbed],
components: [selectorRow], components: [selectorRow, navigationRow],
files files
}; };
}; };
@ -372,7 +407,11 @@ const update = async (client) => {
}; };
const handlePinboardSelection = async (interaction) => { const handlePinboardSelection = async (interaction) => {
if (!interaction.isStringSelectMenu() || interaction.customId !== PINBOARD_SELECT_CUSTOM_ID) { const isImageSelect = interaction.isStringSelectMenu() && interaction.customId === PINBOARD_SELECT_CUSTOM_ID;
const isImageNavButton = interaction.isButton()
&& (interaction.customId === PINBOARD_PREV_CUSTOM_ID || interaction.customId === PINBOARD_NEXT_CUSTOM_ID);
if (!isImageSelect && !isImageNavButton) {
return false; return false;
} }
@ -384,8 +423,18 @@ const handlePinboardSelection = async (interaction) => {
return true; return true;
} }
const selectedRaw = Number.parseInt(interaction.values?.[0] || '0', 10); let selectedIndex = clampIndex(selectedImageIndexByMessage.get(interaction.message.id) ?? 0, pinboardItems.length);
const selectedIndex = clampIndex(selectedRaw, pinboardItems.length);
if (isImageSelect) {
const selectedRaw = Number.parseInt(interaction.values?.[0] || '0', 10);
selectedIndex = clampIndex(selectedRaw, pinboardItems.length);
}
if (isImageNavButton) {
const delta = interaction.customId === PINBOARD_PREV_CUSTOM_ID ? -1 : 1;
selectedIndex = shiftIndex(selectedIndex, delta, pinboardItems.length);
}
selectedImageIndexByMessage.set(interaction.message.id, selectedIndex); selectedImageIndexByMessage.set(interaction.message.id, selectedIndex);
const status = lastKnownStatus || await getMinecraftStatus(); const status = lastKnownStatus || await getMinecraftStatus();