Discord.js v13 REST API 猫和城市问题指南

Discord.js v13 REST API Guide Cat and Urban Issues

所以我在自己制作之前尝试遵循 https://discordjs.guide/additional-info/rest-api.html 指南。但我无法工作。

首先用 /cat 崩溃,控制台 returns 有:

SyntaxError: Unexpected end of JSON input
at JSON.parse (<anonymous>)
at getJSONResponse (BOTLOCATION\index.js:77:14)
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Client.<anonymous> (BOTLOCATION\index.js:90:20)

并且 /urban 有效,但无论我输入什么术语 returns 和 NULL。

这是代码,除了添加的 SlashCommandBuilder 和 REST 之外,它与指南几乎相同。

const { request } = require('undici');


const clientId = 'CLIENTID_HERE';
const guildId = 'GUILDID_HERE';

const { SlashCommandBuilder } = require('@discordjs/builders');
const { REST } = require('@discordjs/rest');
const { Routes } = require('discord-api-types/v9');


const commands = [
    new SlashCommandBuilder().setName('cat').setDescription('Cat thing idk'),
    new SlashCommandBuilder().setName('urban').setDescription('Urban Dictionary Thing'),
]
    .map(command => command.toJSON());

const rest = new REST({ version: '9' }).setToken("TOKEN_HERE");

rest.put(Routes.applicationGuildCommands(clientId, guildId), { body: commands })
//rest.put(Routes.applicationGuildCommands(clientId), { body: commands })
    .then(() => console.log('Successfully registered application commands.'))
    .catch(console.error);


const trim = (str, max) => (str.length > max ? `${str.slice(0, max - 3)}...` : str);

async function getJSONResponse(body) {
    let fullBody = '';

    for await (const data of body) {
        fullBody += data.toString();
    }

    return JSON.parse(fullBody);
}



client.on('interactionCreate', async interaction => {
    if (!interaction.isCommand()) return;

    const { commandName } = interaction;
    await interaction.deferReply();

    if (commandName === 'cat') {
        const catResult = await request('https://aws.random.cat/meow');
        const { file } = await getJSONResponse(catResult.body);
    
        interaction.reply({ files: [{ attachment: file, name: 'cat.png' }] });

    } else if (commandName === 'urban') {
        const term = interaction.options.getString('term');
        const query = new URLSearchParams({ term });

        const dictResult = await request(`https://api.urbandictionary.com/v0/define?${query}`);
        const { list } = await getJSONResponse(dictResult.body);

        if (!list.length) {
            return interaction.editReply(`No results found for **${term}**.`);
        }

        const [answer] = list;

        const embed = new MessageEmbed()
            .setColor('#EFFF00')
            .setTitle(answer.word)
            .setURL(answer.permalink)
            .addFields(
                { name: 'Definition', value: trim(answer.definition, 1024) },
                { name: 'Example', value: trim(answer.example, 1024) },
                {
                    name: 'Rating',
                    value: `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`,
                },
            );
        interaction.editReply({ embeds: [embed] });
    }
});

所以对于 cat 命令,因为有一个 deferReply first we need to use editReply 因为 deferReply 算作 first/initial 回复。

await interaction.deferReply();

const catResult = await request('https://aws.random.cat/meow').catch((err) => { console.log(err); });;
const { file } = await getJSONResponse(catResult.body).catch((err) => { console.log(err); });

return await interaction.editReply({ files: [{ attachment: file, name: 'cat.png' }] });

我还在每个 await 的末尾添加了一个 .catch,这只是为了测试,但我推荐它。

现在使用 urban 命令,它使用 null 的原因是因为您没有字符串选项的文本。我们可以通过添加 if statement.

来检查它
await interaction.deferReply();

const term = interaction.options.getString('term');
if (!term) return await interaction.editReply('Please provide a term.'); // We need to add this check to see if the user provided the term option or not.
const query = new URLSearchParams({ term });

const dictResult = await request(`https://api.urbandictionary.com/v0/define?${query}`);
const { list } = await getJSONResponse(dictResult.body);

if (!list.length) {
    return interaction.editReply(`No results found for **${term}**.`);
}

const [answer] = list;

const embed = new MessageEmbed()
    .setColor('#EFFF00')
    .setTitle(answer.word)
    .setURL(answer.permalink)
    .addFields(
        { name: 'Definition', value: trim(answer.definition, 1024) },
        { name: 'Example', value: trim(answer.example, 1024) },
        {
            name: 'Rating',
            value: `${answer.thumbs_up} thumbs up. ${answer.thumbs_down} thumbs down.`,
        },
    );

return await interaction.editReply({ embeds: [embed] });

重要提示: 当您构建斜杠命令时,您没有设置字符串选项。在 commands 数组中,当创建第二个名为 urban 的斜杠命令时,我们将在其中添加对字符串选项的支持。 (An example using the string option, discord.js guide all command options)

我们可以这样做:

const commands = [
  new SlashCommandBuilder().setName('cat')
    .setDescription('Cat thing idk'),
  new SlashCommandBuilder()
    .setName('urban')
    .setDescription('Urban Dictionary Thing')
    .addStringOption((option) => option.setName('term').setDescription('term')) // We first add the string option then set the name to 'term' which is what the code calls for and then the description.
].map((command) => command.toJSON());

如果你想使术语输入成为必填项,请添加 .setRequired(true) 这将不允许在不输入要搜索的术语的情况下命令为 运行。

一旦你这样做了,你应该一切都好!测试了代码,一旦修复它就可以工作了