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

Tags: , , , ,



so I have my eval command, however when I run such things as an eval to set status or something like that, it returns either [object Object] or [object Map]. I have fixed the previous error with [object Promise], however Object and Map still occur. My code is below, if someone knows how to fix this that would be amazing.

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!!!nn*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: ````jsn${args}````, inline: false },
                    { name: '**Output:**', value: ````jsn${evaled}````, inline: false }
                )
            message.channel.send(evalEmbed)
        }

Answer

Well, do you understand why you’re getting [object Object] and [object Map]? Let’s use your example of setting your bot’s status. Take a look at the docs for what setStatus() returns. According to the docs, it returns Promise<Presence>.

The Problem(s)

You mentioned that you “solved” it returning a Promise, and I assume you mean that you are using async/await to get the result of the Promise instead of getting the Promise itself. So basically, in the status example, because you’re using await you are no longer getting a Promise, but you are now instead getting a Presence object which is the successful result of the Promise (as mentioned by the docs, when it says that setStatus() returns Promise<Presence>).

Okay, so that means your evaled variable now represents that Presence object. So evaled is an Object, not a String; it’s not a line of text that you can send in a message or embed. And when you try to treat the Object like it’s text (a String), your code will attempt to convert the Object into a String which will result in the text you are getting: [object Object]. And of course, the same is true of a Map, since it is also not a String.

When you use your eval command, the result could be any data type. For example, if you do /eval 33, that will return a Number. If you do /eval message.channel.name that will return a String since the name of a channel will be text. But if you for example do /eval client.user.setStatus(), you’re not going to get a simple number or piece of text. You’re going to get an Object, and that’s the cause of your problem.

Since the eval command can return a result of any datatype, we need to account for the datatypes that can’t be converted to a piece of text or the datatypes that will be converted into a piece of text that we weren’t expecting, as is the case with Objects.

Furthermore, I noticed in your code that the only limitation on your eval command is that users cannot access or modify your bot’s token. Do not let users have access to the eval command at all. It is possible to do much worse through an eval command than simply access your token. Users can do anything from intentionally causing errors to crash your bot, to creating a new message handler that automatically deletes every message sent in all of the guilds your bot is in. Plus, as your code is right now, users could still do eval client.token and mess with your token, simply by adding a semicolon to the end of that line. This issue concerning limitations on your eval command isn’t what’s causing your problem, but you need to address it or risk providing users with an easy way of harming your bot, the guilds your bot is in, and/or the members of those guilds. If this bot is hosted locally on your computer, not limiting this command to only yourself could even grant users access to the files on your computer.

A Solution

Here’s how I would recommend you change your eval command, such that it both partially solves your problem and prevents users from doing anything malicious.

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!!!nn*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: ````jsn${args}````,
            inline: false
        },
        {
            name: '**Output:**',
            value: ````jsn${evaled}````,
            inline: false
        }
     );
     message.channel.send(evalEmbed)
}

This will definitely solve your [object Object] issue (it will now instead be a JSON string such as {"key": "value"} instead). I’m not sure if it would be able to convert a Map to JSON, though. Anything else (apart from numbers, booleans, text, objects, and arrays) that can’t be easily converted into text will simply be converted into a message saying something in this format: "Output could not be converted to text (output was of type: <insert datatype here>)."

Feel free to change this code however you’d like to make it look and work the best for you. How the output should look for your specific input is entirely up to you. What’s important is that you get the concept of this answer: using typeof to check for specific datatypes that will be converted into something like [object Object], and converting that data into something better and more readable.

And I would like to repeat the significance of limiting the use of this command to only you, or anyone else that is directly working on this bot. The purpose of eval commands is to make it easier for bot developers to solve issues in their code, allowing them to test the values of certain variables and properties instead of having to restart your bot and console.log those values. Giving all users access to this command, however, would open up hundreds of different ways for users to act maliciously towards guilds, members, your bot, and even you.



Source: stackoverflow