Discord巴士报告系统:特定目的地嵌入交互功能优化求助
Solution for Dynamic Bus Report Bot Interaction
Key Improvements Made
- Centralized destination configuration for easy scaling
- Track user selections from both dropdown menus
- Generate dynamic embeds with destination-specific images
- Fixed collector logic to handle menu selections and button clicks correctly
Corrected Full Code
const { SlashCommandBuilder, EmbedBuilder, ButtonBuilder, ActionRowBuilder, SelectMenuBuilder } = require('discord.js'); module.exports = { data: new SlashCommandBuilder() .setName('bus-test') .setDescription('Submit a bus report') .addAttachmentOption(option => option.setName('screenshot').setDescription('Upload a screenshot').setRequired(true)) .addStringOption(option => option.setName('other_drivers').setDescription('Enter all drivers with @').setRequired(true)) .addStringOption(option => option.setName('passengers').setDescription('Enter all passengers with @').setRequired(true)), async execute(interaction) { const author = interaction.user; const drivers = interaction.options.getString('other_drivers'); const passengers = interaction.options.getString('passengers'); const attachment = interaction.options.get('screenshot').value; // Format lists with bullet points const passengersWithDots = passengers.split(' ').map(passenger => `• ${passenger}`).join('\n'); const driversWithDots = drivers.split(' ').map(driver => `• ${driver}`).join('\n'); const driversWithMention = `• ${author}\n${driversWithDots}`; // -------------------------- // Destination Configuration // Add/remove destinations here easily // -------------------------- const destinations = { option_1: { label: 'Option 1', imageUrl: 'https://example.com/option1-bus.png' // Replace with actual image URL }, option_2: { label: 'Option 2', imageUrl: 'https://example.com/option2-bus.png' }, downtown: { label: 'Downtown Terminal', imageUrl: 'https://example.com/downtown-bus.png' }, airport: { label: 'City Airport', imageUrl: 'https://example.com/airport-bus.png' } }; // -------------------------- // Build UI Components // -------------------------- // Destination dropdown menu (populated from config) const destinationmenu = new SelectMenuBuilder() .setCustomId('destination_menu') .setPlaceholder('Select destination') .addOptions( Object.entries(destinations).map(([value, data]) => ({ label: data.label, value: value })) ); // Driver count dropdown menu const drivermenu = new SelectMenuBuilder() .setCustomId('drivernum_menu') .setPlaceholder('Select number of drivers') .addOptions([ { label: '1 driver(s)', value: 'driver_num_1' }, { label: '2 driver(s)', value: 'driver_num_2' }, { label: '3 driver(s)', value: 'driver_num_3' }, { label: '4 driver(s)', value: 'driver_num_4' }, { label: '5 driver(s)', value: 'driver_num_5' }, { label: '6 driver(s)', value: 'driver_num_6' } ]); // Buttons const Preview = new ButtonBuilder() .setCustomId('Preview_button') .setLabel('Preview') .setStyle('Primary'); const Cancel = new ButtonBuilder() .setCustomId('Cancel_button') .setLabel('Cancel') .setStyle('Danger'); // Action rows const row1 = new ActionRowBuilder().addComponents(destinationmenu); const row2 = new ActionRowBuilder().addComponents(drivermenu); const row3 = new ActionRowBuilder().addComponents(Cancel, Preview); // Initial reply const initialEmbed = new EmbedBuilder() .setTitle('**Bus Report Setup**') .setColor('Yellow') .setDescription(`Please select a destination and number of drivers, then click Preview.\n\n**Drivers:**\n${driversWithMention}\n\n**Passengers:**\n${passengersWithDots}`) .setImage(attachment.url); const reply = await interaction.reply({ embeds: [initialEmbed], ephemeral: true, components: [row1, row2, row3], }); // Track user selections let selectedDestination = null; let selectedDriverNum = null; // Component collector const collector = reply.createMessageComponentCollector({ time: 30000 }); collector.on('collect', async (componentInteraction) => { // Only allow the original user to interact if (componentInteraction.user.id !== interaction.user.id) { return componentInteraction.reply({ content: 'This is not your report!', ephemeral: true }); } // Handle destination selection if (componentInteraction.customId === 'destination_menu') { selectedDestination = componentInteraction.values[0]; await componentInteraction.deferUpdate(); } // Handle driver count selection else if (componentInteraction.customId === 'drivernum_menu') { selectedDriverNum = componentInteraction.values[0]; await componentInteraction.deferUpdate(); } // Handle Preview button click else if (componentInteraction.customId === 'Preview_button') { // Validate selections if (!selectedDestination || !selectedDriverNum) { return componentInteraction.reply({ content: 'Please select both a destination and number of drivers first!', ephemeral: true }); } // Get destination data and driver label const destData = destinations[selectedDestination]; const driverLabel = drivermenu.options.find(opt => opt.value === selectedDriverNum).label; // Build preview embed const previewEmbed = new EmbedBuilder() .setTitle(`Bus Report: ${destData.label}`) .setColor('Green') .setDescription(` Selected Destination: ${destData.label} Selected Driver(s): ${driverLabel} **Drivers:** ${driversWithMention} **Passengers:** ${passengersWithDots} `) .setImage(destData.imageUrl) .setFooter({ text: `Submitted by ${author.tag}`, iconURL: author.displayAvatarURL() }); // Update message with preview await componentInteraction.update({ embeds: [previewEmbed], components: [] }); collector.stop(); } // Handle Cancel button click else if (componentInteraction.customId === 'Cancel_button') { await componentInteraction.update({ content: 'Report canceled.', embeds: [], components: [] }); collector.stop(); } }); collector.on('end', async () => { if (!reply.deleted) { await reply.edit({ content: 'This report is no longer active.', embeds: [], components: [] }); } }); }, };
Usage Notes
- Add New Destinations: Simply add new entries to the
destinationsobject with a unique value, display label, and image URL. The dropdown menu will auto-populate these options. - Replace Image URLs: Update the
imageUrlfields in the destinations config with your actual bus destination images. - Validation: The bot now checks that both a destination and driver count are selected before generating the preview.
- User Restriction: Only the original command user can interact with the menus/buttons to prevent unwanted changes.
内容的提问来源于stack exchange,提问作者Abdalrahma
相关产品推荐
相关产品推荐

