├── config.js ├── commands ├── Other │ ├── ping.js │ ├── uptime.js │ └── help.js └── Config │ ├── setprefix.js │ ├── setchannel.js │ └── setmessage.js ├── package.json ├── LICENSE ├── README.md └── app.js /config.js: -------------------------------------------------------------------------------- 1 | /* Please check https://github.com/LegendaryEmoji/welcome-bot/wiki/Config for information */ 2 | /* Make sure to turn on Server Members intent on discord developer portal or you will get some error & won't be able to get welcome/goodbye message & image */ 3 | 4 | const config = { 5 | Token: "", 6 | Default_Prefix: "", 7 | Color: "", 8 | Welcome_Images: "", 9 | GoodBye_Images: "", 10 | Support: "", 11 | }; 12 | 13 | module.exports = config; 14 | -------------------------------------------------------------------------------- /commands/Other/ping.js: -------------------------------------------------------------------------------- 1 | module.exports.help = { 2 | name: "ping", 3 | aliases: ["pg"], 4 | category: "Other", 5 | description: "Pong!", 6 | usage: "Ping", 7 | run: ({ client, message, Color }) => { 8 | return message.channel.send({ 9 | embeds: [ 10 | { 11 | color: Color || "RANDOM", 12 | description: `Pong - ${client.ws.ping}`, 13 | footer: { text: `- ${message.author.username}` }, 14 | timestamp: new Date(), 15 | }, 16 | ], 17 | }); 18 | }, 19 | }; 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "welcome-bot", 3 | "version": "2.0.0", 4 | "description": "An advanced welcome & goodbye open-source Discord bot.", 5 | "main": "app.js", 6 | "scripts": { 7 | "start": "node app.js" 8 | }, 9 | "repository": { 10 | "url": "https://github.com/LegendaryEmoji/welcome-bot" 11 | }, 12 | "license": "MIT", 13 | "keywords": [ 14 | "discord-js", 15 | "bot", 16 | "emo" 17 | ], 18 | "dependencies": { 19 | "discord-canvas": "^1.4.1", 20 | "discord.js": "^13.1.0", 21 | "moment": "^2.29.1", 22 | "old-wio.db": "^4.0.10" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /commands/Other/uptime.js: -------------------------------------------------------------------------------- 1 | module.exports.help = { 2 | name: "uptime", 3 | aliases: ["upt"], 4 | category: "Other", 5 | description: "Get bot running time", 6 | usage: "Uptime", 7 | run: ({ client, message, Color }) => { 8 | function getUptime(days, hours, minutes, seconds) { 9 | if (days > 0) return `${days}d:${hours}h:${minutes}m:${seconds}s`; 10 | if (hours > 0) return `${hours}h:${minutes}m:${seconds}s`; 11 | if (minutes > 0) return `${minutes}m:${seconds}s`; 12 | return `${seconds}s`; 13 | } 14 | 15 | return message.channel.send({ 16 | embeds: [ 17 | { 18 | color: Color || "RANDOM", 19 | description: getUptime( 20 | Math.floor(client.uptime / 86400000), 21 | Math.floor(client.uptime / 3600000) % 24, 22 | Math.floor(client.uptime / 60000) % 60, 23 | Math.floor(client.uptime / 1000) % 60 24 | ), 25 | footer: { text: `- ${message.author.username}` }, 26 | timestamp: new Date(), 27 | }, 28 | ], 29 | }); 30 | }, 31 | }; 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 - 2021 Legendary Emoji 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /commands/Config/setprefix.js: -------------------------------------------------------------------------------- 1 | const db = require("old-wio.db"); 2 | 3 | module.exports.help = { 4 | name: "setprefix", 5 | aliases: ["newprefix", "sp"], 6 | category: "Config", 7 | description: "Set The Prefix Of Bot!", 8 | usage: "Setprefix ", 9 | run: async ({ message, args, Color, Default_Prefix }) => { 10 | if (!message.member.permissions.has("MANAGE_GUILD")) 11 | return message.channel.send( 12 | "You Don't Have Enough Permission To Execute This Command - Manage Server" 13 | ); 14 | 15 | const Prefix = (await db.fetch(`P-${message.guild.id}`)) || Default_Prefix; 16 | 17 | if (!args[0]) 18 | return message.channel.send("Please Give The New Prefix Of The Bot!"); 19 | 20 | if (args[0].length > 6) 21 | return message.channel.send("Too Long Prefix - 6 Limit"); 22 | 23 | if (args[0] === Prefix) 24 | return message.channel.send("Given Prefix Is The Current Prefix!"); 25 | 26 | await db.set(`P-${message.guild.id}`, args[0]); 27 | 28 | return message.channel.send({ 29 | embeds: [ 30 | { 31 | color: Color || "RANDOM", 32 | title: "Success", 33 | description: `New Prefix Has Been Set - ${args[0]}`, 34 | footer: { text: `- ${message.author.username}` }, 35 | timestamp: new Date(), 36 | }, 37 | ], 38 | }); 39 | }, 40 | }; 41 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Information 2 | 3 | An advanced welcome & goodbye bot with multiple images, custom prefix & custom message support 4 | 5 | - Multiple Images (Welcome, Goodbye - Links) 6 | - Changeable Prefix 7 | - Etc 8 | 9 | ### Installation / Setup 10 | 11 | - Make sure you have [Node.js v16.6.0 or newer](https://nodejs.org/en/) & also a code editor if you want to make things easier (we will be using [Visual Studio Code](https://code.visualstudio.com/) editor in this installation) 12 | - [Download](https://github.com/LegendaryEmoji/welcome-bot/archive/refs/heads/main.zip) / Export / Clone this [respository](https://github.com/LegendaryEmoji/welcome-bot) 13 | - If you downloaded the zip file, please extract it using [Winrar](https://www.win-rar.com/start.html?&L=0) or some other software 14 | - Open bot folder in [Visual Studio Code](https://code.visualstudio.com/) 15 | - After opening the bot folder in the editor, open terminal with **Ctrl + `** & wait for it to open 16 | - Type **npm i** in the terminal & wait for packages to install... 17 | - When it's done, go to Config.js file & fill information (check [Wiki](https://github.com/LegendaryEmoji/welcome-bot/wiki/Config)) 18 | - Setup is finished, enjoy! 19 | 20 | ### Other 21 | 22 | Note: Please make sure you have some basic knowledge before changing anything in source code or you will hate yourself. 23 | 24 | - Credits - Andrew 25 | - Author - Andrew 26 | - Discord Server (Support|Chat) - [Click here](https://discord.gg/Df55eVQVmk) 27 | - License - [MIT](https://github.com/LegendaryEmoji/welcome-bot/blob/main/LICENSE) 28 | -------------------------------------------------------------------------------- /commands/Config/setchannel.js: -------------------------------------------------------------------------------- 1 | const db = require("old-wio.db"); 2 | 3 | module.exports.help = { 4 | name: "setchannel", 5 | aliases: ["setch", "sc"], 6 | category: "Config", 7 | description: "Set The Welcome Or Goodbye Message Channel!", 8 | usage: "Setchannel ", 9 | run: async ({ message, args, Color }) => { 10 | if (!message.member.permissions.has("MANAGE_CHANNELS")) 11 | return message.channel.send( 12 | "You Don't Have Enough Permission To Execute This Command - Manage Channels" 13 | ); 14 | 15 | const mentionedChannel = 16 | message.mentions.channels.first() || 17 | message.guild.channels.cache.get(args[0]); 18 | 19 | if (!mentionedChannel || mentionedChannel.type === "voice") 20 | return message.channel.send(`Please Give A Valid Text Channel!`); 21 | 22 | const Welcome = ["welcome", "wel", "join"], 23 | Goodbye = ["goodbye", "leave", "left"]; 24 | 25 | if ( 26 | !args[1] || 27 | ![...Welcome, ...Goodbye].find((T) => T === args[1].toLowerCase()) 28 | ) 29 | return message.channel.send( 30 | `Please Give A Valid Type - ${[...Welcome, Goodbye].join(", ")}` 31 | ); 32 | 33 | const Current = Welcome.some((wel) => wel === args[1].toLowerCase()) 34 | ? "Welcome" 35 | : "Goodbye"; 36 | 37 | await db.set( 38 | `${Current === "Welcome" ? `WC` : `GC`}-${message.guild.id}`, 39 | mentionedChannel.id 40 | ); 41 | 42 | return message.channel.send({ 43 | embeds: [ 44 | { 45 | color: Color || "RANDOM", 46 | title: "Success", 47 | description: `${Current} Channel Has Been Set - <#${mentionedChannel.id}>`, 48 | footer: { text: `- ${message.author.username}` }, 49 | timestamp: new Date(), 50 | }, 51 | ], 52 | }); 53 | }, 54 | }; 55 | -------------------------------------------------------------------------------- /commands/Config/setmessage.js: -------------------------------------------------------------------------------- 1 | const db = require("old-wio.db"); 2 | 3 | module.exports.help = { 4 | name: "setmessage", 5 | aliases: ["setmsg", "sm"], 6 | category: "Config", 7 | description: "Set The Welcome Or Leave Message When Someone Joins Or Leave!", 8 | usage: "Setmessage ", 9 | run: async ({ message, args, Color }) => { 10 | if (!message.member.permissions.has("MANAGE_MESSAGES")) 11 | return message.channel.send( 12 | "You Don't Have Enough Permission To Execute This Command - Manage Messages" 13 | ); 14 | 15 | const Welcome = ["welcome", "wel", "join"], 16 | Goodbye = ["goodbye", "leave", "left"]; 17 | 18 | if ( 19 | !args[0] || 20 | ![...Welcome, ...Goodbye].find((T) => T === args[0].toLowerCase()) 21 | ) 22 | return message.channel.send( 23 | `Please Give A Valid Type - ${[...Welcome, ...Goodbye].join(", ")}` 24 | ); 25 | 26 | const messageRaw = args.slice(1).join(" "); 27 | 28 | if (!messageRaw) 29 | return message.channel.send( 30 | `Please Give Message\n\nCustom:\n => Server Name\n => Member Name\n => Member Mention` 31 | ); 32 | 33 | if (messageRaw.length > 1000) 34 | return message.channel.send("Too Long Message - Limit 1000"); 35 | 36 | const Current = Welcome.some((wel) => wel === args[0]) 37 | ? "Welcome" 38 | : "Goodbye"; 39 | 40 | await db.set( 41 | `${Current === "Welcome" ? "WM" : "GM"}-${message.guild.id}`, 42 | messageRaw 43 | ); 44 | 45 | return message.channel.send({ 46 | embeds: [ 47 | { 48 | color: Color || "RANDOM", 49 | title: "Success", 50 | description: `${Current} Message Has Been Set -\n${messageRaw}`, 51 | footer: { text: `- ${message.author.username}` }, 52 | timestamp: new Date(), 53 | }, 54 | ], 55 | }); 56 | }, 57 | }; 58 | -------------------------------------------------------------------------------- /commands/Other/help.js: -------------------------------------------------------------------------------- 1 | const db = require("old-wio.db"); 2 | 3 | module.exports.help = { 4 | name: "help", 5 | aliases: ["h"], 6 | category: "Other", 7 | description: "Bot Help Command ;)", 8 | usage: "Help | ", 9 | run: async ({ client, message, args, Color, Support, Default_Prefix }) => { 10 | const Prefix = (await db.fetch(`P-${message.guild.id}`)) || Default_Prefix; 11 | 12 | const Config = [ 13 | ...client.commands 14 | .filter((cmd) => cmd.help.category === "Config") 15 | .values(), 16 | ] 17 | .map((cmd) => "`" + cmd.help.name + "`") 18 | .join(", "); 19 | const Other = [ 20 | ...client.commands 21 | .filter((cmd) => cmd.help.category === "Other") 22 | .values(), 23 | ] 24 | .map((cmd) => "`" + cmd.help.name + "`") 25 | .join(", "); 26 | 27 | if (!args[0]) 28 | return message.channel.send({ 29 | embeds: [ 30 | { 31 | color: Color || "RANDOM", 32 | title: `${client.user.username} Help!`, 33 | thumbnail: { url: client.user.displayAvatarURL({ format: "jpg" }) }, 34 | description: `Type the following command for a specific command information -\n**${Prefix}Help **\n\n**🕹 Config**\n${Config}\n\n**🔮 Other**\n${Other}\n\n**Useful Links**\nSupport server - [Click me](${ 35 | Support || "https://bit.ly/34tvqau" 36 | })\nBot Link - [Click Me](https://discord.com/oauth2/authorize?client_id=${ 37 | client.user.id 38 | }&scope=bot&permissions=8)\n\nThank You So Much <3`, 39 | }, 40 | ], 41 | }); 42 | 43 | const command = 44 | client.commands.find((cmd) => cmd.help.name === args[0].toLowerCase()) || 45 | client.commands.find((cmd) => cmd.help.name === args[0].toLowerCase()); 46 | 47 | if (!command) 48 | return message.channel.send({ 49 | content: `No command found - ${ 50 | args[0].charAt(0).toUpperCase() + args[0].slice(1) 51 | }`, 52 | }); 53 | 54 | return message.channel.send({ 55 | embeds: [ 56 | { 57 | color: Color || "RANDOM", 58 | title: "Command information", 59 | thumbnail: { url: client.user.displayAvatarURL({ format: "jpg" }) }, 60 | fields: [ 61 | { 62 | name: "Name", 63 | value: 64 | command.help.name.charAt(0).toUpperCase() + 65 | command.help.name.slice(1), 66 | inline: true, 67 | }, 68 | { 69 | name: "Category", 70 | value: command.help.category, 71 | inline: true, 72 | }, 73 | { 74 | name: "Aliases", 75 | value: command.help.aliases 76 | ? command.help.aliases.join(", ") 77 | : "No Aliases", 78 | inline: true, 79 | }, 80 | { 81 | name: "Usage", 82 | value: command.help.usage, 83 | inline: true, 84 | }, 85 | { 86 | name: "Description", 87 | value: command.help.description, 88 | }, 89 | ], 90 | footer: { text: `- ${message.author.username}` }, 91 | timestamp: new Date(), 92 | }, 93 | ], 94 | }); 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const { Client, Collection } = require("discord.js"), 2 | { readdir } = require("fs"); 3 | const canvas = require("discord-canvas"), 4 | db = require("old-wio.db"); 5 | const client = new Client({ 6 | intents: ["GUILDS", "GUILD_MESSAGES", "GUILD_MEMBERS"], 7 | }); 8 | const { 9 | Default_Prefix, 10 | Token, 11 | Support, 12 | Color, 13 | Welcome_Images, 14 | GoodBye_Images, 15 | } = require("./config.js"); 16 | (client.commands = new Collection()), (client.aliases = new Collection()); 17 | 18 | client.on("ready", () => { 19 | console.log(`Bot Is Ready To Go!\nTag: ${client.user.tag}`); 20 | client.user.setActivity("Welcoming new members!", { type: "PLAYING" }); 21 | }); 22 | 23 | const categories = ["Config", "Other"]; 24 | 25 | for (const category of categories) { 26 | readdir(`./commands/${category}`, (error, files) => { 27 | if (error) throw error; 28 | for (const file of files) { 29 | if (!file.endsWith(".js")) 30 | return console.info(`${file}: does not ends with .js!`); 31 | const command = require(`./commands/${category}/${file}`); 32 | if (!command.help || !command.help.name) 33 | return console.info( 34 | `${file}: Does not have command.help or command.help.name` 35 | ); 36 | client.commands.set(command.help.name, command); 37 | command.help.aliases 38 | ? command.help.aliases.forEach((alias) => 39 | client.aliases.set(alias, command.help.name) 40 | ) 41 | : (command.help.aliases = null); 42 | } 43 | }); 44 | } 45 | 46 | client.on("messageCreate", async (message) => { 47 | if (message.author.bot || !message.guild || message.webhookID) return; 48 | 49 | const prefix = (await db.fetch(`P-${message.guild.id}`)) || Default_Prefix; 50 | 51 | if (!message.content.startsWith(prefix)) return; 52 | 53 | const args = message.content.slice(prefix.length).split(/ +/g), 54 | cmd = args.shift().toLowerCase(); 55 | const commandFromCmd = 56 | client.commands.get(cmd) || client.commands.get(client.aliases.get(cmd)); 57 | 58 | if (!commandFromCmd) return; 59 | 60 | try { 61 | commandFromCmd.help.run({ 62 | client, 63 | message, 64 | args, 65 | Color, 66 | Default_Prefix, 67 | Support, 68 | }); 69 | } catch (error) { 70 | console.log(error); 71 | return message.channel.send("Something went wrong, try again later"); 72 | } 73 | }); 74 | 75 | client.on("guildMemberAdd", async (member) => { 76 | const welcomeChannel = await db.fetch(`WC-${member.guild.id}`); 77 | if (!welcomeChannel) return; 78 | const welcomeMessage = ( 79 | (await db.fetch(`WM-${member.guild.id}`)) || 80 | `${member.user.username} Has Joined The Server!` 81 | ) 82 | .replace(//g, member.guild.name) 83 | .replace(//g, member.user.username) 84 | .replace(//g, `<@${member.user.id}>`); 85 | 86 | if (member.user.username.length > 25) 87 | member.user.username = member.user.username.slice(0, 25) + "..."; 88 | if (member.guild.name.length > 15) 89 | member.guild.name = member.guild.name.slice(0, 15) + "..."; 90 | 91 | const welcomeImageAttachment = await new canvas.Welcome() 92 | .setUsername(member.user.username) 93 | .setDiscriminator(member.user.discriminator) 94 | .setGuildName(member.guild.name) 95 | .setAvatar(member.user.displayAvatarURL({ dynamic: false, format: "jpg" })) 96 | .setMemberCount(member.guild.memberCount) 97 | .setBackground( 98 | Array.isArray(Welcome_Images) 99 | ? Welcome_Images[Math.floor(Math.random() * Welcome_Images.length)] 100 | : Welcome_Images || 101 | "https://images.wallpaperscraft.com/image/landscape_art_road_127350_1280x720.jpg" 102 | ) 103 | .toAttachment(); 104 | 105 | return client.channels.cache.get(welcomeChannel).send({ 106 | content: welcomeMessage, 107 | files: [ 108 | { 109 | attachment: welcomeImageAttachment.toBuffer(), 110 | name: "Welcome.png", 111 | }, 112 | ], 113 | }); 114 | }); 115 | 116 | client.on("guildMemberRemove", async (member) => { 117 | const goodbyeChannel = await db.fetch(`GC-${member.guild.id}`); 118 | if (!goodbyeChannel) return; 119 | const goodbyeMessage = ( 120 | (await db.fetch(`GM-${member.guild.id}`)) || 121 | `${member.user.username} Has Left The Server!` 122 | ) 123 | .replace(//g, member.guild.name) 124 | .replace(//g, member.user.username) 125 | .replace(//g, `<@${member.user.id}>`); 126 | 127 | if (member.user.username.length > 25) 128 | member.user.username = member.user.username.slice(0, 25) + "..."; 129 | if (member.guild.name.length > 15) 130 | member.guild.name = member.guild.name.slice(0, 15) + "..."; 131 | 132 | const goodbyeImageAttachment = await new canvas.Goodbye() 133 | .setUsername(member.user.username) 134 | .setDiscriminator(member.user.discriminator) 135 | .setGuildName(member.guild.name) 136 | .setAvatar(member.user.displayAvatarURL({ dynamic: false, format: "jpg" })) 137 | .setMemberCount(member.guild.memberCount) 138 | .setBackground( 139 | Array.isArray(GoodBye_Images) 140 | ? GoodBye_Images[Math.floor(Math.random() * GoodBye_Images.length)] 141 | : GoodBye_Images || 142 | "https://images.wallpaperscraft.com/image/cat_night_lights_74375_1280x720.jpg" 143 | ) 144 | .toAttachment(); 145 | 146 | return client.channels.cache.get(goodbyeChannel).send({ 147 | content: goodbyeMessage, 148 | files: [ 149 | { 150 | attachment: goodbyeImageAttachment.toBuffer(), 151 | name: "Goodbye.png", 152 | }, 153 | ], 154 | }); 155 | }); 156 | 157 | client 158 | .login(Token) 159 | .catch(() => 160 | console.log( 161 | `Probably an invalid bot token is provided, please check your bot token.` 162 | ) 163 | ); 164 | --------------------------------------------------------------------------------