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 => {
if (interaction.isStringSelectMenu()) {
await handlePinboardSelection(interaction);
return;
if (interaction.isStringSelectMenu() || interaction.isButton()) {
const handled = await handlePinboardSelection(interaction);
if (handled) {
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 path = require('node:path');
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 preloadedImagesByUrl = new Map();
const warmedMessageIds = new Set();
@ -99,6 +102,12 @@ const clampIndex = (index, length) => {
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) => (
(name || 'pinboard-image')
.toLowerCase()
@ -217,7 +226,7 @@ const buildSelectedImageEmbed = (item, imageReference, options = {}) => {
return new EmbedBuilder()
.setColor('#f59e0b')
.setTitle(item.name)
.setTitle('Stats du Serveur')
.setImage(imageUrl);
};
@ -236,6 +245,31 @@ const buildImageSelectorRow = (items, selectedIndex) => {
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 address = process.env.MINECRAFT_SERVER_ADDRESS;
@ -296,6 +330,7 @@ const buildPanelPayload = (status, messageId, pinboardItems = null, options = {}
disableCacheBust: options.disableCacheBustForSelected
});
const selectorRow = buildImageSelectorRow(items, currentIndex);
const navigationRow = buildImageNavigationRow(items, currentIndex);
const shouldIncludeFiles = options.includeFiles !== false;
const files = shouldIncludeFiles && cachedImage?.buffer
@ -305,7 +340,7 @@ const buildPanelPayload = (status, messageId, pinboardItems = null, options = {}
return {
content: '',
embeds: [panelEmbed, selectedImageEmbed],
components: [selectorRow],
components: [selectorRow, navigationRow],
files
};
};
@ -372,7 +407,11 @@ const update = async (client) => {
};
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;
}
@ -384,8 +423,18 @@ const handlePinboardSelection = async (interaction) => {
return true;
}
const selectedRaw = Number.parseInt(interaction.values?.[0] || '0', 10);
const selectedIndex = clampIndex(selectedRaw, pinboardItems.length);
let selectedIndex = clampIndex(selectedImageIndexByMessage.get(interaction.message.id) ?? 0, 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);
const status = lastKnownStatus || await getMinecraftStatus();