discord.js eval 命令返回 [object Map] 和 [object Object]

discord.js eval command returning [object Map] and [object Object]

所以我有我的 eval 命令,但是当我 运行 诸如 eval 之类的东西来设置状态或类似的东西时,它 returns [object Object][object Map].我已经用 [object Promise] 修复了之前的错误,但是 Object 和 Map 仍然出现。我的代码在下面,如果有人知道如何解决这个问题那就太棒了。

if (message.content.startsWith(prefix + "eval")) {
            if (message.content === (prefix + 'eval client.token')) {
                const noToken = new Discord.MessageEmbed()
                    .setColor('RANDOM')
                    .setDescription('OI WHO GAVE YOU PERMISSION TO TOUCH MY TOKEN!!!\n\n*back off...*')
                return message.channel.send(noToken)
            }
            var result = message.content.split(" ").slice(1).join(" ")
            let evaled = await eval(result);
            const evalEmbed = new Discord.MessageEmbed()
                .setColor('RANDOM')
                .addFields(
                    { name: '**Input:**', value: `\`\`\`js\n${args}\`\`\``, inline: false },
                    { name: '**Output:**', value: `\`\`\`js\n${evaled}\`\`\``, inline: false }
                )
            message.channel.send(evalEmbed)
        }

嗯,你明白为什么你会得到 [object Object][object Map] 吗?让我们使用您设置机器人状态的示例。看一下 setStatus() return 的文档。根据the docs,它returns Promise<Presence>.

问题

您提到您 return 通过 Promise“解决”了它,我假设您的意思是您正在使用 async/await 来获得 [=15= 的结果] 而不是获取 Promise 本身。所以基本上,在状态示例中,因为您正在使用 await,所以您不再获得 Promise,而是现在获得 Presence 对象,这是成功的结果Promise(如文档所述,当它说 setStatus() returns Promise<Presence>)时。

好的,这意味着您的 evaled 变量现在代表 Presence 对象。所以 evaledObject,而不是 String;这不是您可以在消息中发送或嵌入的文本行。当您尝试将 Object 视为文本(String)时,您的代码将尝试将 Object 转换为 String,这将导致文本得到:[object Object]。当然,Map 也是如此,因为它也不是 String.

当您使用 eval 命令时,结果可以是任何数据类型。例如,如果您执行 /eval 33,那么将 return 变成 Number。如果您这样做 /eval message.channel.name,那么将 return 变成 String,因为频道的名称将是文本。但是,如果您执行 /eval client.user.setStatus(),您将不会得到一个简单的数字或一段文本。您将得到一个 Object,这就是您遇到问题的原因。

由于 eval 命令可以 return any 数据类型的结果,我们需要考虑无法转换为一段文本或数据类型将被转换成一段我们没有预料到的文本,就像对象一样。

此外,我注意到您的代码中 eval 命令的唯一限制是用户无法访问或修改您的机器人令牌。 根本不要让用户访问 eval 命令。通过 eval 命令可能比简单地访问您的令牌做得更糟。用户可以做任何事情,从故意导致错误使你的机器人崩溃,到创建一个新的消息处理程序,自动删除你的机器人所在的所有公会中发送的每条消息。另外,正如你现在的代码一样,用户仍然可以做 eval client.token 并弄乱你的令牌,只需在该行的末尾添加一个分号即可。这个关于你的 eval 命令限制的问题不是导致你的问题的原因,但你需要解决它或冒着为用户提供一种简单的方法来伤害你的机器人的风险,你的机器人所在的行会,and/or 的成员那些行会。如果此 bot 在您的计算机本地托管,则不仅限于您自己可以执行此命令,甚至可以授予用户访问您计算机上文件的权限。

一个解决方案

以下是我建议您更改 eval 命令的方法,这样它既可以部分解决您的问题,又可以防止用户进行任何恶意操作。

if (message.content.startsWith(prefix + "eval")) {

    if (message.author.id != "add YOUR discord id here") {
        //Only allow bot developer(s) to use the eval command, not all users

        const noToken = new Discord.MessageEmbed()
        .setColor('RANDOM')
        .setDescription('OI WHO GAVE YOU PERMISSION TO USE EVAL!!!\n\n*back off...*')
        return message.channel.send(noToken)
    }

    var result = message.content.split(" ").slice(1).join(" ")
    let evaled = await eval(result);

    //Convert evaled into a JSON String if it is an Object
    if (typeof evaled === "object") evaled = JSON.stringify(evaled);

    //Do this if evaled is anything else other than a number, text, or true/false
    if (typeof evaled !== "number" && typeof evaled !== "string" && typeof evaled !== "boolean") evaled = `Output could not be converted to text (output was of type: ${typeof evaled}).`;

    const evalEmbed = new Discord.MessageEmbed()
    .setColor('RANDOM')
    .addFields(
        {
            name: '**Input:**',
            value: `\`\`\`js\n${args}\`\`\``,
            inline: false
        },
        {
            name: '**Output:**',
            value: `\`\`\`js\n${evaled}\`\`\``,
            inline: false
        }
     );
     message.channel.send(evalEmbed)
}

这肯定会解决您的 [object Object] 问题(现在它将改为 JSON 字符串,例如 {"key": "value"})。不过,我不确定它是否能够将 Map 转换为 JSON。无法轻松转换为文本的任何其他内容(数字、布尔值、文本、对象和数组除外)都将简单地转换为消息,以这种格式表达内容:"Output could not be converted to text (output was of type: <insert datatype here>)."

您可以随意更改此代码,但您希望它的外观和工作方式最适合您。输出应如何查找您的特定输入完全取决于您。重要的是你得到这个答案的概念:使用 typeof 检查将被转换成类似 [object Object] 的特定数据类型,并将该数据转换成更好、更易读的数据。

并且我想重申将此命令的使用限制在您或直接在该机器人上工作的任何其他人的重要性。 eval 命令的目的是让机器人开发人员更容易解决他们代码中的问题,允许他们测试某些变量和属性的值,而不必重新启动您的机器人和 console.log 这些值。然而,让所有用户都可以访问此命令,将为用户打开数百种不同的方式来对公会、成员、您的机器人甚至您进行恶意行为。