base 64 url converter for discord bot

2k views Asked by At

im using an api to get me mincraft server details it gives me the ip, player count and all that jazz but for the server icon it gives me a base 64url so i need to decode this first inside my discord bot but i am unsure how this could be done https://www.npmjs.com/package/minecraft-server-util this is the api i used if you would like to have a look and incase you need a look at my code so you can show me how to intgrate it this is it

const discord = require("discord.js");
const util = require('minecraft-server-util');
const {MessageEmbed} = require('discord.js');
const bot = new discord.Client();
const token = "my token but i removed it here for privecy reasons";
const PREFIX = "-";


var version = "1.0.1"
util.status("hypixel.net")

bot.on("ready", ()=>{
  console.log("this bot is online!")
})

bot.on("message", message=>{
  let args = message.content.slice(PREFIX.length).split(" ")

  switch(args[0]){
    case "ping":
      message.reply ("pong");
      break;
    case "website":
      message.channel.send("youtube.com/probler")
      break;
    case "info":
      if(args[1] === "version"){
        message.channel.send("We Are Curently In Version " + version)
      }
      else{
        message.channel.send("Invalid Command")
      }
      break;
    case "clear":
      if(!args[1]) return message.reply("Error Please Define A Number")
      message.channel.bulkDelete(args[1]);
      break;

    case "embed":
      const embed = new MessageEmbed()
      .setColor('RANDOM')
      .setTitle("User Information")
      .addField("Player Name", message.author.username, true)
      .addField("Current Server", message.guild.name,)
      .setThumbnail(message.author.displayAvatarURL())
      .setFooter("Version " + version)
      message.channel.send(embed);
      break;

      case 'mc':
        const util = require('minecraft-server-util');
    
        util.status(args[1])
        .then ((response) => {
            const embed = new MessageEmbed()
            .setColor("RANDOM")
            .setTitle('__Server Status__')
            .addField('Server IP', response.host)
            .addField('Server Version', response.version)
            .addField('Online Players', response.onlinePlayers)
            .addField('Max Players', response.maxPlayers)    
            .setThumbnail("Server Icon", response.favicon)
            message.channel.send(embed)
        
        })
       .catch((error, response) => {
           throw error;
       });
       break;
      }
  }
)

bot.login(token);```
1

There are 1 answers

0
Cannicide On BEST ANSWER

Solution

It took me a while, and a lot of failed tests, to figure this out. But I finally got it working, and here's the end result:

const Discord = require('discord.js');
const util = require('minecraft-server-util');

util.status("hypixel.net").then(response => {

    var fav = response.favicon.split(",").slice(1).join(",");
    var imageStream = Buffer.from(fav, "base64");
    var attachment = new Discord.MessageAttachment(imageStream, "favicon.png");
    
    const embed = new Discord.MessageEmbed()
    .attachFiles([attachment])
    .setThumbnail("attachment://favicon.png");

    message.channel.send(embed);
}).catch(console.error);

I tested this using my bot's eval command, and it worked like a charm using my own minecraft server's IP. You might need to tweak the code slightly if your base64 URL's format or filetype are different from mine.

Explanation

I'll explain each step of this solution below:

  1. response.favicon.split(",").slice(1).join(",")

This gets the data from the base64 string. The format of base64 is usually something along the lines of: data:<media type>;[charset=<character set>];base64,<data>. As you can see, the actual data of the base64 only begins after the first comma, so I remove everything before the comma in this line of code.

  1. Buffer.from(fav, "base64")

This converts the base64 into a buffer. Discord's message attachments cannot use base64 URLs, but they can use anything that can be resolved into a Buffer. This line allows our base64 data to be converted into something that can be sent as an attachment in Discord.

  1. new Discord.MessageAttachment(imageStream, "favicon.png")

Note that neither base64 URLs nor Buffers can directly be set as the thumbnail of the embed. The thumbnail only supports a regular URL. So we can use a workaround provided by discord.js, which allows us to first attach our buffer as an attachment, and then move it into the thumbnail afterwards. This line creates our attachment, and names it "favicon.png" (this is important, as we'll need to access this name later).

  1. .attachFiles([attachment])

This line attaches our newly created MessageAttachment to the embed. It is attached only as a file, and isn't in our embed's thumbnail yet.

  1. .setThumbnail("attachment://favicon.png")

Now we can use discord.js' workaround to get our image into the thumbnail. We can use attachment://fileName.extension to access any and all attached files in our embed. This would allow us to set our embed's thumbnail, icons, or image to the minecraft server's favicon by grabbing the file from the attachment. And best of all, when we do this, the file is moved to the thumbnail and is not additionally sent as an attachment.

Relevant Resources

https://discord.js.org/#/docs/main/stable/class/MessageEmbed?scrollTo=attachFiles https://discord.js.org/#/docs/main/stable/class/MessageAttachment

https://github.com/discordjs/discord.js/issues/2175#issuecomment-538948474
^ This was written for discord.js v11 and isn't quite a full/working solution, but provided a general idea of how to do this