开发者问题收集

使用 REST API 实现 Discord 机器人

2022-07-09
2475

我正在尝试制作自己的 discord 机器人(在 discord.js v13 中)。我找到了有关此主题的官方 discord.js 指南 他们的示例代码 ,并且我正在尝试使用/重用那里的代码来构建我自己的机器人。

这个想法是在斜杠命令 “item” 之后获取用户输入(因此 /item:firebrand ),将该用户输入传递到URL(这允许您从后端/API获取有关该项目的信息)并使用收到的响应来填充嵌入的各个字段,这些字段被发送回用户。

我能够传递用户输入并将其添加到 URL,从而返回可用的链接,但在创建嵌入之前代码会中断。我在代码中输入了一些 console.log 命令,以查看哪里出了问题。

在下面的代码中查看 console.log 的位置。

  • 控制台日志 1: {"items":[{"id":14,"name":"Frost Brand","type":"1-h wpn","constlevel":4,"mainlevel":1,"mpath":"W1","gemcost":"5W","screenshot":"/items/14/screenshot"}],"similarity":-0
  • 控制台日志 2: https://dom5api.illwiki.com/items?match=fuzzy&name=frostbrand
  • 控制台日志 3: [object Object]
  • 控制台日志 4: [object Object]
  • 控制台日志 5: undefined - TypeError:无法读取未定义的属性(读取“length”)

我猜我之所以收到 TypeError 是因为 { list } 为 undefined 。这可能是因为 itemSearchResult.body 返回了 [object Object] 作为响应,但我不知道如何修复它。

const { SlashCommandBuilder } = require('@discordjs/builders');
const { MessageEmbed } = require('discord.js');
const { request } = require('undici');
const { ITEM_URL, BASE_URL } = require('../utils/utils');

module.exports = {
    data: new SlashCommandBuilder()
        .setName('item')
        .setDescription('Replies with information about an item')
        .addStringOption(option => option.setName('item_name').setDescription('Enter the name of the item')),
    async execute(interaction) {
        async function getJSONResponse(body) {
            let fullBody = '';
            for await (const data of body) {
                fullBody += data.toString();
                console.log(`Console log 1: `+fullBody);
            }
            return JSON.parse(fullBody);
        }
        const itemName = interaction.options.getString('item_name');
        
        const itemSearchResult = await request(ITEM_URL + encodeURIComponent(itemName));
        console.log(`Console log 2: `+ITEM_URL + encodeURIComponent(itemName)); 
        console.log(`Console log 3: `+itemSearchResult.body);
        console.log(`Console log 4: `+itemSearchResult.body.toString())
        const { list } = await getJSONResponse(itemSearchResult.body);
        console.log(`Console log 5: `+list)

        if (!list.length) {
            await interaction.reply(`No results found for **${itemName}**.`);
        }

        const [answer] = list;
        
        const itemEmbed = new MessageEmbed()
            .setColor('#000000')
            .setTitle(answer.name)
            .setURL('X')
            .setAuthor({ name: 'Author' })
            .setDescription('Lot of hassle, but hey, it was working!')
            .setImage(BASE_URL + answer.screenshot)
            .setTimestamp()
            .setFooter({ text: 'A small step for X, a giant leap for X' });
        await interaction.reply({ embeds: [itemEmbed] });
    },
};

我尝试在网上和 StackOverflow 上搜索错误消息/类似情况,但一无所获。非常感谢您的帮助!

2个回答

正如您在回答中提到的,返回的对象中没有 list 项。它应该是 items 。此外,您收到 [object Object] 是因为您隐式将返回的对象强制转换为字符串(即 console.log(`Console log 3: `+itemSearchResult.body`)

我回答的原因是您可以摆脱那个丑陋的 getJSONResponse() 函数并使用内置的 body mixin 来简化您的代码:

async execute(interaction) {
  const itemName = interaction.options.getString('item_name');
  const { body } = await request(ITEM_URL + encodeURIComponent(itemName));
  const { items } = await body.json();

  if (!items.length)
    await interaction.reply(`No results found for **${itemName}**.`);

  const [answer] = items;
  const itemEmbed = new MessageEmbed()
    .setColor('#000000')
    .setTitle(answer.name)
    .setAuthor({ name: 'Author' })
    .setDescription('Lot of hassle, but hey, it was working!')
    .setImage(BASE_URL + answer.screenshot)
    .setTimestamp()
    .setFooter({ text: 'A small step for X, a giant leap for X' });
  await interaction.reply({ embeds: [itemEmbed] });
},

enter image description here

Zsolt Meszaros
2022-07-09

让朋友看看我的代码并帮忙。

问题出在 const { list } = await getJSONResponse(itemSearchResult.body); ,因为 API 没有传递列表。

有效/正确的代码是:

const itemName = interaction.options.getString('item_name');
        
const itemSearchResult = await request(ITEM_URL + encodeURIComponent(itemName));
const response = await getJSONResponse(itemSearchResult.body);

const items = response.items;
const firstItem = response.items[0];
ToldiReloaded
2022-07-09