Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (2024)

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (1)

Your bot may want to display a cool image when welcoming people to a Discord server. In this tutorial we’ll go over how to do that from scratch using Discord.JS and the WOKCommands package.

Corresponding Video Tutorial

The steps we will take

  1. Creating our project and connecting to MongoDB
  2. Creating a “!setWelcome” command to specify the welcome channel
  3. Creating a “!simJoin” command to simulate joins for testing
  4. Listening for new joins and sending a dynamic image

Creating our project and connecting to MongoDB

We’ll start off by creating a basic Node project, installing the required packages, and create the files/folders we need. I will be doing this through the command line with the following commands:

npm init -y
touch index.js .env
mkdir commands features models
npm install discord.js wokcommands dotenv mongoose canvas
npm install nodemon -g

At this stage we have a basic setup created, but we have to specify our bot’s token. If you don’t have a bot yet then follow the steps here to create one.

The .env file will contain our token like so:

TOKEN=YOUR_TOKEN_HERE
MONGO_URI=YOUR_MONGO_CONNECTION_STRING

We can then follow the WOKCommands documentation to setup our project:

const DiscordJS = require('discord.js')
const WOKCommands = require('wokcommands')
require('dotenv').config()

const client = new DiscordJS.Client()

client.on('ready', () => {
// Initialize WOKCommands with specific folders and MongoDB
new WOKCommands(client, {
commandsDir: 'commands',
featureDir: 'features'
})
.setMongoPath(process.env.MONGO_URI)
.setDefaultPrefix('!') // Change this to whatever you want
})

client.login(process.env.TOKEN)

We should now be able to run our bot with nodemon or node index.js

Creating a “!setWelcome” command to specify the welcome channel

Configuring our Discord bot should be as easy as possible for server owners. We can create a simple command to specify what channel is the welcome channel. This allows server owners to change the name however they want without interfering with our bot’s functionality.

To do this we first need to create a MongoDB model, and then create the command to save data to the specified collection within that model. Let’s start with the model:

// "welcome-channel.js" file within the "models" folderconst mongoose = require('mongoose')// We are using this multiple times so define
// it in an object to clean up our code
const reqString = {
type: String,
required: true,
}
const welcomeSchema = new mongoose.Schema({
_id: reqString, // Guild ID
channelId: reqString,
})
module.exports = mongoose.model('welcome-channel-tutorial', welcomeSchema)

We can now create our command with a basic boilerplate to see if it works:

// "setwelcome.js" file within the "commands" foldermodule.exports = {
requiredPermissions: ['ADMINISTRATOR'],
callback: async ({ message }) => {
message.reply('Works!')
},
}

If we run “!setwelcome” within a Discord server we see that it replies with “Works!” like so:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (2)

We can now add in our desired functionality now that we have a working command. First we have to import our model and then update the channel ID for the guild:

// "setwelcome.js" file within the "commands" folderconst welcomeChannelSchema = require('../models/welcome-channels')module.exports = {
requiredPermissions: ['ADMINISTRATOR'],
callback: async ({ message }) => {
// Destructure the guild and channel properties from the message object
const { guild, channel } = message
// Use find one and update to either update or insert the
// data depending on if it exists already
await welcomeChannelSchema.findOneAndUpdate(
{
_id: guild.id,
},
{
_id: guild.id,
channelId: channel.id,
},
{
upsert: true,
}
)
message.reply('Welcome channel set!')
},
}

After running the command we should now see the following object in our MongoDB database:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (3)

This means everything is working correctly so far. However we won’t want to read from the database every time someone joins, so it’s best for us to cache what guild is using what channel. We can easily do this with a map and an exported function to returns the channel ID. We also want to ensure we load our data when the bot starts up. Our file now looks like this:

// "setwelcome.js" file within the "commands" folderconst welcomeChannelSchema = require('../models/welcome-channels')const cache = new Map()// An async function to load the data
const loadData = async () => {
// Get all stored channel IDs
const results = await welcomeChannelSchema.find({})
// Loop through them all and set them in our map
for (const result of results) {
cache.set(result._id, result.channelId)
}
}
// Invoke this function when the bot starts up
loadData()
module.exports = {
requiredPermissions: ['ADMINISTRATOR'],
callback: async ({ message }) => {
// Destructure the guild and channel properties from the message object
const { guild, channel } = message
// Use find one and update to either update or insert the
// data depending on if it exists already
await welcomeChannelSchema.findOneAndUpdate(
{
_id: guild.id,
},
{
_id: guild.id,
channelId: channel.id,
},
{
upsert: true,
}
)
// Store the information in the cache
cache.set(guild.id, channel.id)
message.reply('Welcome channel set!')
},
}
module.exports.getChannelId = (guildId) => {
return cache.get(guildId)
}

Once we start listening for guild joins we can use the getChannelId function to get the desired channel for that guild.

Creating a “!simJoin” command to simulate joins for testing

We can create a command to simulate someone joining so we don’t have to ask our friends to help out. This is actually fairly simple to do with the following command:

// "simjoin.js" file within the "commands" foldermodule.exports = {
requiredPermissions: ['ADMINISTRATOR'],
callback: ({ message, args, text, client }) => {
client.emit('guildMemberAdd', message.member)
},
}

This will fire/run the “guildMemberAdd” event that we’ll be listening to soon.

Listening for new joins and sending a dynamic image

With the initial setup done we can now incorporate canvas within our project to create our dynamic image whenever someone joins. We’ll start by creating a welcome.js file inside of our “features” folder. This file will handle all of this logic for us:

// "welcome.js" file within the "features" foldermodule.exports = client => {
client.on('guildMemberAdd', member => {
console.log(member.user.tag)
})
}

Running “!simjoin” will now send a simple welcome message to the previously configured welcome channel. This is a nice proof of concept of loading the welcome channel for each guild and sending a message whenever someone joins. We can now move onto the canvas side of things. First off we need a background image. For simplicity we’ll use the one provided by the official Discord.JS documentation:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (4)

Be sure to save this as “background.png” in the root of your project folder like so:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (5)

It is easier to split this problem up into multiple smaller problems. So to start we’ll tackle just displaying the image whenever someone joins. To do that we need to first import canvas, create a canvas, and then attack the image to the canvas like so:

Note: Be sure your callback function is asynchronous!

// "welcome.js" file within the "features" folder// Note the capital 'C'
const Canvas = require('canvas')
const { MessageAttachment } = require('discord.js')
const path = require('path')
const { getChannelId } = require('../commands/setwelcome')
module.exports = (client) => {
client.on('guildMemberAdd', async (member) => {
// Async function
// Destructure the guild property from the member object
const { guild } = member
// Access the channel ID for this guild from the cache
const channelId = getChannelId(guild.id)
// Access the actual channel and send the message
const channel = guild.channels.cache.get(channelId)
// Create a canvas and access the 2d context
const canvas = Canvas.createCanvas(700, 250)
const ctx = canvas.getContext('2d')
// Load the background image and draw it to the canvas
const background = await Canvas.loadImage(
path.join(__dirname, '../background.png')
)
let x = 0
let y = 0
ctx.drawImage(background, x, y)
// Attach the image to a message and send it
const attachment = new MessageAttachment(canvas.toBuffer())
channel.send('', attachment)
})
}

At this stage when we run “!simjoin” it will now display the image inside of our welcome channel like so:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (6)

Now we can customize the other content we want to display on the canvas. This is personal preference, but I’ll be displaying the image and name of the user near the center of the canvas. I’m sure most of you will come up with more creative designs, but this will give us enough experience to know the basics. Let’s first start with displaying the user’s avatar at the exact center:

// "welcome.js" file within the "features" folder// Note the capital 'C'
const Canvas = require('canvas')
const { MessageAttachment } = require('discord.js')
const path = require('path')
const { getChannelId } = require('../commands/setwelcome')
module.exports = (client) => {
client.on('guildMemberAdd', async (member) => {
// Async function
// Destructure the guild property from the member object
const { guild } = member
// Access the channel ID for this guild from the cache
const channelId = getChannelId(guild.id)
// Access the actual channel and send the message
const channel = guild.channels.cache.get(channelId)
// Create a canvas and access the 2d context
const canvas = Canvas.createCanvas(700, 250)
const ctx = canvas.getContext('2d')
// Load the background image and draw it to the canvas
const background = await Canvas.loadImage(
path.join(__dirname, '../background.png')
)
let x = 0
let y = 0
ctx.drawImage(background, x, y)
// Load the user's profile picture and draw it
const pfp = await Canvas.loadImage(
member.user.displayAvatarURL({
format: 'png',
})
)
x = canvas.width / 2 - pfp.width / 2
y = canvas.height / 2 - pfp.height / 2
ctx.drawImage(pfp, x, y)
// Attach the image to a message and send it
const attachment = new MessageAttachment(canvas.toBuffer())
channel.send('', attachment)
})
}

We now see this when I run the “!simjoin” command:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (7)

How does the math work? The end goal here is to center the image. We can divide the width of the image by 2 and then subtract the width of the profile picture by 2. The same concept can be applied to the height to center it vertically too.

Next we need to move the image up to make room for some text below it. We can do this by simply using “25” as the y value:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (8)

We now have room to display some text below which we can do using the following:

// "welcome.js" file within the "features" folder// Note the capital 'C'
const Canvas = require('canvas')
const { MessageAttachment } = require('discord.js')
const path = require('path')
const { getChannelId } = require('../commands/setwelcome')
module.exports = (client) => {
client.on('guildMemberAdd', async (member) => {
// Async function
// Destructure the guild property from the member object
const { guild } = member
// Access the channel ID for this guild from the cache
const channelId = getChannelId(guild.id)
// Access the actual channel and send the message
const channel = guild.channels.cache.get(channelId)
// Create a canvas and access the 2d context
const canvas = Canvas.createCanvas(700, 250)
const ctx = canvas.getContext('2d')
// Load the background image and draw it to the canvas
const background = await Canvas.loadImage(
path.join(__dirname, '../background.png')
)
let x = 0
let y = 0
ctx.drawImage(background, x, y)
// Load the user's profile picture and draw it
const pfp = await Canvas.loadImage(
member.user.displayAvatarURL({
format: 'png',
})
)
x = canvas.width / 2 - pfp.width / 2
y = 25
ctx.drawImage(pfp, x, y)
// Display user text
ctx.fillStyle = '#ffffff' // White text
ctx.font = '35px sans-serif'
let text = `Welcome ${member.user.tag}!`
x = canvas.width / 2 - ctx.measureText(text).width / 2
ctx.fillText(text, x, 60 + pfp.height)
// Display member count
ctx.font = '30px sans-serif'
text = `Member #${guild.memberCount}`
x = canvas.width / 2 - ctx.measureText(text).width / 2
ctx.fillText(text, x, 100 + pfp.height)
// Attach the image to a message and send it
const attachment = new MessageAttachment(canvas.toBuffer())
channel.send('', attachment)
})
}

Running “!simjoin” we now get this result:

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (9)

Again I’m sure most of you can come up with more creative ideas than this. Hopefully you can use this tutorial to modify and adjust the canvas to your liking.

Discord.JS Canvas Tutorial — Custom Welcome Images for Your Discord Bots (2024)

FAQs

How do you make a custom welcome bot in Discord? ›

Set up a welcome bot
  1. Click the Welcome option. To create a welcome bot, click the "Welcome" option. ...
  2. Select what you want the bot to do. ...
  3. You can set what your bot says down to the text color and font, as well as which channel your bot will post in. ...
  4. Hit Save when finished.
Jul 14, 2022

How do I make a Discord welcome image? ›

Log in to your Discord server and open the welcome channel. Drag and drop your image into the channel and you're all set! To place the welcome banner at the top, upload the image first, then add your text.

How do you use Discord canvas? ›

Discord JS - Basic Canvas Welcome Tutorial (2020) [Episode #74]

How do you get a Discord bot to send pictures? ›

Sending Images using Discord.py - YouTube

How do I make a MEE6 welcome message? ›

How to make a Welcome Message for your Discord Server (MEE6)

How do I use Welcome MIMU bot? ›

mimu now needs to know that we'd like this embed to be apart of our greet. use . set greetmsg welcome, {user}! {embed:greet_embed} to set the greet message to a short welcome, pinging the user, and the embed we just created.

What does MIMU bot do? ›

with its extensive configuration options and simple style, Mimu brings to you a one-of-a-kind economy system to your Discord server and brings your dreams to reality. Its utilities are packed, made to be user-friendly and for serves to be a cuter currency system.

What size is the Discord welcome banner? ›

Discord Banner Background images can be up to 960 pixels wide by 540 pixels tall, and Server Invite Splash Images can be 1920 pixels wide to 1080 pixels tall.

Can tuppers send images? ›

Simply visit the dashboard, select your tupper, and click its avatar or the upload button. Alternatively, you can simply paste an image link in the "Avatar URL" field on your tupper. You can either provide an image link, like above, or upload the image while running the command instead of giving a link.

How do I make a Discord bot send gifs? ›

Discord Bots 5: Posting GIFs - YouTube

What is a subcommand Discord? ›

Subcommands organize your commands by specifying actions within a command or group. Subcommand Groups organize your subcommands by grouping subcommands by similar action or resource within a command. These are not enforced rules.

How do you make Welcomer welcome people? ›

How to Get and Setup Welcomer Bot on Discord (Server ... - YouTube

What is canvas Discord? ›

GitHub - discord-canvas/Discord-Canvas-Bot: A bot for keeping track of past and current homework's and tracking assignment deadlines using the VLE Canvas API. Product.

How do you put photos on canvas? ›

Importing images into a canvas is basically a two step process: Get a reference to an HTMLImageElement object or to another canvas element as a source. It is also possible to use images by providing a URL. Draw the image on the canvas using the drawImage() function.

What is Node canvas? ›

The node-canvas package is a NodeJS module allows you to create an image programatically. The package uses Cairo 2D graphics library so that you can generate an image in many common formats like JPG, JPEG or PNG.

How do I get discord canary? ›

You can try out Discord Canary by downloading the latest build release of the Discord Canary desktop app or by trying it out in your web browser. To start, download the latest Discord Canary release for your operating system from the Discord website. You can download and use the desktop app on Linux, Windows, and Mac.

How do you make mee6 Welcome and goodbye? ›

How to Make a Welcome & Goodbye Channel on Discord - YouTube

How do you make a dyno welcome message? ›

How to set up Welcome
  1. Head over to your account and select your server.
  2. Click on the Modules tab.
  3. Ensure that the Welcome module is enabled.
  4. Click the Settings button underneath the Welcome module.
  5. Select your message type ( Message , Embed , or Embed and Text ).

Top Articles
Latest Posts
Article information

Author: Pres. Carey Rath

Last Updated:

Views: 6461

Rating: 4 / 5 (41 voted)

Reviews: 88% of readers found this page helpful

Author information

Name: Pres. Carey Rath

Birthday: 1997-03-06

Address: 14955 Ledner Trail, East Rodrickfort, NE 85127-8369

Phone: +18682428114917

Job: National Technology Representative

Hobby: Sand art, Drama, Web surfing, Cycling, Brazilian jiu-jitsu, Leather crafting, Creative writing

Introduction: My name is Pres. Carey Rath, I am a faithful, funny, vast, joyous, lively, brave, glamorous person who loves writing and wants to share my knowledge and understanding with you.