无论我尝试什么,我都无法显示子命令。它只是显示这个
有趣的命令 /fun:有趣的命令!
今天13:07
示例 fun.js
我尝试在互联网上搜索,询问 chapgtp 等等。尝试查看文档但仍然一无所获。
我尝试更新这两个文件以使其正常工作,没有任何错误,只是 help.js 无法调用甚至无法查看子命令。
这是我每次得到的输出 https://prnt.sc/weeO16P8DIDE
const { SlashCommandBuilder } = require('@discordjs/builders');
const { EmbedBuilder } = require('discord.js');
const axios = require('axios');
const he = require('he'); // Importing the 'he' library for HTML decoding
module.exports = {
data: new SlashCommandBuilder()
.setName('fun')
.setDescription('Fun commands to play with!')
.addSubcommand(subcommands =>
subcommands
.setName('8ball')
.setDescription('Ask the magic 8-ball a question.')
.addStringOption(option => option.setName('question').setDescription('Your yes/no question').setRequired(true)))
.addSubcommand(subcommands =>
subcommands
.setName('av')
.setDescription('Displays the avatar of the specified user.')
.addUserOption(option =>
option.setName('user')
.setDescription('The user whose avatar to display')
.setRequired(false)))
.addSubcommand(subcommand =>
subcommand
.setName('coinflip')
.setDescription('Flip a coin and get heads or tails.'))
.addSubcommand(subcommand =>
subcommand
.setName('fact')
.setDescription('Provides a random interesting fact using an API.'))
.addSubcommand(subcommand =>
subcommand
.setName('joke')
.setDescription('Fetch a random joke.'))
.addSubcommand(subcommand =>
subcommand
.setName('meme')
.setDescription('Fetch a random meme from Reddit.'))
.addSubcommand(subcommand =>
subcommand
.setName('roll')
.setDescription('Rolls a six-sided die.'))
.addSubcommand(subcommand =>
subcommand
.setName('trivia')
.setDescription('Start a trivia game.')),
category: 'fun',
async execute(interaction) {
const subcommand = interaction.options.getSubcommand();
switch (subcommand) {
case '8ball':
const answers = ['Yes', 'No', 'Maybe', 'Definitely', 'Ask again later'];
const randomAnswer = answers[Math.floor(Math.random() * answers.length)];
await interaction.reply(randomAnswer);
break;
case 'av':
await interaction.deferReply();
const user = interaction.options.getUser('user') || interaction.user;
const avatarEmbed = new EmbedBuilder()
.setTitle(`${user.username}'s avatar`)
.setColor(0x333333)
.setImage(user.displayAvatarURL({ dynamic: true, size: 2048 }));
await interaction.followUp({ embeds: [avatarEmbed] });
break;
case 'coinflip':
const result = Math.random() < 0.5 ? 'Heads' : 'Tails';
await interaction.reply(`The coin landed on: ${result}`);
break;
case 'fact':
await interaction.deferReply();
try {
const factResponse = await axios.get('https://uselessfacts.jsph.pl/random.json');
const fact = factResponse.data.text;
const factEmbed = new EmbedBuilder()
.setTitle('🔍 Random Fact')
.setColor(0x333333)
.setDescription(fact);
await interaction.followUp({ embeds: [factEmbed] });
} catch (error) {
console.error(error);
await interaction.followUp({ content: 'Sorry, I couldn\'t fetch a fact at the moment.' });
}
break;
case 'joke':
try {
const jokeResponse = await axios.get('https://official-joke-api.appspot.com/random_joke');
await interaction.reply(`${jokeResponse.data.setup} - ${jokeResponse.data.punchline}`);
} catch (error) {
await interaction.reply('Error fetching joke.');
}
break;
case 'meme':
try {
const memeResponse = await axios.get('https://meme-api.com/gimme'); // Replace with actual meme API
await interaction.reply({ content: memeResponse.data.url });
} catch (error) {
await interaction.reply('Error fetching meme.');
}
break;
case 'roll':
await interaction.deferReply();
const roll = Math.floor(Math.random() * 6) + 1;
const rollEmbed = new EmbedBuilder()
.setTitle('🎲 You rolled!')
.setColor(0x333333)
.setDescription(`You rolled a **${roll}**.`);
await interaction.followUp({ embeds: [rollEmbed] });
break;
case 'trivia':
try {
const triviaResponse = await axios.get('https://opentdb.com/api.php?amount=1&type=multiple');
const question = he.decode(triviaResponse.data.results[0].question);
const correctAnswer = he.decode(triviaResponse.data.results[0].correct_answer);
const incorrectAnswers = triviaResponse.data.results[0].incorrect_answers.map(he.decode);
const answers = [correctAnswer, ...incorrectAnswers].sort(() => Math.random() - 0.5);
const answersString = answers.map((answer, index) => `${index + 1}. ${answer}`).join('\n');
await interaction.reply(`Trivia: ${question}\n\nOptions:\n${answersString}`);
const filter = response => {
return !isNaN(response.content) && response.author.id === interaction.user.id && response.content > 0 && response.content <= answers.length;
};
const collector = interaction.channel.createMessageCollector({ filter, time: 15000 });
collector.on('collect', m => {
const answerIndex = parseInt(m.content) - 1;
const userAnswer = answers[answerIndex];
const correctAnswerIndex = answers.indexOf(correctAnswer);
if (userAnswer === answers[correctAnswerIndex]) {
interaction.followUp(`Correct! 🎉 The answer is: ${correctAnswer}`);
} else {
interaction.followUp(`Wrong answer! The correct answer was: ${correctAnswer}`);
}
collector.stop();
});
collector.on('end', collected => {
if (collected.size === 0) {
interaction.followUp('Time is up! No one answered.');
}
});
} catch (error) {
console.error('Error fetching trivia:', error);
await interaction.reply('Error fetching trivia. Please try again later.');
}
break;
}
},
};
#help.js
const { SlashCommandBuilder } = require('@discordjs/builders');
module.exports = {
data: new SlashCommandBuilder()
.setName('help')
.setDescription('Displays a list of available commands or information about a specific command.')
.addStringOption(option =>
option.setName('command')
.setDescription('The command you want help with')),
category: 'utility',
async execute(interaction) {
const { commands } = interaction.client;
// Define categorizedCommands, including the game category
const categorizedCommands = {
fun: [],
moderation: [],
utility: [],
roleManagement: [],
music: [],
game: [],
chatbot: [],
giveaway: [],
};
// Categorize commands
commands.forEach(command => {
if (command.category && categorizedCommands[command.category]) {
categorizedCommands[command.category].push(command);
} else {
console.warn(`Command ${command.data.name} is missing a valid category or category does not exist.`);
}
});
const commandName = interaction.options.getString('command');
if (!commandName) {
const categories = Object.keys(categorizedCommands);
// Create the initial embed
const helpEmbed = new EmbedBuilder()
.setColor('#5865F2') // Discord's blurple color
.setTitle('📜 Command List')
.setDescription('Select a category to view its commands:')
.setThumbnail(interaction.client.user.displayAvatarURL())
.setTimestamp(); // Adds a timestamp at the bottom
// Function to update the embed with the current category
const updateEmbed = (category) => {
const commandList = categorizedCommands[category]
.map(command => {
// Prepare the command and subcommand display
let commandDisplay = `**/${command.data.name}**: ${command.data.description}`;
// Check if the command has subcommands
if (command.data.options && command.data.options.length > 0) {
const subcommandsDisplay = command.data.options
.filter(option => option.type === 1) // Subcommand type
.map(subcommand => ` - **/${command.data.name} ${subcommand.name}**: ${subcommand.description}`)
.join('\n');
commandDisplay += `\n${subcommandsDisplay}`; // Append subcommands to command
return commandDisplay;}
})
.join('\n') || 'No commands available.';
helpEmbed.setTitle(`📋 Commands in ${category.charAt(0).toUpperCase() + category.slice(1)}`)
.setDescription(commandList);
};
// Set the initial category to the first one
const initialCategory = categories[0];
updateEmbed(initialCategory); // Update for the initial category
// Create a select menu for categories
const selectMenu = new StringSelectMenuBuilder()
.setCustomId('categorySelect')
.setPlaceholder('Select a category')
.addOptions(
categories.slice(0, 25).map(category => ({ // Limit to 25 options for safety
label: category.charAt(0).toUpperCase() + category.slice(1),
value: category,
}))
);
const row = new ActionRowBuilder().addComponents(selectMenu);
const message = await interaction.reply({ embeds: [helpEmbed], components: [row], fetchReply: true });
// Create a message component collector for select interactions
const collector = message.createMessageComponentCollector({ time: 60000 });
collector.on('collect', async i => {
// Check if the select menu is used
if (i.customId === 'categorySelect') {
updateEmbed(i.values[0]); // Update the embed for the selected category
await i.update({ embeds: [helpEmbed] }); // Update the message with the new embed
}
});
collector.on('end', () => {
message.edit({ components: [] }); // Remove the select menu after the collector ends
});
} else {
const command = commands.get(commandName.toLowerCase());
if (!command) {
return interaction.reply("❌ That's not a valid command!");
}
// Create the embed for a specific command
const helpEmbed = new EmbedBuilder()
.setColor('#5865F2')
.setTitle(`❓ Help: /${command.data.name}`)
.setDescription(`**Description**: ${command.data.description}`)
.setThumbnail(interaction.client.user.displayAvatarURL());
if (command.data.aliases) {
helpEmbed.addFields({ name: '🔀 Aliases', value: command.data.aliases.join(', ') });
}
if (command.data.example) {
helpEmbed.addFields({ name: '💡 Example', value: `\`${command.data.example}\`` });
}
if (command.data.options && command.data.options.length > 0) {
const subcommandsList = command.data.options
.filter(option => option.type === 1) // type 1 indicates a subcommand
.map(subcommand => `**/${command.data.name} ${subcommand.name}**: ${subcommand.description}`)
.join('\n') || 'No subcommands available.';
helpEmbed.addFields({ name: '📜 Subcommands', value: subcommandsList });
}
return interaction.reply({ embeds: [helpEmbed] });
}
},
};```
I have tried directly calling the subcommands then tried calling option type 1 as shown above, but still the output is
[![help command output](https://i.sstatic.net/LIJUZSdr.png)](https://i.sstatic.net/LIJUZSdr.png)
[1]: https://i.sstatic.net/fdJc16ta.png
以下代码返回命令的选项,如果选项是子命令,则返回子命令及其下选项的名称和描述,如果选项不是子命令,则返回名称、类型和描述的选项。
console.log(
interaction.client.commands.get("help")
?.data.options.map((option) =>
option instanceof SlashCommandSubcommandBuilder
? {
name: option.name,
description: option.description,
subcommandsOptions: option.options.map((subcommandoption) => ({
name: subcommandoption.name,
type: subcommandoption.type,
description: subcommandoption.description,
})),
}
: { name: option.name, description: option.description }
)
);