Search code examples
node.jsdiscord.jsbuffer

Unable to send image buffer attachment using discord.js


I have a bot command where I access the Wolfram Alpha API to return an image back with an answer to the question posed by the user, but, for some reason, the image buffer is undefined, and I end up with the error below when using the command

C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\util\DataResolver.js:127
    throw new TypeError('REQ_RESOURCE_TYPE');
          ^

TypeError [REQ_RESOURCE_TYPE]: The resource must be a string, Buffer or a valid file stream.
    at Function.resolveFile (C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\util\DataResolver.js:127:11)
    at Function.resolveFile (C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\structures\MessagePayload.js:257:41)
    at C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\structures\MessagePayload.js:222:85
    at Array.map (<anonymous>)
    at MessagePayload.resolveFiles (C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\structures\MessagePayload.js:222:56)
    at TextChannel.send (C:\Users\ACER PREDATOR 300\Desktop\MathBot\node_modules\discord.js\src\structures\interfaces\TextBasedChannel.js:175:50)       
    at Object.execute (C:\Users\ACER PREDATOR 300\Desktop\MathBot\commands\misc\ask.js:40:25)
    at Object.execute (C:\Users\ACER PREDATOR 300\Desktop\MathBot\events\messageCreate.js:159:12)
    at Client.<anonymous> (C:\Users\ACER PREDATOR 300\Desktop\MathBot\bot.js:41:35)
    at Client.emit (node:events:538:35) {
  [Symbol(code)]: 'REQ_RESOURCE_TYPE'
}

Here is the code for my bot command

/**
 * @type {import('../../typings').LegacyCommand}
 */

const { MessageAttachment } = require("discord.js");
const WolframAlphaAPI = require('wolfram-alpha-api');
const waApi = WolframAlphaAPI('API-KEY-REMOVED-FOR-QUESTION');

// Make a getImage function
function getImage(question) {
    // Returns the buffer of the image
    waApi.getSimple(question).then((url) => {
        // Extract the base64 string from the url
        const sfbuff = new Buffer.from(url.split(",")[1]);

        // Convert the base64 string to base64
        const base64 = sfbuff.toString('base64');

        // Convert the base64 to a buffer
        const buffer = Buffer.from(base64, 'base64');

        return buffer;
    });
}

module.exports = {
    name: "ask",
    // Refer to typings.d.ts for available properties.

    execute(message, args) {

        // Get the question from the args
        let question = args.join(" ");

        // Using the getImage function, get the image of the answer.
        const buffer = getImage(question);
        const imageAttachment = new MessageAttachment(buffer, "image-attachment.png");

        // Send the image
        message.channel.send({
            content: `Image:\n⁣`,
            files: [
                { attachment: imageAttachment }
            ]
        });
    },
};

I have extracted the base64 string and put it in an online imageToBase64 converter, and it does work, but I can't seem to convert it to a buffer properly. I suspect it could be something with the processing time, but I could be wrong.

Any help would be appreciated, thanks.


Solution

  • getImage returns a promise but you are not handling it properly I would change the code in this way:

     /**
     * @type {import('../../typings').LegacyCommand}
     */
    
    const { MessageAttachment } = require("discord.js");
    const WolframAlphaAPI = require('wolfram-alpha-api');
    const waApi = WolframAlphaAPI('API-KEY-REMOVED-FOR-QUESTION');
    
    // Make a getImage function
    function getImage(question) {
        // Returns the promise
        return waApi.getSimple(question);
    }
    
    module.exports = {
        name: "ask",
        // Refer to typings.d.ts for available properties.
    
        execute(message, args) {
    
            // Get the question from the args
            let question = args.join(" ");
    
            // Using the getImage function, get the image of the answer.
            const buffer = getImage(question).then((url) => {
                // Extract the base64 string from the url
                const sfbuff = new Buffer.from(url.split(",")[1]);
        
                // Convert the base64 string to base64
                const base64 = sfbuff.toString('base64');
        
                // Convert the base64 to a buffer
                const buffer = Buffer.from(base64, 'base64');
        
                const imageAttachment = new MessageAttachment(buffer, "image-attachment.png");
    
                // Send the image
                message.channel.send({
                    content: `Image:\n⁣`,
                    files: [
                        { attachment: imageAttachment }
                    ]
                });
            })
        },
    };