├── .env.example ├── .gitignore ├── README.md ├── e.jpg ├── package-lock.json ├── package.json ├── src ├── commands │ ├── admin │ │ ├── leave.js │ │ ├── menu.js │ │ ├── pokemon.js │ │ ├── poll.js │ │ ├── roles.js │ │ ├── say-hello.js │ │ ├── stats.js │ │ ├── tags.js │ │ ├── ticket.js │ │ ├── welcome.js │ │ └── xp.js │ ├── general │ │ ├── autopages.js │ │ ├── button.js │ │ ├── calculator.js │ │ ├── canvas.js │ │ ├── embed.js │ │ ├── fight.js │ │ ├── hangman.js │ │ ├── help.js │ │ ├── mdn.js │ │ ├── pages.js │ │ ├── ping.js │ │ ├── poke.js │ │ ├── pokemons.js │ │ ├── profile.js │ │ ├── rank.js │ │ ├── rps.js │ │ ├── suggestion.js │ │ ├── timer.js │ │ └── trade.js │ └── owner │ │ ├── badge.js │ │ └── status.js ├── events │ ├── guildMemberAdd.2.js │ ├── guildMemberAdd.js │ ├── guildMemberRemove.2.js │ ├── guildMemberRemove.js │ ├── interactionCreate.2.js │ ├── interactionCreate.3.js │ ├── interactionCreate.4.js │ ├── interactionCreate.5.js │ ├── interactionCreate.js │ ├── messageCreate.2.js │ ├── messageCreate.3.js │ ├── messageCreate.js │ └── ready.js ├── index.js ├── models │ ├── badge.js │ ├── guildConfig.js │ ├── guildStats.js │ ├── polls.js │ ├── reactionRole.js │ ├── suggestion.js │ ├── ticket.js │ ├── tickets.js │ ├── timer.js │ ├── userConfig.js │ └── user_xp.js └── utility │ ├── commandInfo.js │ ├── createHangman.js │ ├── createLeave.js │ ├── createProfile.js │ ├── getMdnSource.js │ ├── pagination.js │ ├── pagination2.js │ ├── randomId.js │ ├── startTimer.js │ └── words └── tommy.ttf /.env.example: -------------------------------------------------------------------------------- 1 | TOKEN= 2 | MONGO_URI= -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .env 3 | e*.js -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Start 2 | - Run the following commands 3 | - `git clone https://github.com/KartikeSingh/tutorial_bot.git bot` 4 | - `cd bot` 5 | - `npm i` 6 | - `node .` bam done -------------------------------------------------------------------------------- /e.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KartikeSingh/tutorial_bot/e2ebdc078d4654c08c507be06eb63a0436d682b1/e.jpg -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tutorial_bot", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "keywords": [], 10 | "author": "Shisui", 11 | "license": "ISC", 12 | "dependencies": { 13 | "axios": "^0.24.0", 14 | "canvacord": "^5.2.3", 15 | "canvas": "^2.9.0", 16 | "discord-canvas": "^1.4.1", 17 | "discord-fight-game": "^1.0.1", 18 | "discord-purger": "^1.0.2", 19 | "discord-rock-paper-scissor": "^1.1.1", 20 | "discord.js": "^13.6.0", 21 | "dotenv": "^10.0.0", 22 | "eris": "^0.16.1", 23 | "express": "^4.17.3", 24 | "fast-xml-parser": "^4.0.6", 25 | "mathjs": "^10.4.0", 26 | "mongoose": "^6.2.0", 27 | "ms-prettify": "^1.2.1", 28 | "node-canvas-with-twemoji-and-discord-emoji": "^1.2.1", 29 | "node-emoji": "^1.11.0", 30 | "node-fetch": "^2.6.6", 31 | "pokecord": "^1.0.1", 32 | "puppeteer": "^13.5.1", 33 | "twitter": "^1.7.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /src/commands/admin/leave.js: -------------------------------------------------------------------------------- 1 | const guildConfig = require('../../models/guildConfig'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "leave", 6 | description: "Setup the leave configuration for your server", 7 | options: [{ 8 | name: "enable", 9 | description: "Enable the leave module for your server", 10 | type: 1, 11 | options: [{ 12 | name: "channel", 13 | description: "Channel where you want leave messages", 14 | type: 7, 15 | required: true 16 | }] 17 | }, { 18 | name: "disable", 19 | description: "Disable the leave module for your server", 20 | type: 1 21 | }, { 22 | name: "set-message", 23 | description: "Change the leave message for your server", 24 | type: 1, 25 | options: [{ 26 | name: "message", 27 | description: "The leave message, keys : {mention} {user} {server} {members}", 28 | type: 3, 29 | required: true 30 | }] 31 | }] 32 | }, 33 | permissions: ["MANAGE_SERVER"], 34 | 35 | run: async (client, interaction) => { 36 | await interaction.reply({ content: `${client.user.username} is thinking...` }); 37 | 38 | const data = await guildConfig.findOne({ id: interaction.guildId }) || await guildConfig.create({ id: interaction.guildId }), 39 | channel = interaction.options.getChannel("channel"), 40 | message = interaction.options.getString("message"), 41 | command = interaction.options.getSubcommand(); 42 | 43 | if (command === "enable") { 44 | if (data.leave.enable === true && data.leave.channel === channel.id) 45 | return interaction.editReply({ content: "The leave module is already enabled and the channel you provided is already the leave channel" }); 46 | 47 | if (!channel || (channel.type !== "GUILD_TEXT" && channel.type !== "GUILD_NEWS")) 48 | return interaction.editReply("Invalid channel was provided, Please provide a text channel") 49 | 50 | data.leave = { 51 | channel: channel.id, 52 | enable: true, 53 | message: data.leave.message 54 | } 55 | 56 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { leave: data.leave }); 57 | 58 | interaction.editReply({ content: `The leave module is now enabled and the leave channel is now setted to ${channel.toString()}` }); 59 | } else if (command === "disable") { 60 | if (data.leave.enable !== true) 61 | return interaction.editReply({ content: "The leave module is already disabled" }); 62 | 63 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "leave.enable": false }); 64 | 65 | interaction.editReply({ content: "The leave module is now disabled" }); 66 | } else if (command === "set-message") { 67 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "leave.message": message }); 68 | 69 | interaction.editReply({ 70 | content: `The leave message is changed${data.leave.enable === false ? " btw, the leave module is disabled" : ""}` 71 | }); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/commands/admin/menu.js: -------------------------------------------------------------------------------- 1 | const { MessageActionRow, MessageButton } = require('discord.js'); 2 | const menus = require('../../models/reactionRole'); 3 | 4 | module.exports = { 5 | data: { 6 | name: "menu", 7 | description: "Manage guild reaction role", 8 | options: [{ 9 | name: "create", 10 | type: 1, 11 | description: "Create a new role menu", 12 | options: [{ 13 | name: "name", 14 | description: "Name of the role menu", 15 | type: 3, 16 | required: true, 17 | }] 18 | }, { 19 | name: "delete", 20 | type: 1, 21 | description: "Delete a new role menu", 22 | options: [{ 23 | name: "name", 24 | description: "Name of the role menu", 25 | type: 3, 26 | required: true, 27 | }] 28 | }, { 29 | name: "start", 30 | type: 1, 31 | description: "Start a new role menu", 32 | options: [{ 33 | name: "name", 34 | description: "Name of the role menu", 35 | type: 3, 36 | required: true, 37 | }, { 38 | name: "channel", 39 | description: "Mention the channel", 40 | type: 7, 41 | required: true, 42 | }] 43 | }, { 44 | type: 1, 45 | name: "add-role", 46 | description: "Add a role in a reaction role menu", 47 | options: [{ 48 | name: "name", 49 | description: "Name of the role menu", 50 | type: 3, 51 | required: true, 52 | }, { 53 | name: "role", 54 | description: "Mention the role", 55 | type: 8, 56 | required: true, 57 | }] 58 | }, { 59 | type: 1, 60 | name: "remove-role", 61 | description: "Remove a role from a reaction role menu", 62 | options: [{ 63 | name: "name", 64 | description: "Name of the role menu", 65 | type: 3, 66 | required: true, 67 | }, { 68 | name: "role", 69 | description: "Mention the role", 70 | type: 8, 71 | required: true, 72 | }] 73 | }] 74 | }, 75 | permissions: ["MANAGE_SERVER", "MANAGE_ROLES"], 76 | 77 | /** 78 | * 79 | * @param {Client} client 80 | * @param {CommandInteraction} interaction 81 | */ 82 | run: async (client, interaction) => { 83 | await interaction.reply({ content: `${client.user.username} is thinking...` }); 84 | 85 | const option = interaction.options.getSubcommand(true).toLowerCase(); 86 | const name = interaction.options.getString("name")?.toLowerCase()?.trim(); 87 | const menu = await menus.findOne({ name, guild: interaction.guildId }); 88 | const my_role = interaction.guild.me.roles.highest.position; 89 | const role = interaction.options.getRole("role"); 90 | const channel = interaction.options.getChannel("channel"); 91 | 92 | if (option === "create") { 93 | if (menu) return interaction.editReply({ content: `Reaction Role menu already exists with that name, so next time use a different name.` }); 94 | 95 | await menus.create({ guild: interaction.guildId, name, message: "0" }); 96 | 97 | interaction.editReply({ content: `Role menu is created with name : \`${name}\`.` }); 98 | } else if (option === "delete") { 99 | if (!menu) return interaction.editReply({ content: `Reaction Role menu do not exists with that name, so next time use a actual menu name.` }); 100 | 101 | await menus.findOneAndDelete({ guild: interaction.guildId, name }); 102 | 103 | interaction.editReply({ content: `Role menu is delete with name : \`${name}\`.` }); 104 | } else if (option === "start") { 105 | if (channel.type !== "GUILD_TEXT" && channel.type !== "GUILD_NEWS") return interaction.editReply({ content: "Invalid channel was provided" }); 106 | if (menu.roles.length === 0) return interaction.editReply({ content: "This menu have 0 roles." }); 107 | 108 | let content = `Reaction Menu : **${menu.name}**\n\nReact to get yourself a role\n\n`, 109 | rows = [new MessageActionRow()], index; 110 | 111 | menu.roles.forEach((v, i) => { 112 | content += `> ${interaction.guild.emojis.cache.get(v.emoji)?.toString() || v.emoji} : \`${interaction.guild.roles.cache.get(v.role).name}\`\n\n` 113 | 114 | index = parseInt(i / 5); 115 | const button = new MessageButton({ 116 | customId: `reaction_role_${i}`, 117 | style: "PRIMARY", 118 | emoji: v.emoji, 119 | }); 120 | 121 | rows[index] ? rows[index].addComponents(button) : rows[index] = new MessageActionRow().addComponents(button) 122 | }) 123 | 124 | const msg = await channel.send({ content, components: rows }); 125 | 126 | await menus.findOneAndUpdate({ name, guild: interaction.guildId }, { message: msg.id }); 127 | 128 | interaction.editReply({ content: "Menu is started successfully" }); 129 | } else if (option === "add-role") { 130 | if (!menu) return interaction.editReply({ content: `Reaction Role menu do not exists with that name, so next time give a real menu name.` }); 131 | 132 | if (role.position >= my_role) return interaction.editReply({ content: `The provided role is above my highest role, so please put my role above it than try again.` }); 133 | 134 | const msg = await interaction.channel.send({ content: `React with the emoji you want for this role` }); 135 | 136 | const reactions = await msg.awaitReactions({ 137 | errors: ["time"], 138 | filter: (r, u) => u.id === interaction.user.id, 139 | max: 1, 140 | time: 300000 141 | }).catch(e => { }) 142 | 143 | const emoji = reactions.first()?.emoji; 144 | 145 | if (!emoji) return interaction.editReply({ content: "You took too much time to respond" }); 146 | 147 | if (menu.roles.some(v => v.role === role.id) || menu.roles.some(v => v.emoji === emoji.id || v.emoji === emoji.name)) return interaction.editReply({ content: `Reaction Role menu already have either the provided role or the emoji` }); 148 | 149 | menu.roles.push({ role: role.id, emoji: emoji.id || emoji.name }); 150 | 151 | await menus.findOneAndUpdate({ name, guild: interaction.guildId }, { roles: menu.roles }); 152 | 153 | interaction.editReply({ content: `Added role \`${role.name}\` with emoji : ${emoji.toString()} for menu : \`${menu.name}\`` }); 154 | await msg.delete(); 155 | } else if(option=== "remove-role") { 156 | if (!menu) return interaction.editReply({ content: `Reaction Role menu do not exists with that name, so next time give a real menu name.` }); 157 | 158 | if (!menu.roles.some(v => v.role === role.id)) return interaction.editReply({ content: `Reaction Role menu do not have this role as its part` }); 159 | 160 | menu.roles = menu.roles.filter((v) => v.role !== role.id); 161 | 162 | await menus.findOneAndUpdate({ name, guild: interaction.guildId }, { roles: menu.roles }); 163 | 164 | interaction.editReply({ content: `Remove role \`${role.name}\`from menu : \`${menu.name}\`` }); 165 | } 166 | } 167 | } -------------------------------------------------------------------------------- /src/commands/admin/pokemon.js: -------------------------------------------------------------------------------- 1 | const guildConfig = require('../../models/guildConfig'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "pokemon", 6 | description: "Setup the pokemon game for your server", 7 | options: [{ 8 | name: "enable-spawn", 9 | type: 1, 10 | description: "Enable the slash commands" 11 | }, { 12 | name: "disable-spawn", 13 | type: 1, 14 | description: "Disable the slash commands" 15 | }, { 16 | name: "spawn-after", 17 | type: 1, 18 | description: "Random pokemon spawning points", 19 | options: [{ 20 | name: "number", 21 | type: 4, 22 | description: "Number of points", 23 | required: true 24 | }] 25 | }, { 26 | name: "spawn-channel", 27 | type: 1, 28 | description: "Set the random pokemon spawn's channel", 29 | options: [{ 30 | name: "channel", 31 | type: 3, 32 | description: "Mention or give ID, 0 for same channel spawn", 33 | required: true 34 | }] 35 | }], 36 | }, 37 | permissions: ["MANAGE_SERVER"], 38 | 39 | run: async (client, interaction) => { 40 | await interaction.deferReply(); 41 | const data = await guildConfig.findOne({ id: interaction.guildId }) || await guildConfig.create({ id: interaction.guildId }); 42 | const command = interaction.options.getSubcommand(); 43 | 44 | if (command === "enable-spawn") { 45 | if (data.pokemon.spawn) return interaction.editReply({ content: `The pokemon spawning is already enabled` }); 46 | 47 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "pokemon.spawn": true }); 48 | 49 | interaction.editReply({ content: "Enabled pokemon spawning" }); 50 | } else if (command === "disable-spawn") { 51 | if (data.pokemon.spawn) return interaction.editReply({ content: `The pokemon spawning is already disabled` }); 52 | 53 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "pokemon.spawn": false }); 54 | 55 | interaction.editReply({ content: "disabled pokemon spawning" }); 56 | } else if (command === "spawn-after") { 57 | const points = interaction.options.getInteger("number"); 58 | 59 | if (points < 10) return interaction.editReply({ content: "The points can't be below 10" }); 60 | 61 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "pokemon.afterPoints": points }); 62 | 63 | interaction.editReply({ content: `Pokemon spawning required points are not setted to ${points}` }); 64 | } else if (command === "spawn-channel") { 65 | const raw = interaction.options.getString("channel"), channel = raw === "0" ? raw : interaction.guild.channels.cache.get(raw) || interaction.guild.channels.cache.get(raw.substring(2, raw.length - 1)); 66 | 67 | 68 | if (!channel || (channel.type !== "GUILD_TEXT" && channel.type !== "GUILD_NEWS")) return interaction.editReply("Invalid channel was provided, either type 0 for same channel, or mention / give id of a text channel") 69 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "pokemon.spawnAt": channel === "0" ? "0" : channel.id }); 70 | 71 | interaction.editReply({ content: `${channel === "0" ? "Setted the pokemon spawning to the same channel where latest message was sent" : `Now pokemons will spawn it <#${channel.id}>`}` }); 72 | } 73 | 74 | } 75 | } -------------------------------------------------------------------------------- /src/commands/admin/poll.js: -------------------------------------------------------------------------------- 1 | const { find } = require('node-emoji'); 2 | const polls = require("../../models/polls") 3 | const { MessageButton, MessageActionRow } = require('discord.js'); 4 | 5 | module.exports = { 6 | data: { 7 | name: "poll", 8 | description: "Manage polls of your server", 9 | options: [{ 10 | name: "create", 11 | type: 1, 12 | description: "Create a poll", 13 | options: [{ 14 | name: "question", 15 | type: 3, 16 | required: true, 17 | description: "The question of the poll" 18 | }, { 19 | name: "channel", 20 | type: 7, 21 | required: true, 22 | description: "The channel where you want create the poll" 23 | }, { 24 | name: "options", 25 | type: 3, 26 | required: true, 27 | description: "The choices of this poll, seprate them by |", 28 | }, { 29 | name: "custom-emojis", 30 | type: 3, 31 | required: false, 32 | description: "Custom emojis for the chocies, seprate them by |" 33 | }] 34 | }, { 35 | name: "end", 36 | type: 1, 37 | description: "End a poll", 38 | options: [{ 39 | name: "id", 40 | type: 3, 41 | required: true, 42 | description: "Message ID of the poll" 43 | }] 44 | }], 45 | }, 46 | timeout: 5000, 47 | permissions: ["MANAGE_GUILD"], 48 | 49 | run: async (client, interaction) => { 50 | await interaction.deferReply(); 51 | 52 | let _emoji = ["🇦", "🇧", "🇨", "🇩", "🇪", "🇫", "🇬", "🇭", "🇮", "🇯", "🇰", "🇱", "🇲", "🇳", "🇴", "🇵", "🇶", "🇷", "🇸", "🇹", "🇺", "🇻", "🇼", "🇽", "🇾", "🇿"], 53 | emojis = []; 54 | 55 | let option = interaction.options.getSubcommand(), 56 | channel = interaction.options.getChannel("channel"), 57 | rawOptions = interaction.options.getString("options"), 58 | cEmojis = interaction.options.getString("custom-emojis") || "", 59 | id = interaction.options.getString("id"), 60 | question = interaction.options.getString("question"), 61 | poll = await polls.findOne({ message: id }); 62 | 63 | if (option === "create") { 64 | rawOptions = rawOptions.split("|"); 65 | cEmojis = cEmojis?.trim()?.replace(/ +/g, "")?.split("|"); 66 | 67 | if (rawOptions.length < 2 || rawOptions.length > 25) return interaction.editReply({ 68 | embeds: [{ 69 | color: "RED", 70 | title: "❌ Invalid Options", 71 | description: "You need at least 2 options and a maximum of 25 options, You need to seprate options via `|`" 72 | }] 73 | }); 74 | 75 | const rows = [new MessageActionRow()]; 76 | 77 | for (let i = 0; i < rawOptions.length; i++) { 78 | let ind = Math.floor(i / 5); 79 | 80 | emojis.push(fixEmoji(client, cEmojis[i]) || _emoji[i]); 81 | 82 | const button = new MessageButton({ 83 | customId: emojis[i], 84 | emoji: emojis[i], 85 | label: "0", 86 | style: "SECONDARY" 87 | }); 88 | 89 | rows[ind] ? rows[ind].addComponents(button) : rows[ind] = new MessageActionRow({ 90 | components: [button] 91 | }); 92 | } 93 | 94 | channel.send({ 95 | embeds: [{ 96 | color: "BLUE", 97 | title: question.slice(0, 256), 98 | description: rawOptions.map((v, i) => `${cEmojis[i] || emojis[i]} ${v}`).join("\n"), 99 | timestamp: Date.now(), 100 | footer: { 101 | text: `Poll Started At` 102 | } 103 | }], 104 | components: rows 105 | }).then(async (v) => { 106 | await polls.create({ 107 | question, 108 | message: v.id, 109 | channel: channel.id, 110 | guild: interaction.guildId, 111 | votes: {}, 112 | voters: [], 113 | emojis 114 | }); 115 | 116 | interaction.editReply({ 117 | embeds: [{ 118 | color: "GREEN", 119 | title: "✅ Poll Created", 120 | description: `Check the poll [here](${v.url})` 121 | }] 122 | }); 123 | }).catch((e) => { 124 | interaction.editReply({ 125 | embeds: [{ 126 | color: "RED", 127 | title: "❌ Unable To Create The Poll", 128 | }] 129 | }); 130 | }) 131 | } else if (option === "end") { 132 | if (!poll) return interaction.editReply({ 133 | embeds: [{ 134 | color: "RED", 135 | title: "❌ Invalid Poll Message ID", 136 | }] 137 | }); 138 | 139 | if (poll.ended) return interaction.editReply({ 140 | embeds: [{ 141 | color: "RED", 142 | title: "❌ Poll is already Ended", 143 | }] 144 | }); 145 | 146 | const msg = await interaction.guild.channels.cache.get(poll.channel).messages.fetch(id); 147 | 148 | if (!msg) return interaction.editReply({ 149 | embeds: [{ 150 | color: "RED", 151 | title: "❌ Poll Not Endable", 152 | description: `Poll message is deleted, So it is no longer endable` 153 | }] 154 | }); 155 | 156 | const opt = msg.embeds[0].description?.split("\n"); 157 | 158 | const x = Object.entries(poll.votes)?.sort((a, b) => b[1] - a[1]) 159 | 160 | let winner = opt.filter(v => v.includes(x[0][0])); 161 | 162 | interaction.editReply({ 163 | embeds: [{ 164 | color: "GREEN", 165 | title: "Poll Ended" 166 | }] 167 | }) 168 | 169 | msg.edit({ 170 | components: [], 171 | embeds: [{ 172 | title: msg.embeds[0].title, 173 | color: "RED", 174 | description: `**Poll ended**\nThe most voted option got ${x[0][1]} votes and it was:\n${winner}`, 175 | timestamp: Date.now(), 176 | footer: { 177 | text: `Poll Ended At` 178 | } 179 | }] 180 | }); 181 | 182 | await polls.findOneAndUpdate({ message: id }, { ended: true }); 183 | } 184 | } 185 | } 186 | 187 | function fixEmoji(client, emj = "") { 188 | const e = find(emj)?.emoji, e2 = client.emojis.cache.find(v => v.toString() === emj); 189 | 190 | return e2?.id || e; 191 | } -------------------------------------------------------------------------------- /src/commands/admin/roles.js: -------------------------------------------------------------------------------- 1 | const froms = ["all", "human", "bot"]; 2 | 3 | module.exports = { 4 | data: { 5 | name: "roles", 6 | description: "Manage roles of the server", 7 | options: [{ 8 | name: "action", 9 | type: 3, 10 | required: true, 11 | description: "Choose the action", 12 | choices: [{ 13 | name: "Give Role", 14 | value: "1" 15 | }, { 16 | name: "Take Role", 17 | value: "2" 18 | }] 19 | }, { 20 | name: "from", 21 | description: "The category you want to manipulate, give role ID, or type human or bot or all", 22 | required: true, 23 | type: 3 24 | }, { 25 | name: "for", 26 | description: "This is the role you want to give or take", 27 | required: true, 28 | type: 8 29 | }], 30 | }, 31 | timeout: 100000, 32 | permissions: ["ADMINISTRATOR"], 33 | 34 | run: async (client, interaction) => { 35 | const action = interaction.options.getString("action"), 36 | from = interaction.options.getString("from")?.toLowerCase(), 37 | _for = interaction.options.getRole("for"); 38 | 39 | if (!froms.includes(from) && !interaction.guild.roles.cache.get(/\d+/.exec(from) + "")) return interaction.reply({ 40 | embeds: [{ 41 | title: "❌ Invalid from value", 42 | color: "RED", 43 | description: "It should be the role ID, against which you want to take the action\nOr you can type `huamn` for taking action against humans, `bot` for the bots and `all` for everyone" 44 | }] 45 | }); 46 | 47 | if (_for.position > interaction.guild.me.roles.highest.position && !interaction.guild.me.permissions.has("MANAGE_ROLES")) return interaction.reply({ 48 | embeds: [{ 49 | title: "❌ Invalid Permissions", 50 | color: "RED", 51 | description: "Either I do not have Manage Role permission, or the provided role is above my highest role" 52 | }] 53 | }); 54 | 55 | let filter, ind = froms.indexOf(from); 56 | 57 | if (ind === 0) filter = (m) => m.roles.cache.has(_for.id) === (action !== "1") 58 | else if (ind === 1) filter = (m) => !m.user.bot && m.roles.cache.has(_for.id) === (action !== "1") 59 | else if (ind === 2) filter = (m) => m.user.bot && m.roles.cache.has(_for.id) === (action !== "1") 60 | else filter = (m) => m.roles.cache.has(/\d+/.exec(from) + "") && m.roles.cache.has(_for.id) === (action !== "1"); 61 | 62 | const members = (await interaction.guild.members.fetch({ force: true })).filter(filter)?.toJSON(); 63 | 64 | await interaction.reply({ 65 | embeds: [{ 66 | color: "BLUE", 67 | title: `Changing roles for ${members.length} member` 68 | }] 69 | }); 70 | 71 | 72 | for (let i = 0; i < members.length; i++) { 73 | await members[i].roles[action === "1" ? "add" : "remove"](_for); 74 | } 75 | 76 | interaction.editReply({ 77 | embeds: [{ 78 | color: "GREEN", 79 | title: "✅ Roles changed successfully" 80 | }] 81 | }) 82 | } 83 | } -------------------------------------------------------------------------------- /src/commands/admin/say-hello.js: -------------------------------------------------------------------------------- 1 | const { Interaction } = require("discord.js"); 2 | 3 | module.exports = { 4 | data: { 5 | name: "say-hello", 6 | description: "", 7 | type: 2, 8 | }, 9 | permissions: ["MANAGE_SERVER"], 10 | 11 | /** 12 | * 13 | * @param {*} client 14 | * @param {Interaction} interaction 15 | */ 16 | run: async (client, interaction) => { 17 | const member = interaction.guild.members.cache.get(interaction.targetId); 18 | 19 | member.user.send({ content: `Hello from ${interaction.user.toString()}` }).then(v => { 20 | interaction.reply({ content: `Successfuly greeted ${member.user.toString()}`, ephermal: true }); 21 | }).catch(e => { 22 | interaction.reply({ content: `Unable to greete ${member.user.toString()}`, ephermal: true }); 23 | 24 | }) 25 | } 26 | } -------------------------------------------------------------------------------- /src/commands/admin/stats.js: -------------------------------------------------------------------------------- 1 | const { CommandInteraction } = require('discord.js'); 2 | const stats = require('../../models/guildStats'); 3 | 4 | module.exports = { 5 | data: { 6 | name: "stats", 7 | description: "Configure the stats for your server", 8 | options: [{ 9 | name: "type", 10 | type: 3, 11 | required: true, 12 | description: "What kind of stats you want to setup", 13 | choices: [{ 14 | name: "members-stats", 15 | value: "members" 16 | }] 17 | }, { 18 | name: "channel", 19 | type: 7, 20 | required: false, 21 | description: "The voice channel in which you wanna show the stats" 22 | }] 23 | }, 24 | permissions: ["MANAGE_GUILD", "MANAGE_CHANNELS"], 25 | 26 | /** 27 | * 28 | * @param {*} client 29 | * @param {CommandInteraction} interaction 30 | */ 31 | run: async (client, interaction) => { 32 | interaction.deferReply(); 33 | const channel = interaction.options.getChannel("channel") || await interaction.guild.channels.create(`Members : ${interaction.guild.memberCount}`, { 34 | reason: "for stats", 35 | type: "GUILD_VOICE" 36 | }); 37 | 38 | const newData = { guild: interaction.guildId }; 39 | newData[interaction.options.getString("type")] = channel.id; 40 | 41 | const data = await stats.findOneAndUpdate({ guild: interaction.guildId }, newData, { new: true }) || await stats.create(newData); 42 | 43 | interaction.editReply({ content: `Added stats for ${interaction.options.getString("type")}` }); 44 | } 45 | } -------------------------------------------------------------------------------- /src/commands/admin/tags.js: -------------------------------------------------------------------------------- 1 | const configs = require('../../models/guildConfig'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "tags", 6 | description: "Configure the tags of your server", 7 | options: [{ 8 | name: 'add', 9 | description: "Add a tag", 10 | type: 1, 11 | options: [{ 12 | name: "name", 13 | description: "The name of the tag", 14 | type: 3, 15 | required: true 16 | }, { 17 | name: "response", 18 | description: "The response for this tag", 19 | type: 3, 20 | required: true 21 | }, { 22 | name: "case", 23 | description: "Whether the tag is case sensitive or not", 24 | type: 5, 25 | required: false 26 | }, { 27 | name: "include", 28 | description: "Whether the tag should be triggered when it is incldued in the message", 29 | type: 5, 30 | required: false 31 | }, { 32 | name: "embed", 33 | description: "Whether the response should be a embed", 34 | type: 5, 35 | required: false 36 | }] 37 | }, { 38 | name: 'remove', 39 | type: 1, 40 | description: "Remove a tag", 41 | options: [{ 42 | name: "name", 43 | description: "The name of the tag", 44 | type: 3, 45 | required: true 46 | }] 47 | }, { 48 | name: 'edit', 49 | description: "Edit a tag", 50 | type: 1, 51 | options: [{ 52 | name: "name", 53 | description: "The name of the tag you want to edit", 54 | type: 3, 55 | required: true 56 | }, { 57 | name: "new-name", 58 | description: "The new name for this tag", 59 | type: 3, 60 | required: false 61 | }, { 62 | name: "response", 63 | description: "The new response for this tag", 64 | type: 3, 65 | required: false 66 | }, { 67 | name: "case", 68 | description: "Whether the tag is case sensitive or not", 69 | type: 5, 70 | required: false 71 | }, { 72 | name: "include", 73 | description: "Whether the tag should be triggered when it is incldued in the message", 74 | type: 5, 75 | required: false 76 | }, { 77 | name: "embed", 78 | description: "Whether the response should be a embed", 79 | type: 5, 80 | required: false 81 | }] 82 | }] 83 | }, 84 | permissions: ["MANAGE_SERVER"], 85 | 86 | run: async (client, interaction) => { 87 | await interaction.reply({ content: "Compiling the inputs" }); 88 | 89 | const data = await configs.findOne({ id: interaction.guild.id }) || await configs.create({ id: interaction.guild.id }), 90 | command = interaction.options.getSubcommand(), 91 | name = interaction.options.getString("name"), 92 | new_name = interaction.options.getString("new-name"), 93 | response = interaction.options.getString("response"), 94 | case_ = interaction.options.getBoolean("case"), 95 | include = interaction.options.getBoolean("include"), 96 | embed = interaction.options.getBoolean("embed"); 97 | 98 | if (command === "add") { 99 | if (data?.tags?.filter(v => v.name.toLowerCase() === name.toLowerCase()).length > 0) return interaction.editReply({ content: `You already have a tag with the name \`${name}\`` }) 100 | 101 | interaction.editReply({ content: `New tag is added with name \`${name}\`` }) 102 | 103 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { 104 | $push: { 105 | tags: { 106 | name, 107 | response, 108 | embed, 109 | case: case_, 110 | include, 111 | } 112 | } 113 | }) 114 | } else if (command === "remove") { 115 | if (data?.tags?.filter(v => v.name.toLowerCase() === name.toLowerCase()).length === 0) return interaction.editReply({ content: `You do not have a tag with the name \`${name}\`` }) 116 | 117 | interaction.editReply({ content: `the tag with name \`${name}\` is removed` }) 118 | 119 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { tags: data.tags.filter(v => v.name.toLowerCase() !== name.toLowerCase()) }) 120 | } else if (command === "edit") { 121 | let tag = data?.tags?.filter(v => v.name.toLowerCase() === name.toLowerCase())[0]; 122 | if (!tag) return interaction.editReply({ content: `You do not have a tag with the name \`${name}\`` }) 123 | 124 | interaction.editReply({ content: `The tag with name \`${name}\` is edited successfully ✔` }) 125 | 126 | const tags = data.tags.filter(v => v.name.toLowerCase() !== name.toLowerCase()); 127 | 128 | tags.push({ 129 | name: new_name || tag.name, 130 | response: response || tag.response, 131 | embed: typeof (embed) !== "boolean" ? tag.embed : embed, 132 | case: typeof (case_) !== "boolean" ? tag.case : case_, 133 | include: typeof (include) !== "boolean" ? tag.include : include, 134 | }) 135 | 136 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { 137 | tags 138 | }) 139 | } 140 | } 141 | } -------------------------------------------------------------------------------- /src/commands/admin/ticket.js: -------------------------------------------------------------------------------- 1 | const tickets = require('../../models/tickets'); 2 | const ticket = require('../../models/ticket'); 3 | const { MessageEmbed, MessageActionRow, MessageButton, CommandInteraction } = require('discord.js'); 4 | 5 | module.exports = { 6 | data: { 7 | name: "ticket", 8 | description: "COnfigure your server's tickets / panels", 9 | options: [{ 10 | name: "create", 11 | type: 1, 12 | description: "Create a ticket panel", 13 | options: [{ 14 | name: "panel-name", 15 | description: "The name of the panel you want to create", 16 | type: 3, 17 | required: true 18 | }] 19 | }, { 20 | name: "remove", 21 | type: 1, 22 | description: "Remove a ticket panel", 23 | options: [{ 24 | name: "panel-name", 25 | description: "The name of the panel you want to remove", 26 | type: 3, 27 | required: true 28 | }] 29 | }, { 30 | name: "start", 31 | type: 1, 32 | description: "Start a ticket panel", 33 | options: [{ 34 | name: "panel-name", 35 | description: "The name of the panel you want to start", 36 | type: 3, 37 | required: true 38 | }, { 39 | name: "channel", 40 | description: "The channel where you want to start the panel", 41 | required: true, 42 | type: 7 43 | }] 44 | }, { 45 | name: "close", 46 | type: 1, 47 | description: "Close a openen ticket for your discord server", 48 | }, { 49 | name: "re-open", 50 | type: 1, 51 | description: "Re-open a closed ticket for your discord server", 52 | }, { 53 | name: "delete", 54 | type: 1, 55 | description: "Delete a ticket for your discord server", 56 | }, { 57 | name: "logs-disable", 58 | type: 1, 59 | description: "Disable ticket logs for your server", 60 | options: [{ 61 | name: "panel-name", 62 | description: "The name of the panel", 63 | type: 3, 64 | required: true 65 | }] 66 | }, { 67 | name: "logs-enable", 68 | type: 1, 69 | description: "Enable ticket logs for your server", 70 | options: [{ 71 | name: "panel-name", 72 | description: "The name of the panel", 73 | type: 3, 74 | required: true 75 | }, { 76 | name: "channel", 77 | type: 7, 78 | description: "channel to send ticket logs for your server", 79 | required: true 80 | }] 81 | }, { 82 | name: "moderator-add", 83 | type: 1, 84 | description: "Add a moderator role for your server's ticket panel", 85 | options: [{ 86 | name: "panel-name", 87 | description: "The name of the panel", 88 | type: 3, 89 | required: true 90 | }, { 91 | name: "role", 92 | type: 8, 93 | description: "The role to add as a moderator", 94 | required: true 95 | }] 96 | }, { 97 | name: "moderator-remove", 98 | type: 1, 99 | description: "Remove a moderator role for your server's ticket panel", 100 | options: [{ 101 | name: "panel-name", 102 | description: "The name of the panel", 103 | type: 3, 104 | required: true 105 | }, { 106 | name: "role", 107 | type: 8, 108 | description: "The role to remove from moderator role", 109 | required: true 110 | }] 111 | }, { 112 | name: "banned-add", 113 | type: 1, 114 | description: "Add a banned role for your server's ticket panel", 115 | options: [{ 116 | name: "panel-name", 117 | description: "The name of the panel", 118 | type: 3, 119 | required: true 120 | }, { 121 | name: "role", 122 | type: 8, 123 | description: "The role to add as a banned", 124 | required: true 125 | }] 126 | }, { 127 | name: "banned-remove", 128 | type: 1, 129 | description: "Remove a banned role for your server's ticket panel", 130 | options: [{ 131 | name: "panel-name", 132 | description: "The name of the panel", 133 | type: 3, 134 | required: true 135 | }, { 136 | name: "role", 137 | type: 8, 138 | description: "The role to remove from banned role", 139 | required: true 140 | }] 141 | }, { 142 | name: "max-ticket", 143 | type: 1, 144 | description: "Set maximum number of tickets a user can create in a pannel", 145 | options: [{ 146 | name: "panel-name", 147 | description: "The name of the panel", 148 | type: 3, 149 | required: true 150 | }, { 151 | name: "limit", 152 | type: 4, 153 | description: "The number of tickets a user can create", 154 | required: true 155 | }] 156 | }] 157 | }, 158 | permissions: ["MANAGE_SERVER"], 159 | 160 | /** 161 | * 162 | * @param {*} client 163 | * @param {CommandInteraction} interaction 164 | * @returns 165 | */ 166 | run: async (client, interaction) => { 167 | await interaction.deferReply(); 168 | 169 | const name = interaction.options.getString("panel-name"), 170 | ticketData = await ticket.findOne({ guild: interaction.guildId, channel: interaction.channel.id }) || {}, 171 | data = await tickets.findOne({ guild: interaction.guildId, name }) || await tickets.findOne({ guild: interaction.guildId, name: ticketData.panel }), 172 | command = interaction.options.getSubcommand(), 173 | channel = interaction.options.getChannel("channel"), 174 | role = interaction.options.getRole("role"), 175 | limit = interaction.options.getInteger("limit"), 176 | modCommands = ["close", "reopen", "delete"], 177 | permissions = ["MANAGA_SERVER", "MANAGE_CHANNELS"], 178 | member = interaction.guild.members.cache.get(ticketData?.user); 179 | 180 | if (modCommands.includes(command) && !data?.moderators.some(v => interaction.member.roles.cache.has(v)) && !permissions.some(v => interaction.member.permissions.has(v))) 181 | return interaction.editReply({ content: `You can not use this command, because you neither have moderator role for this pannel nor any of the following permission ${permissions.join(", ")}` }) 182 | 183 | if (!modCommands.includes(command) && !permissions.some(v => interaction.member.permissions.has(v))) 184 | return interaction.editReply({ content: `You can not use this command, because you do not have any of the following permission ${permissions.join(", ")}` }) 185 | 186 | if (command === "create") { 187 | if (data) return interaction.editReply({ content: `You already have a panel with name \`${name}\`` }); 188 | await tickets.create({ name, guild: interaction.guildId }); 189 | 190 | interaction.editReply({ content: `I created a panel with name \`${name}\`` }); 191 | } else if (command === "remove") { 192 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 193 | await tickets.findOneAndDelete({ name, guild: interaction.guildId }); 194 | 195 | interaction.editReply({ content: `I delete the panel with name \`${name}\`` }); 196 | } else if (command === "start") { 197 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 198 | if (channel.type !== "GUILD_TEXT") return interaction.editReply({ content: "Channel should be a text channel" }); 199 | 200 | const embed = new MessageEmbed().setTitle(`Panel : ${name}`).setDescription("click on 📩 to create a ticket"); 201 | const row = new MessageActionRow().addComponents(new MessageButton().setCustomId("ticket_button").setLabel("Create Ticket").setEmoji("📩").setStyle("PRIMARY")); 202 | 203 | channel?.send({ embeds: [embed], components: [row] }).then(async v => { 204 | console.log(v) 205 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { message: v.id }); 206 | interaction.editReply({ content: `Successfully started the panel with name : \`${name}\` in ${channel.toString()}` }) 207 | }).catch(e => { 208 | interaction.editReply({ content: `Unable to send the message in ${channel.toString()}` }) 209 | }) 210 | } else if (command === "logs-disable") { 211 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 212 | 213 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { logs: "0" }); 214 | interaction.editReply({ content: "Successfully disabled Ticket logs for this server." }); 215 | } else if (command === "logs-enable") { 216 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 217 | 218 | if (channel.type !== "GUILD_TEXT") return interaction.editReply({ content: "Channel should be a text channel" }); 219 | 220 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { logs: channel.id }); 221 | interaction.editReply({ content: "Successfully enable Ticket logs for this server in " + channel.toString() }); 222 | } else if (command === "moderator-add") { 223 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 224 | if (data.moderators?.includes(role.id)) return interaction.editReply({ content: `This role is already a moderator role in the panel \`${data.name}\`` }); 225 | 226 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { $push: { moderators: role.id } }); 227 | interaction.editReply({ content: `Successfully added **${role.name}** as a moderator role in the panel \`${data.name}\`` }); 228 | } else if (command === "moderator-remove") { 229 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 230 | if (!data.moderators?.includes(role.id)) return interaction.editReply({ content: `This role is not a moderator role in the panel \`${data.name}\`` }); 231 | 232 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { $pull: { moderators: { $in: role.id } } }); 233 | interaction.editReply({ content: `Successfully remove **${role.name}** from moderator roles in the panel \`${data.name}\`` }); 234 | } else if (command === "banned-add") { 235 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 236 | if (data.banned?.includes(role.id)) return interaction.editReply({ content: `This role is already a banned role in the panel \`${data.name}\`` }); 237 | 238 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { $push: { banned: role.id } }); 239 | interaction.editReply({ content: `Successfully added **${role.name}** as a banned role in the panel \`${data.name}\`` }); 240 | } else if (command === "banned-remove") { 241 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 242 | if (!data.banned?.includes(role.id)) return interaction.editReply({ content: `This role is not a banned role in the panel \`${data.name}\`` }); 243 | 244 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { $pull: { banned: { $in: role.id } } }); 245 | interaction.editReply({ content: `Successfully remove **${role.name}** from banned roles in the panel \`${data.name}\`` }); 246 | } else if (command === "max-ticket") { 247 | if (!data) return interaction.editReply({ content: `You do not have a panel with name \`${name}\`` }); 248 | if (limit < 1 || limit > 1000) return interaction.editReply({ content: "The maximum ticket limit can't be less than 1 or greater than 1000" }); 249 | 250 | await tickets.findOneAndUpdate({ guild: interaction.guildId, name }, { max: limit }); 251 | interaction.editReply({ content: `Successfully setted maximum ticket limit to **${limit}** in the panel \`${data.name}\`` }); 252 | } else { 253 | if (!ticketData || !ticketData.panel) return interaction.editReply({ content: "This is not a ticket channel." }); 254 | 255 | let user = interaction.guild.members.cache.get(ticketData?.user); 256 | 257 | if (command === "close") { 258 | if (ticketData.closed) return interaction.editReply({ content: "This ticket is already closed" }); 259 | interaction.channel.permissionOverwrites.create(user, { 260 | VIEW_CHANNEL: false, 261 | SEND_MESSAGES: false, 262 | }); 263 | 264 | await ticket.findOneAndUpdate({ channel: interaction.channel.id }, { closed: true }); 265 | 266 | interaction.editReply({ content: "This ticket is now closed" }); 267 | 268 | interaction.guild.channels.cache.get(data.logs)?.send({ 269 | embeds: [{ 270 | title: "Ticket closed", 271 | timestamps: Date.now(), 272 | fields: [{ 273 | name: "Panel", 274 | value: data.name, 275 | inline: true 276 | }, { 277 | name: "User", 278 | value: member.user.username, 279 | inline: true 280 | }, { 281 | name: "Ticket", 282 | value: interaction.channel.toString(), 283 | inline: true 284 | }, { 285 | name: "\u200b", 286 | value: "\u200b", 287 | inline: true 288 | }, { 289 | name: "Moderator", 290 | value: interaction.user.username, 291 | inline: true 292 | }] 293 | }] 294 | }) 295 | } else if (command === "re-open") { 296 | if (!ticketData.closed) return interaction.editReply({ content: "This ticket is not closed" }); 297 | interaction.channel.permissionOverwrites.create(user, { 298 | VIEW_CHANNEL: true, 299 | SEND_MESSAGES: true, 300 | }); 301 | 302 | await ticket.findOneAndUpdate({ channel: interaction.channel.id }, { closed: false }); 303 | 304 | interaction.editReply({ content: "This ticket is now re-opened" }); 305 | interaction.guild.channels.cache.get(data.logs)?.send({ 306 | embeds: [{ 307 | title: "Ticket re-opened", 308 | timestamps: Date.now(), 309 | fields: [{ 310 | name: "Panel", 311 | value: data.name, 312 | inline: true 313 | }, { 314 | name: "User", 315 | value: member.user.username, 316 | inline: true 317 | }, { 318 | name: "Ticket", 319 | value: interaction.channel.toString(), 320 | inline: true 321 | }, { 322 | name: "\u200b", 323 | value: "\u200b", 324 | inline: true 325 | }, { 326 | name: "Moderator", 327 | value: interaction.user.username, 328 | inline: true 329 | }] 330 | }] 331 | }) 332 | } else if (command === "delete") { 333 | interaction.editReply({ content: "This ticket is closed and channel will be deleted in few seconds" }); 334 | await ticket.findOneAndDelete({ channel: interaction.channel.id }); 335 | await new Promise(res => setTimeout(res, 2000)); 336 | 337 | interaction.channel.delete().catch(e => { 338 | interaction.editReply({ content: "Ticket was deleted from database but i was unable to delete this channel" }); 339 | }) 340 | interaction.guild.channels.cache.get(data.logs)?.send({ 341 | embeds: [{ 342 | title: "Ticket deleted", 343 | timestamps: Date.now(), 344 | fields: [{ 345 | name: "Panel", 346 | value: data.name, 347 | inline: true 348 | }, { 349 | name: "User", 350 | value: member.user.username, 351 | inline: true 352 | }, { 353 | name: "Ticket", 354 | value: interaction.channel.toString(), 355 | inline: true 356 | }, { 357 | name: "\u200b", 358 | value: "\u200b", 359 | inline: true 360 | }, { 361 | name: "Moderator", 362 | value: interaction.user.username, 363 | inline: true 364 | }] 365 | }] 366 | }) 367 | } 368 | } 369 | } 370 | } -------------------------------------------------------------------------------- /src/commands/admin/welcome.js: -------------------------------------------------------------------------------- 1 | const guildConfig = require('../../models/guildConfig'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "welcome", 6 | description: "Setup the welcome configuration for your server", 7 | options: [{ 8 | name: "enable", 9 | description: "Enable the welcome module for your server", 10 | type: 1, 11 | options: [{ 12 | name: "channel", 13 | description: "Channel where you want welcome messages", 14 | type: 7, 15 | required: true 16 | }] 17 | }, { 18 | name: "disable", 19 | description: "Disable the welcome module for your server", 20 | type: 1 21 | }, { 22 | name: "set-message", 23 | description: "Change the welcome message for your server", 24 | type: 1, 25 | options: [{ 26 | name: "message", 27 | description: "The welcome message, keys : {mention} {user} {server} {members}", 28 | type: 3, 29 | required: true 30 | }] 31 | }] 32 | }, 33 | permissions: ["MANAGE_SERVER"], 34 | 35 | run: async (client, interaction) => { 36 | await interaction.reply({ content: `${client.user.username} is thinking...` }); 37 | 38 | const data = await guildConfig.findOne({ id: interaction.guildId }) || await guildConfig.create({ id: interaction.guildId }), 39 | channel = interaction.options.getChannel("channel"), 40 | message = interaction.options.getString("message"), 41 | command = interaction.options.getSubcommand(); 42 | 43 | if (command === "enable") { 44 | if (data.welcome.enable === true && data.welcome.channel === channel.id) 45 | return interaction.editReply({ content: "The welcome module is already enabled and the channel you provided is already the welcome channel" }); 46 | 47 | if (!channel || (channel.type !== "GUILD_TEXT" && channel.type !== "GUILD_NEWS")) 48 | return interaction.editReply("Invalid channel was provided, Please provide a text channel") 49 | 50 | data.welcome = { 51 | channel: channel.id, 52 | enable: true, 53 | message: data.welcome.message 54 | } 55 | 56 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { welcome: data.welcome }); 57 | 58 | interaction.editReply({ content: `The welcome module is now enabled and the welcome channel is now setted to ${channel.toString()}` }); 59 | } else if (command === "disable") { 60 | if (data.welcome.enable !== true) 61 | return interaction.editReply({ content: "The welcome module is already disabled" }); 62 | 63 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "welcome.enable": false }); 64 | 65 | interaction.editReply({ content: "The welcome module is now disabled" }); 66 | } else if (command === "set-message") { 67 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { "welcome.message": message }); 68 | 69 | interaction.editReply({ 70 | content: `The welcome message is changed${data.welcome.enable === false ? " btw, the welcome module is disabled" : ""}` 71 | }); 72 | } 73 | } 74 | } -------------------------------------------------------------------------------- /src/commands/admin/xp.js: -------------------------------------------------------------------------------- 1 | const configs = require('../../models/guildConfig'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "xp", 6 | description: "Manage xp system of your server", 7 | options: [{ 8 | name: "enable", 9 | type: 1, 10 | description: "Enable the XP system in your server", 11 | }, { 12 | name: "disable", 13 | type: 1, 14 | description: "Disable the XP system in your server", 15 | }, { 16 | name: "rate", 17 | type: 1, 18 | description: "Change the XP rate of your server", 19 | options: [{ 20 | name: "rate", 21 | type: 4, 22 | required: true, 23 | description: "The percantage of XP Rate" 24 | }] 25 | }, { 26 | name: "limits", 27 | type: 1, 28 | description: "Change the XP icrement limits for your server", 29 | options: [{ 30 | name: "up-limit", 31 | type: 4, 32 | required: false, 33 | description: "The maximum XP increment" 34 | }, { 35 | name: "down-limit", 36 | type: 4, 37 | required: false, 38 | description: "The minimum XP increment" 39 | }] 40 | }, { 41 | name: "level-up-message", 42 | type: 1, 43 | description: "Change the level up message for your server", 44 | options: [{ 45 | name: "message", 46 | type: 3, 47 | required: true, 48 | description: "The new level up message, you can use these: {level} {xp} {mention}" 49 | }] 50 | }, { 51 | name: "level-up-message-enable", 52 | type: 1, 53 | description: "Enable the XP level up mesage in your server", 54 | }, { 55 | name: "level-up-message-disable", 56 | type: 1, 57 | description: "Disable the XP level up mesage in your server", 58 | }, { 59 | name: "level-up-channel", 60 | type: 1, 61 | description: "Change the level up message channel", 62 | options: [{ 63 | name: "channel", 64 | type: 3, 65 | description: "Mention the channel or give ID, 0 for same channel message", 66 | required: true 67 | }] 68 | }, { 69 | name: "ignore-channel-add", 70 | type: 1, 71 | description: "Add ignore XP Channel", 72 | options: [{ 73 | name: "channel", 74 | type: 7, 75 | description: "Mention the channel to disable XP increment", 76 | required: true 77 | }] 78 | }, { 79 | name: "ignore-channel-remove", 80 | type: 1, 81 | description: "remove ignore XP Channel", 82 | options: [{ 83 | name: "channel", 84 | type: 7, 85 | description: "Mention the channel to re-enable XP increment", 86 | required: true 87 | }] 88 | }, { 89 | name: "level-up-reward-message", 90 | type: 1, 91 | description: "Change the level up message for your server", 92 | options: [{ 93 | name: "success-message", 94 | type: 3, 95 | required: false, 96 | description: "The new level up message, you can use these: {level} {xp} {mention}" 97 | }, { 98 | name: "fail-message", 99 | type: 3, 100 | required: false, 101 | description: "The new level up message, you can use these: {level} {xp} {mention}" 102 | }] 103 | }, { 104 | name: "add-level-reward", 105 | type: 1, 106 | description: "Add a level reward for your server", 107 | options: [{ 108 | name: "level", 109 | type: 3, 110 | description: "Levle when the user will get this reward", 111 | required: true 112 | }, { 113 | name: "role", 114 | type: 8, 115 | description: "The reward role user will get", 116 | required: true 117 | }] 118 | }, { 119 | name: "remove-level-reward", 120 | type: 1, 121 | description: "Remove a level reward for your server", 122 | options: [{ 123 | name: "level", 124 | type: 3, 125 | description: "Level of which you want to remove", 126 | required: true 127 | }] 128 | }] 129 | }, 130 | permissions: ["MANAGE_SERVER"], 131 | 132 | /** 133 | * 134 | * @param {Client} client 135 | * @param {CommandInteraction} interaction 136 | */ 137 | run: async (client, interaction) => { 138 | await interaction.reply({ content: `${client.user.username} is thinking...` }); 139 | 140 | const option = interaction.options.getSubcommand(true).toLowerCase(), 141 | data = await configs.findOne({ id: interaction.guild.id }) || await configs.create({ id: interaction.guild.id }); 142 | 143 | data.levelReward = data.levelReward || {}; 144 | 145 | const rate = interaction.options.getInteger("rate"), 146 | ul = Math.floor(interaction.options.getInteger("up-limit")), 147 | dl = Math.floor(interaction.options.getInteger("down-limit")), 148 | message = interaction.options.getString("message"), 149 | s_message = interaction.options.getString("success-message"), 150 | f_message = interaction.options.getString("fail-message"), 151 | role = interaction.options.getRole("role"), 152 | level = interaction.options.getString("level"), 153 | channel = interaction.options.get("channel")?.value; 154 | 155 | if (option === "enable") { 156 | if (data.xp) return interaction.editReply({ content: "XP System is already enabled" }); 157 | 158 | interaction.editReply({ content: "XP System is now enabled" }); 159 | 160 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { xp: true }) 161 | } else if (option === "disable") { 162 | if (!data.xp) return interaction.editReply({ content: "XP System is already disabled" }); 163 | 164 | interaction.editReply({ content: "XP System is now disabled" }); 165 | 166 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { xp: false }) 167 | } else if (option === "rate") { 168 | if (rate < 0 || rate > 1000) return interaction.editReply({ content: "Please provide valid XP Rate from 1% to 1000% ( you don't have to type % just the number will work )" }) 169 | 170 | interaction.editReply({ content: `XP rate is change to ${rate}%` }); 171 | 172 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { xpRate: rate / 100 }) 173 | } else if (option === "limits") { 174 | if (dl > ul || ul < 0 || ul > 1000 || dl < 0 || dl > 1000) return interaction.editReply({ content: "Please provide valid XP increment limits from 1 to 1000 and up limit should be more than down limit" }) 175 | if (!dl && !ul) return interaction.editReply({ content: "Please provide either of the XP increment limit i.e. up or down" }) 176 | 177 | ul = ul || data.xpLimit.up; 178 | dl = dl || data.xpLimit.down; 179 | 180 | interaction.editReply({ content: `XP increment is change to:\nup limit: ${ul}\ndown limit: ${dl}` }); 181 | 182 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { "xpLimit.up": ul, "xpLimit.down": dl }) 183 | } else if (option === "level-up-message-enable") { 184 | if (data.xpLevelUp.xp) return interaction.editReply({ content: "XP level up message is already enabled" }); 185 | 186 | interaction.editReply({ content: "XP level up message is now enabled" }); 187 | 188 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { "xpLevelUp.enable": true }) 189 | } else if (option === "level-up-message-disable") { 190 | if (!data.xpLevelUp.xp) return interaction.editReply({ content: "XP level up message is already disabled" }); 191 | 192 | interaction.editReply({ content: "XP level up message is now disabled" }); 193 | 194 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { "xpLevelUp.enable": false }) 195 | } else if (option === "level-up-message") { 196 | interaction.editReply({ content: "XP level up message is now changed" }); 197 | 198 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { "xpLevelUp.message": message }) 199 | } else if (option === "level-up-channel") { 200 | let c = interaction.guild.channels.cache.get(channel) || interaction.guild.channels.cache.get(channel.substring(2, channel.length - 1)) 201 | 202 | if ((!c && channel !== "0") || (c && channel !== "0" && c.type !== "GUILD_TEXT")) 203 | return interaction.editReply({ content: "Either type 0 for same channel message or give a valid Text channel ID" }); 204 | 205 | interaction.editReply({ content: "XP level up message channel is now changed" }); 206 | 207 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { "xpLevelUp.channel": channel === "0" ? channel : c.id }) 208 | } else if (option === "ignore-channel-add") { 209 | if (data.ignoreXP.includes("channel")) 210 | return interaction.editReply({ content: "Yo nerd this channel is already disabled for xp increment" }); 211 | 212 | interaction.editReply({ content: "Now the mentioned channel will not get xp incremenets" }); 213 | 214 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { $push: { ignoreXP: channel.id } }) 215 | } else if (option === "ignore-channel-remove") { 216 | if (!data.ignoreXP.includes("channel")) 217 | return interaction.editReply({ content: "Yo nerd, this channel is not disabled for xp increment" }); 218 | 219 | interaction.editReply({ content: "Now the mentioned channel will get xp incremenets" }); 220 | 221 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { $pull: { ignoreXP: channel.id } }) 222 | } else if (option === "level-up-reward-message") { 223 | if (!s_message && !f_message) return interaction.editReply("Either provide success message or failed message."); 224 | 225 | interaction.editReply({ content: "Level Up reward message(s) changed successfully" }); 226 | 227 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { 228 | levelRewardMessage: { 229 | success: s_message || data.levelRewardMessage.success, 230 | fail: s_message || data.levelRewardMessage.fail, 231 | } 232 | }) 233 | } else if (option === "remove-level-reward") { 234 | if (!data.levelReward[level]) return interaction.editReply("Yo, you don't have any level reward for this level."); 235 | 236 | interaction.editReply({ content: "Level Up reward removed successfully" }); 237 | 238 | data.levelReward[level] = "0"; 239 | 240 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { levelReward: data.levelReward }) 241 | } else if (option === "add-level-reward") { 242 | if (data.levelReward[level] === role.id) return interaction.editReply("Yo, this level reward for this level already exist."); 243 | 244 | interaction.editReply({ content: "Level Up reward updated successfully" }); 245 | 246 | data.levelReward[level] = role.id; 247 | 248 | await configs.findOneAndUpdate({ id: interaction.guild.id }, { levelReward: data.levelReward }) 249 | } 250 | } 251 | } -------------------------------------------------------------------------------- /src/commands/general/autopages.js: -------------------------------------------------------------------------------- 1 | const page = require('../../utility/pagination'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "auto-pages", 6 | description: "make some automatic pages", 7 | options: [], 8 | }, 9 | timeout: 5000, 10 | 11 | run: async (client, interaction) => { 12 | let s = "hello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\nhello world I am just testing some cool as bull shit trust me on that man, alr? you get me. I am bored writing long string is boring, so i will use repeat function to repeat the same text again and again lol.\n".repeat(20); 13 | 14 | s = s.match(/[\s\S]{1,1000}[\s\n]/g); 15 | 16 | const pages = s.map((v,i) => { 17 | return { 18 | title:`Page Number ${i+1}`, 19 | description:v 20 | } 21 | }); 22 | 23 | page(interaction,pages) 24 | } 25 | } -------------------------------------------------------------------------------- /src/commands/general/button.js: -------------------------------------------------------------------------------- 1 | const { MessageButton, MessageActionRow, CommandInteraction, MessageComponentInteraction, InteractionCollector, MessageCollector } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "button", 6 | description: "Get some buttons!", 7 | options: [], 8 | }, 9 | 10 | /** 11 | * 12 | * @param {*} client 13 | * @param {CommandInteraction} interaction 14 | */ 15 | run: async (client, interaction) => { 16 | const row = new MessageActionRow().addComponents( 17 | new MessageButton().setStyle("LINK").setURL("https://google.com").setLabel("Google").setEmoji("883586635470606356").setDisabled(true), 18 | new MessageButton().setStyle("DANGER").setLabel("Danger Zone").setCustomId("1"), 19 | new MessageButton().setStyle("SECONDARY").setLabel("Secondayr").setCustomId("2"), 20 | new MessageButton().setStyle("PRIMARY").setLabel("Primary").setCustomId("3"), 21 | new MessageButton().setStyle("SUCCESS").setLabel("Success").setCustomId("4"), 22 | ); 23 | 24 | 25 | await interaction.reply({ components: [row], content: "Buttons!" }); 26 | const msg = await interaction.fetchReply(); 27 | 28 | const collector = msg.createMessageComponentCollector({ filter: (i) => i.user.id === interaction.user.id && parseInt(i.customId), time: 5000 }) 29 | 30 | collector.on('collect', (int) => collector.stop(int.customId)); 31 | 32 | collector.on('end', (ints, reason) => { 33 | let content = ""; 34 | 35 | if (reason === "time") content = "You are way too slow to click on button you NERD"; 36 | else if (reason === "1") content = "You clicked on the danger button"; 37 | else if (reason === "2") content = "You clicked on the secondary button"; 38 | else if (reason === "3") content = "You clicked on the primary button"; 39 | else if (reason === "4") content = "You clicked on the success button"; 40 | else content = "You click on a unknown button"; 41 | 42 | interaction.editReply({ components: [], content }); 43 | }) 44 | } 45 | } -------------------------------------------------------------------------------- /src/commands/general/calculator.js: -------------------------------------------------------------------------------- 1 | const { MessageActionRow, MessageButton } = require('discord.js'); 2 | const math = require('mathjs'); 3 | 4 | module.exports = { 5 | data: { 6 | name: "calculator", 7 | description: "Use the calculator on discord", 8 | options: [], 9 | }, 10 | timeout: 20000, 11 | 12 | run: async (client, interaction) => { 13 | const rows = [ 14 | new MessageActionRow().addComponents([ 15 | new MessageButton({ 16 | customId: 'clear', 17 | style: 'DANGER', 18 | label: "AC", 19 | }), 20 | new MessageButton({ 21 | customId: '(', 22 | style: 'PRIMARY', 23 | label: "(", 24 | }), 25 | new MessageButton({ 26 | customId: ')', 27 | style: 'PRIMARY', 28 | label: ")", 29 | }), 30 | new MessageButton({ 31 | customId: '/', 32 | style: 'PRIMARY', 33 | label: "➗", 34 | }) 35 | ]), 36 | new MessageActionRow().addComponents([ 37 | new MessageButton({ 38 | customId: '7', 39 | style: 'SECONDARY', 40 | label: "7", 41 | }), 42 | new MessageButton({ 43 | customId: '8', 44 | style: 'SECONDARY', 45 | label: "8", 46 | }), 47 | new MessageButton({ 48 | customId: '9', 49 | style: 'SECONDARY', 50 | label: "9", 51 | }), 52 | new MessageButton({ 53 | customId: '*', 54 | style: 'PRIMARY', 55 | label: "✖️", 56 | }) 57 | ]), 58 | new MessageActionRow().addComponents([ 59 | new MessageButton({ 60 | customId: '4', 61 | style: 'SECONDARY', 62 | label: "4", 63 | }), 64 | new MessageButton({ 65 | customId: '5', 66 | style: 'SECONDARY', 67 | label: "5", 68 | }), 69 | new MessageButton({ 70 | customId: '6', 71 | style: 'SECONDARY', 72 | label: "6", 73 | }), 74 | new MessageButton({ 75 | customId: '-', 76 | style: 'PRIMARY', 77 | label: "➖", 78 | }) 79 | ]), 80 | new MessageActionRow().addComponents([ 81 | new MessageButton({ 82 | customId: '1', 83 | style: 'SECONDARY', 84 | label: "1", 85 | }), 86 | new MessageButton({ 87 | customId: '2', 88 | style: 'SECONDARY', 89 | label: "2", 90 | }), 91 | new MessageButton({ 92 | customId: '3', 93 | style: 'SECONDARY', 94 | label: "3", 95 | }), 96 | new MessageButton({ 97 | customId: '+', 98 | style: 'PRIMARY', 99 | label: "➕", 100 | }) 101 | ]), 102 | new MessageActionRow().addComponents([ 103 | new MessageButton({ 104 | customId: 'backspace', 105 | style: 'PRIMARY', 106 | label: "⬅️", 107 | }), 108 | new MessageButton({ 109 | customId: '0', 110 | style: 'SECONDARY', 111 | label: "0", 112 | }), 113 | new MessageButton({ 114 | customId: '.', 115 | style: 'PRIMARY', 116 | label: "⚫", 117 | }), 118 | new MessageButton({ 119 | customId: 'result', 120 | style: 'SUCCESS', 121 | label: "=", 122 | }) 123 | ]), 124 | ]; 125 | 126 | const msg = await interaction.reply({ 127 | components: rows, 128 | embeds: [{ 129 | description: "```\nResults will be displayed here\n```", 130 | color: "BLUE" 131 | }], 132 | fetchReply: true, 133 | }); 134 | 135 | let data = ""; 136 | 137 | const col = msg.createMessageComponentCollector({ 138 | filter: i => i.user.id === interaction.user.id, 139 | time: 600000 140 | }); 141 | 142 | col.on('collect', async (i) => { 143 | let extra = ""; 144 | 145 | if (i.customId === "result") { 146 | try { 147 | data = math.evaluate(data).toString(); 148 | } catch (e) { 149 | data = ""; 150 | extra = "An Error Occured, Please click on AC for restart"; 151 | } 152 | } else if (i.customId === "clear") { 153 | data = ""; 154 | extra = "Results will be displayed here" 155 | } else if (i.customId === "backspace") { 156 | data = data.slice(0, data.length - 2); 157 | } else { 158 | const lc = data[data.length - 1]; 159 | 160 | data += `${( 161 | (parseInt(i.customId) == i.customId || i.customId === ".") 162 | && 163 | (lc == parseInt(lc) || lc === ".") 164 | ) || data.length === 0 ? "" : " "}` + i.customId; 165 | } 166 | 167 | i.update({ 168 | embeds: [{ 169 | color: "BLUE", 170 | description: `\`\`\`\n${data || extra}\n\`\`\`` 171 | }] 172 | }) 173 | }) 174 | 175 | col.on('end', () => { 176 | msg.edit({ 177 | components: [new MessageActionRow().addComponents([ 178 | new MessageButton({ 179 | label: "The Calculator Ended", 180 | disabled: true, 181 | style: "DANGER", 182 | customId: "_1_" 183 | }) 184 | ])] 185 | }) 186 | }) 187 | } 188 | } -------------------------------------------------------------------------------- /src/commands/general/canvas.js: -------------------------------------------------------------------------------- 1 | const { createCanvas, loadImage } = require('canvas'); 2 | const { MessageAttachment } = require('discord.js'); 3 | 4 | module.exports = { 5 | data: { 6 | name: "canvas", 7 | description: "Create a canvas", 8 | options: [], 9 | }, 10 | run: async (client, interaction) => { 11 | const canvas = createCanvas(1200, 700); 12 | const ctx = canvas.getContext('2d'); 13 | const avatar = await loadImage(interaction.user.displayAvatarURL({ dynamic: false, format: "png" })); 14 | const diameter = 500; 15 | 16 | ctx.fillStyle = "white"; 17 | ctx.fillRect(0, 0, canvas.width, canvas.height); 18 | 19 | ctx.fillStyle = "black"; 20 | ctx.font = "bold 50px Impact" 21 | ctx.textAlign = "center"; 22 | ctx.fillText("Filled text", 600, 670); 23 | 24 | ctx.beginPath(); 25 | ctx.arc(canvas.width / 2, canvas.height / 2, diameter / 2, 0, 2 * Math.PI); 26 | ctx.closePath(); 27 | ctx.clip(); 28 | 29 | ctx.drawImage(avatar, canvas.width / 2 - diameter / 2, canvas.height / 2 - diameter / 2, diameter, diameter); 30 | 31 | const image = new MessageAttachment(canvas.toBuffer(), "image.png"); 32 | interaction.reply({ files: [image] }); 33 | } 34 | } -------------------------------------------------------------------------------- /src/commands/general/embed.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed, MessageAttachment, CommandInteraction } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "embed", 6 | description: "Get some random embeds", 7 | options: [], 8 | }, 9 | 10 | /** 11 | * 12 | * @param {*} client 13 | * @param {CommandInteraction} interaction 14 | */ 15 | run: async (client, interaction) => { 16 | const embed2 = new MessageEmbed() 17 | .setAuthor(interaction.user.username, interaction.user.displayAvatarURL(), "https://www.google.com") 18 | .setTitle("Hello this a a cool title") 19 | .setURL("https://studio.youtube.com/channel/UCSqcbw8r8TZKYUhx4mufvNg") 20 | .setDescription(`Hello this a description, for a youtube tutorial of [Krazy Developer](https://www.fiverr.com/kartikethehuman?up_rollout=true)`) 21 | .setThumbnail("https://cdn.discordapp.com/attachments/723104565708324915/948955281495302174/board.png") 22 | .setImage("attachment://e.jpg") 23 | .setColor("GOLD") 24 | .setFooter(`Command User: ${interaction.user.username}`, "https://wallpaperaccess.com/full/3458163.jpg") 25 | .addField("Test", "hello world") 26 | .addFields([ 27 | { name: "COol field 1", value: "Trying to be better everyday!", inline: true }, 28 | { name: "COol field 2", value: "Trying to be better everyday!", inline: true }, 29 | { name: "COol field 3", value: "Trying to be better everyday!", inline: false }, 30 | ]) 31 | .setTimestamp() 32 | 33 | 34 | interaction.reply({ 35 | embeds: [{ 36 | author: { 37 | name: interaction.user.username, 38 | iconURL: interaction.user.displayAvatarURL(), 39 | url: "https://www.google.com" 40 | }, 41 | title: "Hello It is a better title", 42 | url: "https://studio.youtube.com/channel/UCSqcbw8r8TZKYUhx4mufvNg", 43 | description: "Hello this a description, for a youtube tutorial of [Krazy Developer](https://www.fiverr.com/kartikethehuman?up_rollout=true)", 44 | thumbnail: { 45 | url: 'attachment://e.jpg' 46 | }, image: { 47 | url: 'attachment://e.jpg' 48 | }, 49 | color: "DARK_ORANGE", 50 | footer: { 51 | text: "This is the footer bro", 52 | iconURL: "https://wallpaperaccess.com/full/3458163.jpg" 53 | }, 54 | fields: [ 55 | { name: "COol field 1", value: "Trying to be better everyday!", inline: true }, 56 | { name: "COol field 2", value: "Trying to be better everyday!", inline: true }, 57 | { name: "COol field 3", value: "Trying to be better everyday!", inline: false }, 58 | { name: "COol field 4", value: "Trying to be better everyday!", inline: true }, 59 | { name: "COol field 5", value: "Trying to be better everyday!", inline: true }, 60 | 61 | ],timestamp:Date.now(), 62 | }], 63 | files: [new MessageAttachment('./e.jpg')] 64 | }) 65 | } 66 | } -------------------------------------------------------------------------------- /src/commands/general/fight.js: -------------------------------------------------------------------------------- 1 | const fight = require('discord-fight-game'); 2 | 3 | module.exports = { 4 | data: { 5 | name: "fight", 6 | description: "Fight someone", 7 | options: [{ 8 | name: "user", 9 | description: "Mention a user", 10 | required: false, 11 | type: 6, 12 | }], 13 | }, 14 | 15 | run: async (client, interaction) => { 16 | const game = new fight(client, { 17 | oneEmoji: "🤺", 18 | oneName: "Sword", 19 | twoEmoji: "🏹", 20 | twoName: "Bow", 21 | threeEmoji: "🛡", 22 | threeName: "Shield", 23 | endEmoji: "🏃‍♂️", 24 | endName: "run away", 25 | 26 | // Custom Messages 27 | startMessage: "The war has begun, get ready warriors", 28 | midMessage: "The fighters chose their move, Current battle condition :", 29 | endMessage: "{winner} gloriously defeated {looser}", 30 | forceEndMessage: "{user} was scared so they ended the war", 31 | timeEndMessage: "{user} ran away from the war", 32 | 33 | // Custom Game LOgic 34 | startHealth: 69, 35 | }); 36 | 37 | interaction.reply({ content: `The game is started` }); 38 | 39 | const user = interaction.options.getUser("user"); 40 | 41 | interaction.author = interaction.user; 42 | 43 | if (user && user.bot) return interaction.editReply({ content: "You can not play the game with bots" }) 44 | 45 | if (!user) game.solo(interaction) 46 | else game.duo(interaction, user); 47 | } 48 | } -------------------------------------------------------------------------------- /src/commands/general/hangman.js: -------------------------------------------------------------------------------- 1 | const { MessageAttachment, MessageCollector } = require('discord.js'); 2 | const { readFileSync } = require('fs'); 3 | const createHangman = require("../../utility/createHangman"); 4 | const words = readFileSync("./src/utility/words", { encoding: 'utf-8' }).split("\n"); 5 | 6 | module.exports = { 7 | data: { 8 | name: "hangman", 9 | description: "Play the hangman game", 10 | options: [], 11 | }, 12 | timeout: 10000, 13 | 14 | run: async (client, interaction) => { 15 | await interaction.deferReply(); 16 | 17 | let wrongs = 0, at = new MessageAttachment(await createHangman(wrongs), "game.png"), word = words[Math.floor(Math.random() * words.length)], used = []; 18 | 19 | await interaction.editReply({ 20 | files: [at], 21 | embeds: [{ 22 | title: "Hangman Game!", 23 | image: { 24 | url: "attachment://game.png" 25 | }, 26 | color: "BLUE", 27 | description: `Type a character to guess the word\n\n\`\`\`${word.split("").map(v => used.includes(v) ? v.toUpperCase() : "_").join(" ")}\`\`\`` 28 | }] 29 | }); 30 | 31 | const col = new MessageCollector(interaction.channel, { 32 | filter: m => m.author.id === interaction.user.id, 33 | time: 600000 34 | }); 35 | 36 | col.on('collect', async (msg) => { 37 | const char = msg.content[0]?.toLowerCase(); 38 | 39 | if (!/[a-z]/i.test(char)) return msg.reply("You have to **provide** a **letter**, **not** a **number/symbol**").then((m) => setTimeout(() => m.delete().catch(e => { }), 5000)) 40 | if (used.includes(char)) return msg.reply("You aleady used this letter").then((m) => setTimeout(() => m.delete().catch(e => { }), 5000)); 41 | 42 | used.push(char); 43 | 44 | if (!word.includes(char)) wrongs++; 45 | 46 | let done = word.split("").every(v => used.includes(v)); 47 | let description = wrongs === 6 || done ? `You ${done ? "won" : "lost"} the game, The word was **${word}**` : `Type a character to guess the word\n\n\`\`\`${word.split("").map(v => used.includes(v) ? v.toUpperCase() : "_").join(" ")}\`\`\`` 48 | 49 | await interaction.editReply({ 50 | attachments: [], 51 | files: [new MessageAttachment(await createHangman(wrongs), "game.png")], 52 | embeds: [{ 53 | title: "Hangman Game!", 54 | image: { 55 | url: "attachment://game.png" 56 | }, 57 | color: wrongs === 6 ? "#ff0000" : done ? "GREEN" : "RANDOM", 58 | description 59 | }] 60 | }); 61 | 62 | if (wrongs === 6 || done) col.stop(); 63 | }) 64 | 65 | col.on('end', (s, r) => { 66 | if (r === "time") { 67 | interaction.editReply({ 68 | attachments: [], 69 | embeds: [{ 70 | title: "⛔ Game Ended", 71 | description: "You took too much time to respond" 72 | }] 73 | }); 74 | } 75 | }) 76 | } 77 | } -------------------------------------------------------------------------------- /src/commands/general/help.js: -------------------------------------------------------------------------------- 1 | const { MessageActionRow, CommandInteraction } = require('discord.js'); 2 | const commandInfo = require('../../utility/commandInfo'); 3 | const pagination = require('../../utility/pagination'); 4 | 5 | module.exports = { 6 | data: { 7 | name: "help", 8 | description: "Get some help ;D", 9 | options: [{ 10 | name: "basic", 11 | description: "Get basic information of the bot and category/command list", 12 | type: 1 13 | }, { 14 | name: "commands", 15 | description: "Get information of all commands of a category", 16 | type: 1, 17 | options: [{ 18 | name: "category", 19 | type: 3, 20 | required: true, 21 | description: "The category who's commands information you want" 22 | }] 23 | }, { 24 | name: "command", 25 | description: "Get information of a command", 26 | type: 1, 27 | options: [{ 28 | name: "command", 29 | type: 3, 30 | required: true, 31 | description: "The command who's commands information you want" 32 | }] 33 | }] 34 | }, 35 | 36 | /** 37 | * 38 | * @param {*} client 39 | * @param {CommandInteraction} interaction 40 | */ 41 | run: async (client, interaction) => { 42 | const option = interaction.options.getSubcommand(); 43 | 44 | if (option === "basic") { 45 | const row = new MessageActionRow(), options = client.categories.map(v => { 46 | return { 47 | label: `${v.replace(v.charAt(0), v.charAt(0).toUpperCase())}`, 48 | value: v 49 | } 50 | }); 51 | 52 | let used = false; 53 | 54 | row.addComponents({ 55 | type: "SELECT_MENU", 56 | customId: "select", 57 | placeholder: "Choose a category", 58 | options 59 | }); 60 | 61 | const msg = await interaction.reply({ 62 | fetchReply: true, 63 | components: [row], 64 | embeds: [{ 65 | title: `${client.user.username}'s Help 📚 Menu`, 66 | description: `I am a simple tutorial bot, for my youtube channel's series on [discord bots](https://www.youtube.com/watch?v=En1rbbrar_Q&list=PLE7Nd_E0DDA837kBCGO4lqBW5ve-x_gk_)` + 67 | `\nI have various cool features like\n- Reaction role\n- Ticket System\n- Simple Pokemon Game\n- Greetings\n- Tags\nAnd a lot more and guess what new things will be coming soon :D\n\nTo get list of commands of a category select the category from the select menu below`, 68 | color: "#f5a207" 69 | }] 70 | }); 71 | 72 | // Select menu collector for category 73 | const col = msg.createMessageComponentCollector({ 74 | filter: (i) => i.user.id === interaction.user.id, 75 | time: 10000, 76 | }); 77 | 78 | // Select menu collector for category 79 | col.on('collect', async (i) => { 80 | let cat = i.values[0], index = 0; 81 | used = true; 82 | 83 | row.components[0].options = client.commands.filter(v => v.category === cat).map(c => { 84 | let v = c.data.name 85 | 86 | return { 87 | label: v.replace(v.charAt(0), v.charAt(0).toUpperCase()), 88 | value: v 89 | } 90 | }); 91 | row.components[0].placeholder = "Choose a command"; 92 | 93 | const msg = await i.update({ 94 | embeds: [{ 95 | title: `${cat.replace(cat.charAt(0), cat.charAt(0).toUpperCase())}'s commands list`, 96 | description: 97 | client.commands.filter(v => v.category === cat).map((v) => `\`${++index}.\`**${v.data.name}**\n${v.data.description}`).join("\n\n") 98 | }], 99 | components: [row], 100 | fetchReply: true 101 | }); 102 | 103 | const col2 = msg.createMessageComponentCollector({ 104 | filter: (i) => i.user.id === interaction.user.id, 105 | time: 10000 106 | }); 107 | 108 | col2.on('collect', (i) => { 109 | const command = client.commands.get(i.values[0]); 110 | 111 | i.update({ 112 | embeds: [commandInfo(command)], 113 | components: [] 114 | }); 115 | 116 | col2.stop(); 117 | }); 118 | 119 | col2.on('end', (reason) => { 120 | if (reason === 'time') { 121 | msg.edit({ 122 | components: [] 123 | }) 124 | } 125 | }) 126 | 127 | col.stop(); 128 | }); 129 | 130 | // Select menu collector for category end 131 | col.on('end', (reason) => { 132 | if (reason === 'time' && !used) { 133 | msg.edit({ 134 | components: [] 135 | }) 136 | } 137 | }) 138 | } else if (option === "commands") { 139 | const cat = interaction.options.getString("category")?.toLowerCase(); 140 | const commands = client.commands.filter(v => v.category === cat); 141 | 142 | const embeds = commands.map(v => commandInfo(v)); 143 | 144 | pagination(interaction, embeds); 145 | } else if (option === "command") { 146 | interaction.reply({ 147 | embeds: [commandInfo(client.commands.get(interaction.options.getString("command")?.toLowerCase()))] 148 | }) 149 | } 150 | } 151 | } -------------------------------------------------------------------------------- /src/commands/general/mdn.js: -------------------------------------------------------------------------------- 1 | const getSource = require('../../utility/getMdnSource'); 2 | const fetch = require('node-fetch'); 3 | const MDN_BASE_URL = "https://developer.mozilla.org/en-US/docs/"; 4 | 5 | module.exports = { 6 | data: { 7 | name: "mdn", 8 | description: "Browse the mdn docs", 9 | options: [{ 10 | type: 3, 11 | required: true, 12 | description: "The query you want to search", 13 | name: "query" 14 | }], 15 | }, 16 | 17 | run: async (client, interaction) => { 18 | await interaction.reply("Fetching the data"); 19 | const { sitemap, index } = await getSource(), q = interaction.options.getString("query"); 20 | 21 | const search = index.search(q, { limit: 10 }).map((id) => sitemap[id].loc); 22 | 23 | if (search?.length === 0) interaction.editReply("YOu sucks the result are not sfound ❌"); 24 | else if (search.length === 1) { 25 | const res = await fetch(`${MDN_BASE_URL + search[0]}/index.json`); 26 | const doc = (await res.json()).doc; 27 | 28 | interaction.editReply({ 29 | embeds: [{ 30 | author: { 31 | name: "Mdn Documentation", 32 | iconURL: "https://i.imgur.com/1P4wotC.png", 33 | url: `${MDN_BASE_URL}${doc.mdn_url}` 34 | }, 35 | url: `${MDN_BASE_URL}${doc.mdn_url}`, 36 | color: 0x83BFFF, 37 | title: doc.pageTitle, 38 | description: doc.summary 39 | }] 40 | }) 41 | } else { 42 | const results = search.map((path) => `**• [${path.replace(/_|-/g, " ")}](${MDN_BASE_URL}${path})**`); 43 | 44 | interaction.editReply({ 45 | embeds: [{ 46 | author: { 47 | name: "Mdn Documentation", 48 | iconURL: "https://i.imgur.com/1P4wotC.png", 49 | url: `${MDN_BASE_URL}` 50 | }, 51 | color: 0x83BFFF, 52 | title: `Search for: ${query}`, 53 | description: results.join("\n") 54 | }] 55 | }) 56 | } 57 | } 58 | } 59 | 60 | -------------------------------------------------------------------------------- /src/commands/general/pages.js: -------------------------------------------------------------------------------- 1 | const pagination = require("../../utility/pagination2") 2 | 3 | module.exports = { 4 | data: { 5 | name: "pages", 6 | description: "Test the select menu pagination of the bot", 7 | options: [], 8 | }, 9 | timeout: 10000, 10 | 11 | run: async (client, interaction) => { 12 | const 13 | pages = [ 14 | { title: "Page 1" }, 15 | { title: "Page 2" }, 16 | { title: "Page 3" }, 17 | ], 18 | options = [{ 19 | label: "Page 1", 20 | emoji: '1️⃣' 21 | }, { 22 | label: "Page 2", 23 | emoji: '2️⃣' 24 | }, { 25 | label: "Page 3", 26 | emoji: '3️⃣' 27 | }]; 28 | 29 | 30 | pagination(interaction, pages, options) 31 | } 32 | } -------------------------------------------------------------------------------- /src/commands/general/ping.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | data: { 3 | name: "ping", 4 | description: "Get this bot's ping!", 5 | options: [], 6 | }, 7 | timeout:10000, 8 | 9 | run: async (client, interaction) => { 10 | interaction.reply({ content: `THe ping of the client is ${client.ws.ping}` }) 11 | } 12 | } -------------------------------------------------------------------------------- /src/commands/general/poke.js: -------------------------------------------------------------------------------- 1 | const { Client, Message } = require("discord.js"); 2 | 3 | module.exports = { 4 | data: { 5 | name: "poke", 6 | description: "", // it should be empty 7 | type: 3, 8 | }, 9 | 10 | /** 11 | * 12 | * @param {Client} client 13 | * @param {*} interaction 14 | */ 15 | run: async (client, interaction) => { 16 | const message = await client.channels.cache.get(interaction.channelId).messages.fetch(interaction.targetId, true); 17 | 18 | interaction.reply({ content: `${interaction.user.toString()} poked ${message.author.toString()}` }) 19 | } 20 | } -------------------------------------------------------------------------------- /src/commands/general/pokemons.js: -------------------------------------------------------------------------------- 1 | const userConfig = require('../../models/userConfig'); 2 | const pokecord = require('pokecord'); 3 | 4 | module.exports = { 5 | data: { 6 | name: "pokemons", 7 | description: "Get list of pokemons your pokemons or someone else's", 8 | options: [{ 9 | name: "user", 10 | description: "Mention a user to get their pokemons", 11 | required: false, 12 | type: 6, 13 | }], 14 | }, 15 | 16 | run: async (client, interaction) => { 17 | await interaction.deferReply(); 18 | 19 | const user = interaction.options.getUser("user") || interaction.user; 20 | const data = await userConfig.findOne({ user: user.id }) || await userConfig.create({ user: user.id }); 21 | let pokemons = "ID\tPokemon"; 22 | 23 | for (let i = 0; i < data.pokemons.length; i++) { 24 | const v = data.pokemons[i]; 25 | pokemons += `${i}. ${(await pokecord.Spawn(v)).name}\n` 26 | } 27 | 28 | interaction.editReply({ 29 | embeds: [{ 30 | title: `${user.username}'s Pokemon's`, 31 | description: pokemons 32 | }] 33 | }) 34 | } 35 | } -------------------------------------------------------------------------------- /src/commands/general/profile.js: -------------------------------------------------------------------------------- 1 | const { MessageAttachment } = require("discord.js"); 2 | const badge = require("../../models/badge") 3 | const userConfig = require("../../models/userConfig"); 4 | const createProfile = require("../../utility/createProfile"); 5 | 6 | module.exports = { 7 | data: { 8 | name: "profile", 9 | description: "Check somebody's profile", 10 | options: [{ 11 | type: 6, 12 | name: 'user', 13 | description: "The user who's profile you want to check" 14 | }], 15 | }, 16 | timeout: 3000, 17 | 18 | run: async (client, interaction) => { 19 | await interaction.deferReply(); 20 | 21 | const user = interaction.options.getUser("user") || interaction.user, 22 | u = await userConfig.findOne({ user: user.id }) || await userConfig.create({ user: user.id }); 23 | 24 | let badges = []; 25 | 26 | for (let i = 0; i < u.badges.length; i++) { 27 | const bg = await badge.findOne({ id: u.badges[i] }); 28 | 29 | if (!bg) continue; 30 | 31 | badges.push(client.emojis.cache.get(bg?.emoji)?.toString() || bg?.emoji); 32 | } 33 | 34 | interaction.editReply({ 35 | embeds: [{ 36 | title: `${user.username}'s profile`, 37 | image: { 38 | url: 'attachment://profile.png' 39 | } 40 | }], 41 | files: [new MessageAttachment(await createProfile(user.username, user.displayAvatarURL({ format: 'png' }), badges ), "profile.png")] 42 | }); 43 | } 44 | } -------------------------------------------------------------------------------- /src/commands/general/rank.js: -------------------------------------------------------------------------------- 1 | const users = require('../../models/user_xp'); 2 | const { createCanvas, loadImage } = require('canvas'); 3 | const { MessageAttachment, TextChannel } = require('discord.js'); 4 | 5 | module.exports = { 6 | data: { 7 | name: "rank", 8 | description: "Check your rank!", 9 | options: [{ 10 | name: "user", 11 | description: "Mention a user", 12 | required: false, 13 | type: 6, 14 | }], 15 | }, 16 | 17 | run: async (client, interaction) => { 18 | await interaction.reply("Calculating data!"); 19 | 20 | const user = interaction.options.getUser("user") || interaction.user; 21 | let datas = await users.find({ guild: interaction.guild.id }) || {}, data, rank; 22 | 23 | for (let i = 0; i < datas.length; i++) { 24 | let v = datas[i]; 25 | 26 | if (v.user === user.id) { 27 | data = v; 28 | rank = i + 1; 29 | break; 30 | } 31 | }; 32 | 33 | if (!data) return interaction.editReply("you have no xp & data") 34 | 35 | let reqXP = 100; 36 | 37 | for (let i = 1; i <= data.level; i++)reqXP += 5 * (i ^ 2) + (50 * i) + 100; 38 | 39 | const canvas = createCanvas(1000, 300), 40 | ctx = canvas.getContext('2d'), 41 | bar_width = 600, 42 | bg = await loadImage("https://cdn.discordapp.com/attachments/725600118098886657/933972874765680720/3b30adb3-2147-42d3-a4f6-a869c3d71723.png"), 43 | av = await loadImage(interaction.user.displayAvatarURL({ format: 'png', dynamic: false })); 44 | 45 | ctx.drawImage(bg, 0, 0, canvas.width, canvas.height); 46 | 47 | // Middle circle for Avatar Background 48 | ctx.beginPath(); 49 | ctx.arc(120, 120, 110, 0, 2 * Math.PI); 50 | ctx.lineWidth = 2; 51 | ctx.strokeStyle = "white"; 52 | ctx.stroke(); 53 | ctx.closePath(); 54 | 55 | // XP Bar 56 | ctx.lineJoin = "round"; 57 | ctx.lineWidth = 69; 58 | 59 | // Shadow of xp bar 60 | ctx.strokeRect(298, 199, bar_width, 2); 61 | 62 | // Empty Bar 63 | ctx.strokeStyle = "black"; 64 | ctx.strokeRect(300, 200, bar_width, 0); 65 | 66 | // Filled Bar 67 | ctx.strokeStyle = "#1762e8" 68 | ctx.strokeRect(300, 200, bar_width * data.xp / reqXP, 0); 69 | 70 | // Adding Username 71 | ctx.font = "bold 40px Sans"; 72 | ctx.fillStyle = "#fe5701"; // Username color 73 | ctx.textAlign = "center"; 74 | ctx.fillText(user.username, 120, 275, 200); 75 | 76 | // Adding stats 77 | ctx.fillText("#" + rank, 760, 40, 80); 78 | ctx.fillText(data.level, 930, 40, 80); 79 | 80 | // Adding titles 81 | ctx.fillStyle = "white"; 82 | ctx.font = "bold 25px Sans"; 83 | ctx.fillText("Rank", 680, 40, 200); 84 | ctx.fillText("Level", 850, 40, 200); 85 | 86 | // Adding bar title 87 | ctx.fillStyle = "#white"; 88 | ctx.font = "bold 22px Serif"; 89 | ctx.fillText(`${data.xp}/${reqXP} XP`, 850, 150); 90 | ctx.fillText(`${((data.xp * 100) / reqXP).toFixed(0)}/100 %`, 350, 150); 91 | 92 | // Remove the corners 93 | ctx.beginPath(); 94 | ctx.arc(120, 120, 110, 0, 2 * Math.PI); 95 | ctx.closePath(); 96 | ctx.clip(); 97 | 98 | // Add the avatar 99 | ctx.drawImage(av, 10, 10, 220, 200); 100 | 101 | const at = new MessageAttachment(canvas.toBuffer(), "rank.png"); 102 | 103 | interaction.editReply({ 104 | files: [at] 105 | }) 106 | } 107 | } -------------------------------------------------------------------------------- /src/commands/general/rps.js: -------------------------------------------------------------------------------- 1 | const rps = require('discord-rock-paper-scissor'); 2 | const game = new rps({ 3 | readyMessage: "Nerds choose your moves in the DMs", 4 | endTitle: "{winner} won the dang game", 5 | endDescription: "{winner} is the winner\n{looser} is the looser", 6 | }); 7 | 8 | module.exports = { 9 | data: { 10 | name: "rock-paper-scissor", 11 | description: "Play rock paper scissor game", 12 | options: [{ 13 | name: "user", 14 | description: "Mention a user", 15 | required: false, 16 | type: 6, 17 | }], 18 | }, 19 | 20 | run: async (client, interaction) => { 21 | interaction.reply({ content: `The game is started` }); 22 | const user = interaction.options.getUser("user"); 23 | 24 | if (user && user.bot) return interaction.editReply({ content: "You can not play the game with bots" }) 25 | 26 | if (!user) game.solo(interaction, client) 27 | else game.duo(interaction, user); 28 | } 29 | } -------------------------------------------------------------------------------- /src/commands/general/suggestion.js: -------------------------------------------------------------------------------- 1 | const { MessageActionRow, MessageButton } = require("discord.js"); 2 | const guildConfig = require("../../models/guildConfig") 3 | const suggestions = require("../../models/suggestion") 4 | 5 | module.exports = { 6 | data: { 7 | name: "suggestion", 8 | description: "Create or reply to suggestions", 9 | options: [{ 10 | name: "create", 11 | type: 1, 12 | description: "Create a suggestion", 13 | options: [{ 14 | name: "suggestion", 15 | type: 3, 16 | required: true, 17 | description: "The suggesiton you want to give" 18 | }] 19 | }, { 20 | name: "reply", 21 | type: 1, 22 | description: "Reply to a suggesiton", 23 | options: [{ 24 | name: "id", 25 | type: 3, 26 | required: true, 27 | description: "The suggestion to which you want to reply" 28 | }, { 29 | name: "status", 30 | type: 3, 31 | required: true, 32 | description: "Set the status of this suggestion", 33 | choices: [{ 34 | name: "Accepted", 35 | value: "1" 36 | }, { 37 | name: "Rejected", 38 | value: "2" 39 | }] 40 | }, { 41 | name: "response", 42 | type: 3, 43 | required: true, 44 | description: "The response to this status" 45 | }] 46 | }, { 47 | name: 'set-channel', 48 | type: 1, 49 | description: "Select the suggestion channel", 50 | options: [{ 51 | name: "channel", 52 | type: 7, 53 | required: true, 54 | description: "The channel where I should send the suggestions" 55 | }] 56 | }], 57 | }, 58 | timeout: 1000, 59 | 60 | run: async (client, interaction) => { 61 | await interaction.deferReply(); 62 | 63 | const option = interaction.options.getSubcommand(), 64 | suggestion = interaction.options.getString("suggestion"), 65 | channel = interaction.options.getChannel("channel"), 66 | id = interaction.options.getString("id"), 67 | status = interaction.options.getString("status"), 68 | response = interaction.options.getString("response"), 69 | data = await guildConfig.findOne({ id: interaction.guild.id }) || await guildConfig.create({ id: interaction.guild.id }), 70 | sug = await suggestions.findOne({ message: id }), 71 | c = interaction.guild.channels.cache.get(data.suggestion); 72 | 73 | if (option === "create") { 74 | if (!c) return interaction.editReply({ 75 | embeds: [{ 76 | title: "❌ Suggestion Not Setuped" 77 | }] 78 | }); 79 | 80 | const row = new MessageActionRow().addComponents([ 81 | new MessageButton({ 82 | customId: "1", 83 | label: "⬆ Up Vote", 84 | style: "SECONDARY" 85 | }), new MessageButton({ 86 | customId: "2", 87 | label: "⬇ Down Vote", 88 | style: "SECONDARY" 89 | }) 90 | ]) 91 | 92 | const msg = await c.send({ 93 | components: [row], 94 | embeds: [{ 95 | title: "New Suggestion!", 96 | color: "BLUE", 97 | description: suggestion, 98 | fields: [{ 99 | name: "Up Votes", 100 | value: "0", 101 | inline: true 102 | }, { 103 | name: "Down Votes", 104 | value: "0", 105 | inline: true 106 | }, { 107 | name: "Status", 108 | value: "pending", 109 | inline: true 110 | }], 111 | footer: { 112 | text: interaction.user.username, 113 | iconURL: interaction.user.displayAvatarURL() 114 | } 115 | }] 116 | }); 117 | 118 | await suggestions.create({ 119 | suggestion, 120 | user: interaction.user.id, 121 | message: msg.id, 122 | channel: c.id, 123 | guild: interaction.guildId, 124 | votes: { 125 | up: [], down: [] 126 | }, 127 | createdAt: Date.now(), 128 | }); 129 | 130 | msg.embeds[0].fields.push({ 131 | name: "Suggestion ID", 132 | value: `\`\`\`\n${msg.id}\n\`\`\``, 133 | inline: true 134 | }); 135 | 136 | msg.edit({ 137 | embeds: msg.embeds 138 | }); 139 | 140 | interaction.editReply({ 141 | embeds: [{ 142 | color: "GREEN", 143 | title: "✅ Suggestion Created" 144 | }] 145 | }) 146 | } else if (option === "reply") { 147 | if (!interaction.member.permissions.has("MANAGE_GUILD")) return interaction.editReply({ 148 | embeds: [{ 149 | title: "❌ You are not allowed" 150 | }] 151 | }); 152 | 153 | if (!sug) return interaction.editReply({ 154 | embeds: [{ 155 | title: "❌ Invalid Suggestion ID" 156 | }] 157 | }); 158 | 159 | const msg = await interaction.guild.channels.cache.get(sug.channel)?.messages?.fetch(sug.message); 160 | 161 | if (!msg) return interaction.editReply({ 162 | embeds: [{ 163 | title: "❌ Suggestion Message is Deleted", 164 | description: "This suggestion can no longer be replied" 165 | }] 166 | }); 167 | 168 | const row = new MessageActionRow().addComponents([ 169 | new MessageButton({ 170 | customId: "1", 171 | label: "⬆ Up Vote", 172 | style: "SECONDARY", 173 | disabled: true 174 | }), new MessageButton({ 175 | customId: "2", 176 | label: "⬇ Down Vote", 177 | style: "SECONDARY", 178 | disabled: true 179 | }) 180 | ]); 181 | 182 | msg.embeds[0].fields[2].value = status === "1" ? "✅ Accepted" : "❌ Rejected"; 183 | msg.embeds[0].fields.push({ 184 | name: "Response", 185 | value: response, 186 | }) 187 | 188 | msg.edit({ 189 | embeds: msg.embeds, 190 | components: [row] 191 | }); 192 | 193 | interaction.editReply({ 194 | embeds: [{ 195 | color: "GREEN", 196 | title: "✅ Suggestion Replied" 197 | }] 198 | }) 199 | } else if (option === "set-channel") { 200 | if (!interaction.member.permissions.has("MANAGE_GUILD")) return interaction.editReply({ 201 | embeds: [{ 202 | title: "❌ You are not allowed" 203 | }] 204 | }); 205 | 206 | if (channel.type !== "GUILD_TEXT") return interaction.editReply({ 207 | embeds: [{ 208 | title: "❌ Invalid Channel Type" 209 | }] 210 | }); 211 | 212 | await guildConfig.findOneAndUpdate({ id: interaction.guildId }, { suggestion: channel.id }); 213 | 214 | interaction.editReply({ 215 | embeds: [{ 216 | color: "GREEN", 217 | title: "✅ Suggestion Setuped! " 218 | }] 219 | }) 220 | } 221 | } 222 | } -------------------------------------------------------------------------------- /src/commands/general/timer.js: -------------------------------------------------------------------------------- 1 | const ms = require('ms-prettify').default; 2 | const timers = require('../../models/timer'); 3 | const createID = require('../../utility/randomId'); 4 | const startTimer = require('../../utility/startTimer'); 5 | 6 | module.exports = { 7 | data: { 8 | name: "timer", 9 | description: "Set some kind of timer?", 10 | options: [{ 11 | name: "time", 12 | description: "Time for this timer, like 10 min 23 sec", 13 | required: true, 14 | type: 3, 15 | }, { 16 | name: "reason", 17 | description: "Reason for this timeout, no?", 18 | required: false, 19 | type: 3, 20 | }], 21 | }, 22 | 23 | run: async (client, interaction) => { 24 | const time = ms(interaction.options.getString("time")), 25 | reason = interaction.options.getString("reason") || ""; 26 | 27 | if (!time) return interaction.reply("Invalid time was provided"); 28 | 29 | const timer = await timers.create({ id: createID(), user: interaction.user.id, guild: interaction.guild.id, channel: interaction.channel.id, reason, createdAt: Date.now(), time, endAt: Date.now() + time }); 30 | 31 | interaction.reply({ content: "Your timer ⏰ is started!" }); 32 | 33 | startTimer(client, timer) 34 | } 35 | } -------------------------------------------------------------------------------- /src/commands/general/trade.js: -------------------------------------------------------------------------------- 1 | const userConfig = require('../../models/userConfig'); 2 | const pokecord = require('pokecord'); 3 | const { ReactionCollector, MessageCollector } = require('discord.js'); 4 | 5 | module.exports = { 6 | data: { 7 | name: "trade", 8 | description: "Trade your pokemons", 9 | options: [{ 10 | name: "user", 11 | description: "Mention a user to trade with", 12 | required: true, 13 | type: 6, 14 | }, { 15 | name: "item", 16 | description: "The item you want to trade, type -1 for nothing", 17 | required: true, 18 | type: 4, 19 | }], 20 | }, 21 | 22 | run: async (client, interaction) => { 23 | await interaction.reply("Fetching the details"); 24 | 25 | const u1_data = await userConfig.findOne({ user: interaction.user.id }) || await userConfig.create({ user: interaction.user.id }), 26 | user = interaction.options.getUser("user"), 27 | u2_data = await userConfig.findOne({ user: user.id }) || await userConfig.create({ user: user.id }), 28 | P1_id = interaction.options.getInteger("item"); 29 | 30 | if (user.id === interaction.user.id || user.bot) return interaction.editReply("you can't trae with yourself or with a bot"); 31 | 32 | if (P1_id !== -1 && !u1_data.pokemons[P1_id]) return interaction.editReply(`❌ Invalid Pokemon ID was provided`); 33 | 34 | let P1 = P1_id === -1 ? -1 : await pokecord.Spawn(u1_data.pokemons[P1_id]), P2, P2_id; 35 | 36 | const msg = await interaction.channel.send({ 37 | embeds: [{ 38 | title: "Trade Offer", 39 | description: `Hello ${user.username}, ${interaction.user.username} gave you a trade offer for a **${P1 === -1 ? "nothing" : P1.name}**, react with ✅ for continuing the trade or react with ❌ for rejecting the trade offer` 40 | }], 41 | content: `${user.toString()}` 42 | }); 43 | 44 | await msg.react("✅"); 45 | await msg.react("❌"); 46 | 47 | const c = new ReactionCollector(msg, { time: 30000, filter: (r, u) => ["✅", "❌"].includes(r.emoji.name) && u.id === user.id }); 48 | 49 | c.on('collect', (rec) => c.stop(rec.emoji.name)); 50 | 51 | c.on('end', (shit, reason) => { 52 | if (reason === "time") { 53 | interaction.followUp("The mentioned user ignored the trade offer"); 54 | msg.edit({ 55 | embeds: [{ 56 | title: "Trade Offer Expired", 57 | color: "#ff0000", 58 | descrption: `Trade offer from ${interaction.user.username} is expired` 59 | }] 60 | }) 61 | } else if (reason === "❌") { 62 | interaction.followUp("The mentioned user denied ❌ the trade offer"); 63 | 64 | msg.edit({ 65 | embeds: [{ 66 | title: "Trade Offer Declined Successfully", 67 | descrption: `Trade offer from ${interaction.user.username} is declined` 68 | }] 69 | }) 70 | } else { 71 | msg.edit({ 72 | embeds: [{ 73 | title: "Trade Offer Accepted Successfully", 74 | description: `${user.toString()}, Now give the pokemon ID you want to trade or type \`-1\` for \`nothing\` or type \`cancel\` to cancel the trade` 75 | }], 76 | }); 77 | 78 | const col = new MessageCollector(msg.channel, { time: 120000, filter: (m) => m.author.id === user.id }); 79 | 80 | col.on('collect', async (msg) => { 81 | if (msg.content.toLowerCase() === "cancel") return col.stop("cancel"); 82 | 83 | P2_id = parseInt(msg.content); 84 | if (isNaN(P2_id) || (!u2_data.pokemons[P2_id] && P2_id !== -1)) return msg.reply("Invalid pokemon ID was provided, provide a valid ID, or -1 for nothing or type `cancel` to cancel the trade"); 85 | P2 = P2_id=== -1 ? -1 : await pokecord.Spawn(u2_data.pokemons[msg.content]); 86 | 87 | col.stop("done"); 88 | }); 89 | 90 | col.on('end', async (shit, reason) => { 91 | if (reason === "time") { 92 | interaction.followUp("The mentioned user took way too much time to respond so the trade is expired"); 93 | 94 | msg.edit({ 95 | embeds: [{ 96 | title: "Trade Offer Expired", 97 | color: "#ff0000", 98 | descrption: `You took way too much time to respond` 99 | }] 100 | }) 101 | } else if (reason === "cancel") { 102 | interaction.followUp("The mentioned user denied ❌ the trade offer"); 103 | 104 | msg.edit({ 105 | embeds: [{ 106 | title: "Trade Offer Declined Successfully", 107 | descrption: `Trade offer from ${interaction.user.username} is declined` 108 | }] 109 | }) 110 | } else { 111 | const msg = await interaction.followUp(`The mentioned user offered ${P2 === -1 ? "nothing" : P2.name}, do you want to confirm the trade, if yes react with ✅ else react with ❌`); 112 | await msg.react("✅") 113 | await msg.react("❌") 114 | 115 | const c = new ReactionCollector(msg, { time: 30000, filter: (r, u) => ["✅", "❌"].includes(r.emoji.name) && u.id === interaction.user.id }); 116 | c.on('collect', (rec) => c.stop(rec.emoji.name)); 117 | 118 | c.on('end', async (rec) => { 119 | if (reason === "time") { 120 | interaction.followUp("You took way too much time to respond so the trade is expired"); 121 | } else if (reason === "❌") { 122 | msg.edit({ 123 | embeds: [{ 124 | title: "Trade Offer was Declined", 125 | descrption: `Trade offer was declined by ${interaction.user.username}` 126 | }] 127 | }) 128 | } else { 129 | if (P1 !== -1) { 130 | u1_data.pokemons = u1_data.pokemons.filter((v, i) => i !== P1_id); 131 | u2_data.pokemons.push(P1.id) 132 | } 133 | if (P2 !== -1) { 134 | u2_data.pokemons = u2_data.pokemons.filter((v, i) => i !== P2_id); 135 | u1_data.pokemons.push(P2.id) 136 | } 137 | 138 | msg.channel.send({ 139 | embeds: [{ 140 | title: "Trade Ended Successfully", 141 | descrption: ` 142 | ${interaction.user.username} got ${P2 === -1 ? "Nothing" : P2.name},\n 143 | ${user.username} got ${P1 === -1 ? "Nothing" : P1.name}, 144 | ` 145 | }] 146 | }) 147 | 148 | await userConfig.findOneAndUpdate({ user: interaction.user.id }, { pokemons: u1_data.pokemons }); 149 | await userConfig.findOneAndUpdate({ user: user.id }, { pokemons: u2_data.pokemons }); 150 | } 151 | }) 152 | } 153 | }) 154 | } 155 | }) 156 | } 157 | } -------------------------------------------------------------------------------- /src/commands/owner/badge.js: -------------------------------------------------------------------------------- 1 | const { hasEmoji } = require('node-emoji'); 2 | 3 | const badges = require('../../models/badge'); 4 | const users = require('../../models/userConfig'); 5 | const randomId = require('../../utility/randomId'); 6 | 7 | module.exports = { 8 | data: { 9 | name: "badge", 10 | description: "Manage badges of the bot", 11 | options: [{ 12 | name: 'create', 13 | description: "Create a new badge", 14 | type: 1, 15 | options: [{ 16 | name: 'name', 17 | description: "Name of this badge", 18 | type: 3, 19 | required: true 20 | }, { 21 | name: 'emoji', 22 | description: "Emoji of this badge", 23 | type: 3, 24 | required: true 25 | }] 26 | }, { 27 | name: 'edit', 28 | description: "Edit a new badge", 29 | type: 1, 30 | options: [{ 31 | name: 'id', 32 | description: "ID of the badge you want to edit", 33 | type: 3, 34 | required: true 35 | }, { 36 | name: 'name', 37 | description: "New name of this badge", 38 | type: 3, 39 | required: false 40 | }, { 41 | name: 'emoji', 42 | description: "New emoji of this badge", 43 | type: 3, 44 | required: false 45 | }] 46 | }, { 47 | name: 'delete', 48 | description: "Delete a new badge", 49 | type: 1, 50 | options: [{ 51 | name: 'id', 52 | description: "ID of the badge you want to delete", 53 | type: 3, 54 | required: true 55 | }] 56 | }, { 57 | name: 'give', 58 | description: "Give a badge to someone", 59 | type: 1, 60 | options: [{ 61 | name: 'id', 62 | description: "ID of the badge you want to give", 63 | type: 3, 64 | required: true 65 | }, { 66 | name: 'user-id', 67 | description: "ID of the user to whom you want to give the badge", 68 | type: 3, 69 | required: true 70 | }] 71 | }, { 72 | name: 'take', 73 | description: "Take a badge from someone", 74 | type: 1, 75 | options: [{ 76 | name: 'id', 77 | description: "ID of the badge you want to take", 78 | type: 3, 79 | required: true 80 | }, { 81 | name: 'user-id', 82 | description: "ID of the user from whom you want to take the badge", 83 | type: 3, 84 | required: true 85 | }] 86 | }, { 87 | name: 'list', 88 | type: 1, 89 | description: "Get the list of badges" 90 | }] 91 | }, 92 | 93 | run: async (client, interaction) => { 94 | if (!client.owners.includes(interaction.user.id)) return interaction.reply({ content: `You are not a owner` }); 95 | 96 | await interaction.deferReply(); 97 | 98 | let option = interaction.options.getSubcommand(), 99 | id = interaction.options.getString("id"), 100 | name = interaction.options.getString("name"), 101 | emoji = interaction.options.getString("emoji")?.split(/ +/g)[0], 102 | user_id = interaction.options.getString("user-id"), 103 | user = client.users.cache.get(user_id), 104 | userData = user ? await users.findOne({ user: user?.id }) || await users.create({ user: user?.id }) : null, 105 | badge = await badges.findOne({ id }); 106 | 107 | if (option === "create") { 108 | if (!isEmoji(client, emoji)) return interaction.editReply({ 109 | embeds: [{ 110 | title: "❌ Invalid Emoji", 111 | description: "Please provide a valid emoji" 112 | }] 113 | }); 114 | 115 | badge = await badges.create({ 116 | id: randomId(8), 117 | name, 118 | emoji, 119 | createdAt: Date.now() 120 | }); 121 | 122 | interaction.editReply({ 123 | embeds: [{ 124 | title: "✅ Successfully created the badge!", 125 | fields: [{ 126 | name: "Badge ID", 127 | value: badge.id, 128 | inline: true 129 | }, { 130 | name: "Badge Name", 131 | value: badge.name, 132 | inline: true 133 | }, { 134 | name: "Badge Emoji", 135 | value: client.emojis.cache.get(badge.emoji) || badge.emoji || "Unknown", 136 | inline: true 137 | }, { 138 | name: "Created At", 139 | value: ``, 140 | inline: true 141 | }] 142 | }] 143 | }) 144 | } else if (option === "edit") { 145 | if (!badge) return interaction.editReply({ 146 | embeds: [{ 147 | title: "❌ Invalid badge", 148 | description: "Please provide a valid badge ID" 149 | }] 150 | }); 151 | 152 | name = name || badge.name; 153 | emoji = emoji || badge.emoji; 154 | 155 | if (!isEmoji(client, emoji)) return interaction.editReply({ 156 | embeds: [{ 157 | title: "❌ Invalid Emoji", 158 | description: "Please provide a valid emoji" 159 | }] 160 | }); 161 | 162 | badge = await badges.findOneAndUpdate({ id }, { 163 | name, 164 | emoji, 165 | createdAt: Date.now() 166 | }, { new: true }); 167 | 168 | interaction.editReply({ 169 | embeds: [{ 170 | title: "✅ Successfully edited the badge!", 171 | fields: [{ 172 | name: "Badge ID", 173 | value: badge.id, 174 | inline: true 175 | }, { 176 | name: "Badge Name", 177 | value: badge.name, 178 | inline: true 179 | }, { 180 | name: "Badge Emoji", 181 | value: client.emojis.cache.get(badge.emoji) || badge.emoji || "Unknown", 182 | inline: true 183 | }, { 184 | name: "Created At", 185 | value: `` || "Unknown Date", 186 | inline: true 187 | }] 188 | }] 189 | }) 190 | } else if (option === "delete") { 191 | if (!badge) return interaction.editReply({ 192 | embeds: [{ 193 | title: "❌ Invalid badge", 194 | description: "Please provide a valid badge ID" 195 | }] 196 | }); 197 | 198 | await badges.findOneAndDelete({ id }); 199 | 200 | interaction.editReply({ 201 | embeds: [{ 202 | title: "✅ Badge Deleted", 203 | }] 204 | }); 205 | } else if (option === "give") { 206 | if (!badge) return interaction.editReply({ 207 | embeds: [{ 208 | title: "❌ Invalid badge", 209 | description: "Please provide a valid badge ID" 210 | }] 211 | }); 212 | 213 | if (!user) return interaction.editReply({ 214 | embeds: [{ 215 | title: "❌ Invalid User", 216 | description: "Please provide a valid user ID" 217 | }] 218 | }); 219 | 220 | if (userData?.badges?.includes(badge.id)) return interaction.editReply({ 221 | embeds: [{ 222 | title: "❌ Cannot Add Badge", 223 | description: "The provided user already have this badge!" 224 | }] 225 | }); 226 | 227 | await users.findOneAndUpdate({ user: user.id }, { $push: { badges: badge.id } }); 228 | 229 | interaction.editReply({ 230 | embeds: [{ 231 | title: "✅ Badge Added", 232 | description: `Successfully gave **${badge.name}** to **${user.username}**` 233 | }] 234 | }); 235 | } else if (option === "take") { 236 | if (!badge) return interaction.editReply({ 237 | embeds: [{ 238 | title: "❌ Invalid badge", 239 | description: "Please provide a valid badge ID" 240 | }] 241 | }); 242 | 243 | if (!user) return interaction.editReply({ 244 | embeds: [{ 245 | title: "❌ Invalid User", 246 | description: "Please provide a valid user ID" 247 | }] 248 | }); 249 | 250 | if (!userData?.badges?.includes(badge.id)) return interaction.editReply({ 251 | embeds: [{ 252 | title: "❌ Cannot Take Badge", 253 | description: "The provided user do not have this badge!" 254 | }] 255 | }); 256 | 257 | await users.findOneAndDelete({ user: user.id }, { $pull: { badges: badge.id } }); 258 | 259 | interaction.editReply({ 260 | embeds: [{ 261 | title: "✅ Badge Remove", 262 | description: `Successfully took **${badge.name}** from **${user.username}**` 263 | }] 264 | }); 265 | } else if (option === "list") { 266 | const badg = await badges.find(); 267 | 268 | if (badg.length === 0) return interaction.editReply({ 269 | embeds: [{ 270 | title: "This Bot Do Not Have Badges", 271 | color: "RED" 272 | }] 273 | }) 274 | 275 | let str = ""; 276 | 277 | for (let i = 0; i < badg.length; i++) { 278 | const bg = badg[i]; 279 | 280 | str += `${client.emojis.cache.get(bg?.emoji)?.toString() || bg?.emoji} **${bg?.name}** | Created At: \n` 281 | } 282 | 283 | interaction.editReply({ 284 | embeds: [{ 285 | title: "Badges Of The Bot", 286 | description: str 287 | }] 288 | }) 289 | } 290 | } 291 | } 292 | function isEmoji(client, emoji) { 293 | return hasEmoji(emoji) || client.emojis.cache.get(/\d+/.exec(emoji) + ""); 294 | } -------------------------------------------------------------------------------- /src/commands/owner/status.js: -------------------------------------------------------------------------------- 1 | const { Client } = require("discord.js"); 2 | 3 | module.exports = { 4 | data: { 5 | name: "status", 6 | description: "Change the status of your client!", 7 | options: [{ 8 | name: "status", 9 | description: "the new status of your client!", 10 | required: true, 11 | type: "STRING", 12 | }], 13 | }, 14 | 15 | /** 16 | * 17 | * @param {Client} client 18 | * @param {*} interaction 19 | * @returns 20 | */ 21 | run: async (client, interaction,args) => { 22 | if (!client.owners.includes(interaction.user.id)) return interaction.reply({ content: `You are not a owner` }); 23 | 24 | client.user.setActivity({ 25 | name: interaction.options.getString("status", true), 26 | type: "PLAYING" 27 | }); 28 | 29 | interaction.reply({ content: `Status changed to : ${interaction.options.getString("status")}` }); 30 | } 31 | } -------------------------------------------------------------------------------- /src/events/guildMemberAdd.2.js: -------------------------------------------------------------------------------- 1 | const guildConfig = require('../models/guildConfig'); 2 | const canvacord = require('canvacord'); 3 | 4 | module.exports = async (client, member) => { 5 | const data = await guildConfig.findOne({ id: member.guild.id }), 6 | channel = member.guild.channels.cache.get(data?.welcome.channel); 7 | 8 | if (!channel || data?.welcome.enable !== true) return; 9 | 10 | const welcomeImage = new canvacord.Welcomer() 11 | .setAvatar(member.user.displayAvatarURL({ dynamic: false, format: "png" })) 12 | .setUsername(member.user.username) 13 | .setDiscriminator(member.user.discriminator) 14 | .setGuildName(member.guild.name) 15 | .setMemberCount(member.guild.memberCount + 1) 16 | .setBackground("https://cdn.discordapp.com/attachments/714747037983309866/909416865539969065/2Q.png"), 17 | 18 | content = data.welcome.message 19 | .replace(/\{mention\}/g, member.user.toString()) 20 | .replace(/\{user\}/g, member.user.username) 21 | .replace(/\{server\}/g, member.guild.name) 22 | .replace(/\{members\}/g, member.guild.memberCount + 1) 23 | 24 | channel.send({ 25 | content, 26 | files: [await welcomeImage.build()] 27 | }) 28 | } -------------------------------------------------------------------------------- /src/events/guildMemberAdd.js: -------------------------------------------------------------------------------- 1 | const stats = require('../models/guildStats'); 2 | 3 | module.exports =async (client, member) => { 4 | const data = await stats.findOne({ guild: member.guild.id }); 5 | 6 | if (!data || !data.members || data.members === "0") return; 7 | 8 | const channel = member.guild.channels.cache.get(data.members); 9 | 10 | if (!channel || !channel.manageable) return; 11 | 12 | channel.setName(`Members : ${member.guild.memberCount}`) 13 | } -------------------------------------------------------------------------------- /src/events/guildMemberRemove.2.js: -------------------------------------------------------------------------------- 1 | const { MessageAttachment } = require('discord.js'); 2 | 3 | const guildConfig = require('../models/guildConfig'); 4 | const createLeave = require('../utility/createLeave'); 5 | 6 | module.exports = async (client, member) => { 7 | const data = await guildConfig.findOne({ id: member.guild.id }), 8 | channel = member.guild.channels.cache.get(data?.leave.channel); 9 | 10 | if (!channel || !data?.leave.enable) return; 11 | 12 | const a = new MessageAttachment(await createLeave(member), "leave.png") 13 | 14 | channel.send({ 15 | files: [a], 16 | embeds: [{ 17 | description: data.leave.message.replace(/{user}/g, member.user.username).replace(/{members}/g, member.guild.memberCount).replace(/{mention}/g, member.user.username).replace(/{guild}/g, member.guild.name), 18 | image: { 19 | url: "attachment://leave.png" 20 | } 21 | }] 22 | }) 23 | } -------------------------------------------------------------------------------- /src/events/guildMemberRemove.js: -------------------------------------------------------------------------------- 1 | const stats = require('../models/guildStats'); 2 | 3 | module.exports = async(client, member) => { 4 | const data = await stats.findOne({ guild: member.guild.id }); 5 | 6 | if (!data || !data.members || data.members === "0") return; 7 | 8 | const channel = member.guild.channels.cache.get(data.members); 9 | 10 | if (!channel || !channel.manageable) return; 11 | 12 | channel.setName(`Members : ${member.guild.memberCount}`) 13 | } -------------------------------------------------------------------------------- /src/events/interactionCreate.2.js: -------------------------------------------------------------------------------- 1 | const reactionRole = require("../models/reactionRole"); 2 | 3 | module.exports = async (client, interaction) => { 4 | if (!interaction.isButton() || !interaction.guild) return; 5 | 6 | const emoji = interaction?.component?.emoji; 7 | 8 | const menu = await reactionRole.findOne({ message: interaction.message.id }); 9 | 10 | if (!menu || menu.roles.length === 0 || !menu.roles.some(v => v.emoji === emoji.id || v.emoji === emoji.name)) return; 11 | 12 | const member = interaction.guild.members.cache.get(interaction.user.id); 13 | 14 | menu.roles.forEach(v => { 15 | const role = interaction.guild.roles.cache.get(v.role); 16 | 17 | if ((v.emoji !== emoji.name && v.emoji !== emoji.id)) return; 18 | 19 | if (!member.roles.cache.has(role.id)) { 20 | member.roles.add(role).then(() => { 21 | interaction.reply({ content: `I gave you the **${role.name}** role in ${interaction.guild.name}`, ephemeral: true }) 22 | }).catch(() => { 23 | interaction.reply({ content: `I was unable to give you the role in ${interaction.guild.name}`, ephemeral: true }) 24 | }) 25 | } else { 26 | member.roles.remove(role).then(() => { 27 | interaction.reply({ content: `I removed the **${role.name}** role from you in ${interaction.guild.name}`, ephemeral: true }) 28 | }).catch(() => { 29 | interaction.reply({ content: `I was unable to remove a role from you in ${interaction.guild.name}`, ephemeral: true }) 30 | }) 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /src/events/interactionCreate.3.js: -------------------------------------------------------------------------------- 1 | const tickets = require('../models/tickets'); 2 | const ticket = require('../models/ticket'); 3 | 4 | module.exports = async (client, interaction) => { 5 | if (!interaction.isButton() || !interaction.guild) return; 6 | 7 | const data = await tickets.findOne({ guild: interaction.guildId, message: interaction.message.id }); 8 | member = interaction.member; 9 | 10 | if (!data) return; 11 | 12 | const user_tickets = await ticket.find({ panel: data.name, user: interaction.user.id, closed: false }).lean(); 13 | 14 | if (data.banned.some(v => member.roles.cache.has(v))) return interaction.reply({ content: "You are banned from the panel", ephemeral: true }); 15 | if (user_tickets.length >= data.max) return interaction.reply({ content: "You already made maximum tickets `(" + data.max + ")` you are allowed to make in this panel", ephemeral: true }); 16 | 17 | const overwrites = [{ 18 | id: interaction.guild.roles.everyone.id, 19 | deny: ["VIEW_CHANNEL"], 20 | type: "role" 21 | }, { 22 | id: interaction.user.id, 23 | allow: ["VIEW_CHANNEL"], 24 | type: "member" 25 | }]; 26 | 27 | data.moderators.forEach(v => overwrites.push({ id: v, allow: ["VIEW_CHANNEL"], type: "role" })); 28 | 29 | const channel = await interaction.guild.channels.create(`ticket - ${data.index + 1} `, { 30 | reason: "for ticket system", 31 | type: "GUILD_TEXT", 32 | permissionOverwrites: overwrites 33 | }); 34 | 35 | interaction.reply({ content: "ticket is created successfully", ephemeral: true }); 36 | 37 | channel.send({ content: `${interaction.user.toString()}, stay patient staff will be arving soon.` }); 38 | 39 | interaction.guild.channels.cache.get(data.logs)?.send({ 40 | content: `${data.moderators.map(v => `<@&${v}>`).join(", ")}, A new ticket ( ${channel.toString()} ) was created go check it out`, 41 | embeds: [{ 42 | title: "New ticket created", 43 | timestamps: Date.now(), 44 | fields: [{ 45 | name: "Panel", 46 | value: data.name, 47 | inline: true 48 | }, { 49 | name: "User", 50 | value: interaction.user.username, 51 | inline: true 52 | }, { 53 | name: "Ticket", 54 | value: channel.toString(), 55 | inline: true 56 | }] 57 | }] 58 | }) 59 | 60 | await tickets.findOneAndUpdate({ guild: interaction.guildId, message: interaction.message.id }, { $inc: { index: 1 } }); 61 | await ticket.create({ channel: channel.id, guild: interaction.guildId, user: interaction.user.id, panel: data.name }); 62 | } -------------------------------------------------------------------------------- /src/events/interactionCreate.4.js: -------------------------------------------------------------------------------- 1 | const suggestion = require("../models/suggestion"); 2 | 3 | module.exports = async (client, interaction) => { 4 | if (!interaction.isButton()) return; 5 | 6 | const sug = await suggestion.findOne({ message: interaction.message?.id }); 7 | 8 | if (!sug) return; 9 | await interaction.deferReply({ ephemeral: true }); 10 | 11 | if (sug.votes.up.includes(interaction.user.id) || sug.votes.down.includes(interaction.user.id)) return interaction.editReply({ 12 | embeds: [{ 13 | color: "RED", 14 | title: "❌ Already voted" 15 | }] 16 | }); 17 | 18 | sug.votes[interaction.customId === "1" ? "up" : "down"]?.push(interaction.user.id); 19 | await suggestion.findOneAndUpdate({ message: sug.message }, sug); 20 | 21 | interaction.editReply({ 22 | embeds: [{ 23 | color: "GREEN", 24 | title: "✅ Voted Successfully" 25 | }] 26 | }); 27 | const msg = await interaction.channel.messages.fetch(sug.message); 28 | 29 | if (!msg) return; 30 | 31 | msg.embeds[0].fields[0].value = sug.votes.up.length.toString(); 32 | msg.embeds[0].fields[1].value = sug.votes.down.length.toString(); 33 | 34 | msg?.edit({ 35 | embeds: msg.embeds 36 | }) 37 | } -------------------------------------------------------------------------------- /src/events/interactionCreate.5.js: -------------------------------------------------------------------------------- 1 | const polls = require("../models/polls"); 2 | 3 | module.exports = async (client, interaction) => { 4 | if (!interaction.isButton()) return; 5 | 6 | const pol = await polls.findOne({ message: interaction.message.id }); 7 | 8 | if (!pol) return; 9 | 10 | await interaction.deferReply({ 11 | ephemeral: true 12 | }); 13 | 14 | if (pol.voters.includes(interaction.user.id)) return interaction.editReply({ 15 | embeds: [{ 16 | color: "RED", 17 | title: "❌ Already Voted!" 18 | }] 19 | }); 20 | 21 | pol.votes = pol.votes || {}; 22 | 23 | if (pol.votes[interaction.customId]) pol.votes[interaction.customId] += 1 24 | else pol.votes[interaction.customId] = 1; 25 | 26 | pol.voters.push(interaction.user.id); 27 | 28 | await polls.findOneAndUpdate({ message: pol.message }, pol); 29 | 30 | interaction.editReply({ 31 | embeds: [{ 32 | color: "GREEN", 33 | title: "✅ Voted Successfully" 34 | }] 35 | }); 36 | 37 | const m = interaction.message; 38 | 39 | m.edit({ 40 | components: m.components.map(row => { 41 | row.components = row.components?.map(v => { 42 | v.label = `${pol.votes[v.customId] || 0}`; 43 | 44 | return v; 45 | }); 46 | 47 | return row; 48 | }) 49 | }) 50 | } -------------------------------------------------------------------------------- /src/events/interactionCreate.js: -------------------------------------------------------------------------------- 1 | const ms = require('ms-prettify').default; 2 | 3 | module.exports = async (client, interaction) => { 4 | try { 5 | if (!interaction.isCommand()) return; 6 | 7 | const command = client.commands.get(interaction.commandName), member = interaction.guild.members.cache.get(interaction.member.id); 8 | 9 | if (!command || (!command.dm && !interaction.guild)) return; 10 | 11 | if (command.permissions?.length > 0 && !(command.permissions.some(v => member.permissions.has(v)))) return interaction.reply({ content: `You do not have any of the required permissions to use this command, required permissions : ${command.permissions.join(", ")}` }) 12 | 13 | const t = client.timeouts.get(`${interaction.user.id}_${command.name}`) || 0; 14 | 15 | if (Date.now() - t < 0) return interaction.reply({ content: `You are on a timeout of ${ms(t - Date.now(), { till: 'second' })}` }); 16 | 17 | client.timeouts.set(`${interaction.user.id}_${command.name}`, Date.now() + (command.timeout || 0)); 18 | 19 | command.run(client, interaction); 20 | } catch (e) { 21 | console.log(e); 22 | interaction.reply({ content: "There was an issue in executing the command" }); 23 | } 24 | } -------------------------------------------------------------------------------- /src/events/messageCreate.2.js: -------------------------------------------------------------------------------- 1 | const guildConfigs = require('../models/guildConfig'); 2 | const users = require('../models/user_xp'); 3 | 4 | module.exports = async (client, message) => { 5 | const data = await guildConfigs.findOne({ id: message.guild.id }) || {}; 6 | 7 | if (!data.xp || data?.ignoreXP?.includes(message.channel.id) || message.author.bot) return; 8 | 9 | const userData = await users.findOne({ user: message.author.id, guild: message.guild.id }) || await users.create({ user: message.author.id, guild: message.guild.id }); 10 | 11 | if (userData.lastXP + (data.xpTimeout || 1000) > Date.now()) return; 12 | let xp = Math.floor(((Math.random() * (data.xpLimit.up - data.xpLimit.down)) + data.xpLimit.down) * data.xpRate), 13 | reqXP = 100; 14 | 15 | userData.xp += xp; 16 | 17 | for (let i = 1; i <= userData.level; i++)reqXP += 5 * (i ^ 2) + (50 * i) + 100; 18 | 19 | if (userData.xp >= reqXP) { 20 | userData.level += 1; 21 | data.levelReward = data.levelReward || {}; 22 | 23 | const r = data.levelReward[userData.level], role = message.guild.roles.cache.get(r), 24 | channel = message.guild.channels.cache.get(data.xpLevelUp.channel) || message.channel; 25 | 26 | if (r !==undefined) { 27 | message.member.roles.add(role, `Level reward for reaching ${userData.level} level`).then(() => { 28 | reply(data.levelRewardMessage.success, channel, message, userData, data, role) 29 | }).catch(() => { 30 | reply(data.levelRewardMessage.fail, channel, message, userData, data, role); 31 | }) 32 | } else { 33 | reply(data.xpLevelUp.message, channel, message, userData, data); 34 | } 35 | } 36 | 37 | await users.findOneAndUpdate({ user: message.author.id, guild: message.guild.id }, { 38 | xp: userData.xp, 39 | level: userData.level, 40 | lastXP: Date.now() 41 | }); 42 | } 43 | 44 | function reply(content, channel, message, userData, data, role) { 45 | if (!data.xpLevelUp.enable) return; 46 | 47 | channel.send({ content: content.replace(/{mention}/g, message.author.toString()).replace(/{level}/, userData.level).replace(/{xp}/, userData.xp).replace(/{role}/, role?.name) }); 48 | } -------------------------------------------------------------------------------- /src/events/messageCreate.3.js: -------------------------------------------------------------------------------- 1 | const guildConfigs = require('../models/guildConfig'); 2 | 3 | module.exports = async (client, message) => { 4 | if (message.author.bot) return; 5 | 6 | const data = await guildConfigs.findOne({ id: message.guild.id }) || {}; 7 | 8 | if (!data?.tags?.length > 0) return; 9 | data.tags?.forEach(tag => { 10 | const content = tag.case ? message.content : message.content.toLowerCase(), 11 | name = tag.case ? tag.name : tag.name.toLowerCase(); 12 | 13 | if (!(tag.include ? content.includes(name + " ") || content.endsWith(" " + name) : content === name)) return; 14 | 15 | const res = tag.response.replace(/{mention}/g, message.author.toString()).replace(/{user}/g, message.author.username).replace(/{server}/g, message.guild.name) 16 | 17 | let msg = tag.embed ? { 18 | embeds: [{ 19 | description: res 20 | }] 21 | } : { 22 | content: res 23 | }; 24 | 25 | message.reply(msg); 26 | }) 27 | } -------------------------------------------------------------------------------- /src/events/messageCreate.js: -------------------------------------------------------------------------------- 1 | const guildConfigs = require('../models/guildConfig'); 2 | const users = require('../models/userConfig'); 3 | const pokecord = require('pokecord'); 4 | const { MessageEmbed, MessageCollector } = require('discord.js'); 5 | 6 | module.exports = async (client, message) => { 7 | const p = ""; 8 | if (message.author.bot) return; 9 | 10 | const data = await guildConfigs.findOne({ id: message.guild.id }); 11 | 12 | if (!data || !data.pokemon.spawn) return; 13 | 14 | data.pokemon.points += Math.floor(Math.random() * 3) + 1; 15 | 16 | if (data.pokemon.points < data.pokemon.afterPoints) return guildConfigs.findOneAndUpdate({ id: message.guild.id }, { "pokemon.points": data.pokemon.points }); 17 | 18 | await guildConfigs.findOneAndUpdate({ id: message.guild.id }, { "pokemon.points": 0 }); 19 | 20 | const pokemon = await pokecord.Spawn(); 21 | 22 | const channel = message.guild.channels.cache.get(data.pokemon.spawnAt) || message.channel; 23 | 24 | const embed = new MessageEmbed() 25 | .setTitle("A new pokemon has appeared") 26 | .setImage(pokemon.imageURL) 27 | .setDescription(`Catch pokemon by typing \`${p}catch < pokemon name >\``); 28 | 29 | const msg = await channel.send({ embeds: [embed] }); 30 | 31 | let catched = false; 32 | 33 | msg.channel.awaitMessages({ 34 | time: 60000, 35 | errors: ['time'], 36 | filter: (m) => m.content.toLowerCase() === `${p}catch ${pokemon.name.toLowerCase()}` || m.content.toLowerCase() === `${p}c ${pokemon.name.toLowerCase()}`, 37 | max: 1 38 | }).then(async col => { 39 | catched = true; 40 | const msg = col.first(); 41 | 42 | await users.findOneAndUpdate({ user: msg.author.id }, { $push: { pokemons: pokemon.id } }) || await users.create({ 43 | user: msg.author.id, 44 | pokemons: [pokemon.id] 45 | }); 46 | 47 | msg.reply(`You successfully caught \`${pokemon.name}\` pokemon`); 48 | }).catch(() => { 49 | catched = true; 50 | 51 | embed.setTitle("Pokemon ran away") 52 | .setImage(pokemon.imageURL) 53 | msg.edit({ embeds: [embed] }); 54 | }) 55 | 56 | const col = new MessageCollector(message.channel, { filter: (m) => m.content.toLowerCase() === `${p}h` || m.content.toLowerCase() === `${p}hint`, time: 55000 }) 57 | 58 | let t = 0; 59 | 60 | col.on('collect', (msg) => { 61 | if (catched) return col.stop(); 62 | 63 | if (Date.now() - t < 10000) return msg.reply("You are on a timeout to use the hint command"); 64 | t = Date.now(); 65 | 66 | let hint = pokemon.name, i = pokemon.name.length / 2; 67 | 68 | while (--i >= 0) { 69 | let p = Math.floor(Math.random() * pokemon.length); 70 | 71 | hint = hint.replace(hint[p], "_") 72 | } 73 | 74 | msg.reply(`Hint for this pokemon is ${hint}`) 75 | }) 76 | } -------------------------------------------------------------------------------- /src/events/ready.js: -------------------------------------------------------------------------------- 1 | const { MessageAttachment } = require('discord.js'); 2 | const timers = require('../models/timer'); 3 | const startTimer = require('../utility/startTimer'); 4 | 5 | module.exports = async (client) => { 6 | console.log("Client is up"); 7 | 8 | // 926705336675631195 9 | client.application.commands.set([...client.commands.map(v => v.data)], "732883841395720213"); 10 | 11 | // Reloading the timers 12 | const data = await timers.find(); 13 | 14 | data.forEach((timer) => { 15 | startTimer(client, timer); 16 | }) 17 | } -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | // Importing Lib 2 | const Discord = require('discord.js'); 3 | const dotenv = require('dotenv'); 4 | const mongoose = require("mongoose"); 5 | const app = (require('express'))(); 6 | const { readdirSync } = require('fs'); 7 | const { join } = require('path'); 8 | 9 | // Hosting 10 | app.get('/', (r, res) => res.sendStatus(200)); 11 | 12 | app.listen(process.env.PORT || 3000); 13 | 14 | // Loading the enviroment variables 15 | dotenv.config(); 16 | 17 | // Connecting to mongoose 18 | mongoose.connect(process.env.MONGO_URI, { useUnifiedTopology: true, useNewUrlParser: true }); 19 | 20 | // Creating the client instance 21 | const client = new Discord.Client({ 22 | intents: ["GUILDS", "GUILD_MESSAGE_REACTIONS", "GUILD_MEMBERS", "GUILD_MESSAGES", "GUILD_VOICE_STATES"], 23 | partials: ["REACTION", "MESSAGE"] 24 | }); 25 | 26 | client.timeouts = new Discord.Collection(); 27 | client.commands = new Discord.Collection(); 28 | client.categories = readdirSync(join(__dirname, "./commands")); 29 | client.owners = ["441943765855240192", "723049421021118535"]; 30 | 31 | // Event handler 32 | readdirSync(join(__dirname, "./events")).forEach(file => 33 | client.on(file.split(".")[0], (...args) => require(`./events/${file}`)(client, ...args)) 34 | ); 35 | 36 | // Command Handler 37 | for (let i = 0; i < client.categories.length; i++) { 38 | const commands = readdirSync(join(__dirname, `./commands/${client.categories[i]}`)).filter(file => file.endsWith(".js")); 39 | 40 | for (let j = 0; j < commands.length; j++) { 41 | const command = require(`./commands/${client.categories[i]}/${commands[j]}`); 42 | if (!command || !command?.data?.name || typeof (command?.run) !== "function") continue; 43 | command.category = client.categories[i]; 44 | client.commands.set(command.data.name, command); 45 | } 46 | } 47 | 48 | // Logging in the client! 49 | client.login(process.env.TOKEN); -------------------------------------------------------------------------------- /src/models/badge.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const Badge = new Schema({ 4 | id: String, 5 | name: String, 6 | emoji: String, 7 | createdAt: String, 8 | }) 9 | 10 | module.exports = model("badge", Badge); -------------------------------------------------------------------------------- /src/models/guildConfig.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const guildStats = new Schema({ 4 | id: String, 5 | pokemon: { 6 | spawn: { 7 | type: Boolean, 8 | default: false 9 | }, 10 | afterPoints: { 11 | type: Number, 12 | default: 100 13 | }, 14 | points: { 15 | type: Number, 16 | default: 0 17 | }, 18 | spawnAt: String, 19 | lastMessage: String 20 | }, 21 | welcome: { 22 | enable: Boolean, 23 | channel: String, 24 | message: { 25 | type: String, 26 | default: "Welcome {mention}, To **{server}**\nNow we are a family of {members}" 27 | } 28 | }, 29 | 30 | ignoreXP: [String], 31 | xp: { 32 | type: Boolean, 33 | default: false 34 | }, 35 | xpTimeout: { 36 | type: Number, 37 | default: 60000 38 | }, 39 | xpLevelUp: { 40 | message: { 41 | type: String, 42 | default: "Congrats {mention} 🎉 on reaching {level} level" 43 | }, 44 | channel: { 45 | type: String, 46 | default: "0" 47 | }, 48 | enable: { 49 | type: Boolean, 50 | default: true 51 | } 52 | }, 53 | xpRate: { 54 | type: Number, 55 | default: 1 56 | }, 57 | xpLimit: { 58 | up: { 59 | type: Number, 60 | default: 20 61 | }, 62 | down: { 63 | type: Number, 64 | default: 5 65 | }, 66 | }, 67 | tags: [{ 68 | name: String, 69 | response: String, 70 | embed: Boolean, 71 | case: Boolean, 72 | include: Boolean, 73 | }], 74 | levelRewardMessage: { 75 | success: { 76 | type: String, 77 | default: "Congrats {mention} 🎉 on reaching {level} level, and you got **{role}** role as a reward 🎉" 78 | }, 79 | fail: { 80 | type: String, 81 | default: "Congrats {mention} 🎉 on reaching {level} level, you were supposed to get **{role}** role as a reward but I was unable to give you the role" 82 | }, 83 | }, 84 | levelReward: Object, 85 | /** 86 | levelReward = { 87 | "1": "roleid-1", 88 | 2: "another-id" 89 | // etc 90 | } 91 | */ 92 | leave: { 93 | enable: { 94 | type: Boolean, 95 | default: false 96 | }, 97 | channel: String, 98 | message: { 99 | type: String, 100 | default: `**{user}** left the server.` 101 | } 102 | }, 103 | suggestion:String 104 | }) 105 | 106 | module.exports = model("Guild_Config", guildStats); -------------------------------------------------------------------------------- /src/models/guildStats.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const guildStats = new Schema({ 4 | guild: String, 5 | members: String, 6 | }) 7 | 8 | module.exports = model("Guild_Stats", guildStats); -------------------------------------------------------------------------------- /src/models/polls.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const Poll = new Schema({ 4 | question: String, 5 | message: String, 6 | channel: String, 7 | guild: String, 8 | votes: Object, 9 | voters: { 10 | type: [String], 11 | default: [] 12 | }, 13 | emojis: [String], 14 | ended: { 15 | type: Boolean, 16 | default: false 17 | } 18 | }) 19 | 20 | module.exports = model("polls", Poll); -------------------------------------------------------------------------------- /src/models/reactionRole.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const reactionRole = new Schema({ 4 | name: String, 5 | guild: String, 6 | message: String, 7 | roles: [{ 8 | role: String, 9 | emoji: String, 10 | }] 11 | }) 12 | 13 | module.exports = model("Reaction_Role_Menu", reactionRole); -------------------------------------------------------------------------------- /src/models/suggestion.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const SuggestionSchema = new Schema({ 4 | suggestion: String, 5 | user: String, 6 | message: String, 7 | channel: String, 8 | guild: String, 9 | votes: { 10 | up: { 11 | type: [String], 12 | default: [] 13 | }, down: { 14 | type: [String], 15 | default: [] 16 | } 17 | }, 18 | createdAt: Number, 19 | }) 20 | 21 | module.exports = model("Suggestions-Data", SuggestionSchema); -------------------------------------------------------------------------------- /src/models/ticket.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const Ticket = new Schema({ 4 | panel: String, 5 | channel: String, 6 | guild: String, 7 | user: String, 8 | closed: { 9 | type: Boolean, 10 | default: false 11 | } 12 | }) 13 | 14 | module.exports = model("ticket", Ticket); -------------------------------------------------------------------------------- /src/models/tickets.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const Tickets = new Schema({ 4 | name: String, 5 | guild: String, 6 | max: { 7 | type: Number, 8 | default: 69 9 | }, 10 | logs: String, 11 | index: { type: Number, default: 0 }, 12 | message: { 13 | type: String, 14 | default: 0 15 | }, 16 | moderators: { 17 | type: [String], 18 | default: [] 19 | }, 20 | banned: { 21 | type: [String], 22 | default: [] 23 | } 24 | }) 25 | 26 | module.exports = model("ticket_panels", Tickets); -------------------------------------------------------------------------------- /src/models/timer.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const Timer = new Schema({ 4 | id: String, 5 | user: String, 6 | channel: String, // for emergency conditions 7 | reason: String, 8 | guild: String, // kinda useless, but might come handy for stats? 9 | time: String, // kinda useless, but might come handy for stats? 10 | createdAt: String, // kinda useless, but might come handy for stats? 11 | endAt: String, 12 | }) 13 | 14 | module.exports = model("timer", Timer); -------------------------------------------------------------------------------- /src/models/userConfig.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const userConfig = new Schema({ 4 | user: String, 5 | pokemons: [String], 6 | badges:[String] 7 | }) 8 | 9 | module.exports = model("User_Pokemons", userConfig); -------------------------------------------------------------------------------- /src/models/user_xp.js: -------------------------------------------------------------------------------- 1 | const { Schema, model } = require('mongoose'); 2 | 3 | const userXPConfig = new Schema({ 4 | user: String, 5 | guild: String, 6 | xp: { 7 | type: Number, 8 | default: 0 9 | }, 10 | level: { 11 | type: Number, 12 | default: 0 13 | }, 14 | lastXP: { 15 | type: Number, 16 | default: 0 17 | }, 18 | }) 19 | 20 | module.exports = model("User_XP", userXPConfig); 21 | -------------------------------------------------------------------------------- /src/utility/commandInfo.js: -------------------------------------------------------------------------------- 1 | module.exports = (command) => { 2 | return command?.data ? { 3 | title: `${command.data.name[0].toUpperCase() + command.data.name.slice(1)}'s Information 📑`, 4 | description: `\`${command.data.description || "No Description"}\`\n\n${command.data.options?.length > 0 ? "Below is the list of otptions of this command" : ""}`, 5 | fields: command.data.options?.map(v => { 6 | return { 7 | name: v.name, 8 | value: `\`${v.description}\`` 9 | } 10 | }), 11 | color: "BLUE" 12 | } : { 13 | title: "❌ Invalid command was provided", 14 | color: "RED" 15 | } 16 | } -------------------------------------------------------------------------------- /src/utility/createHangman.js: -------------------------------------------------------------------------------- 1 | const { createCanvas } = require('canvas'); 2 | 3 | module.exports = async (state = 0) => { 4 | return new Promise((res) => { 5 | const canvas = createCanvas(300, 350); 6 | const ctx = canvas.getContext('2d'); 7 | 8 | ctx.lineWidth = 5; 9 | 10 | // Poll base 11 | createLine(ctx, 50, 330, 150, 330); 12 | 13 | // Poll Mid 14 | createLine(ctx, 100, 330, 100, 50); 15 | 16 | // Poll Head 17 | createLine(ctx, 100, 50, 200, 50); 18 | 19 | // Poll To Man Connector 20 | createLine(ctx, 200, 50, 200, 80); 21 | 22 | // Head 23 | ctx.strokeStyle = state < 1 ? "#a3a3a3" : "#000000"; 24 | ctx.beginPath(); 25 | ctx.arc(200, 100, 20, 0, 2 * Math.PI); 26 | ctx.stroke(); 27 | ctx.closePath(); 28 | 29 | // Main Body 30 | createLine(ctx, 200, 120, 200, 200, state < 2 ? "#a3a3a3" : "#000000"); 31 | 32 | // Hands 33 | createLine(ctx, 200, 150, 170, 130, state < 3 ? "#a3a3a3" : "#000000"); 34 | createLine(ctx, 200, 150, 230, 130, state < 4 ? "#a3a3a3" : "#000000"); 35 | 36 | // Legs 37 | createLine(ctx, 200, 200, 180, 230, state < 5 ? "#a3a3a3" : "#000000"); 38 | createLine(ctx, 200, 200, 220, 230, state < 6 ? "#a3a3a3" : "#000000"); 39 | 40 | res(canvas.toBuffer()) 41 | }) 42 | } 43 | 44 | function createLine(ctx, fromX, fromY, toX, toY, color = "#000000") { 45 | ctx.beginPath(); 46 | 47 | ctx.strokeStyle = color; 48 | ctx.moveTo(fromX, fromY); 49 | ctx.lineTo(toX, toY); 50 | ctx.stroke(); 51 | 52 | ctx.closePath(); 53 | } -------------------------------------------------------------------------------- /src/utility/createLeave.js: -------------------------------------------------------------------------------- 1 | const { createCanvas, loadImage, registerFont } = require('canvas'); 2 | 3 | // NOTE: create a file called tommy.ttf in main folder of your bot and you can download file from here: https://github.com/KartikeSingh/tutorial_bot/blob/master/tommy.ttf 4 | registerFont("./tommy.ttf", { 5 | family: "tommy" 6 | }); 7 | 8 | module.exports = async (member) => { 9 | return new Promise(async (res, rej) => { 10 | try { 11 | const canvas = createCanvas(850, 450); 12 | const ctx = canvas.getContext('2d'); 13 | const r = 160; 14 | 15 | const bg = await loadImage("https://cdn.discordapp.com/attachments/723104565708324915/944119444928606288/PicsArt_02-18-12.03.27.jpg"), 16 | av = await loadImage(member.user.displayAvatarURL({ format: 'png' })); 17 | 18 | // Background of the image 19 | ctx.drawImage(bg, 0, 0, canvas.width, canvas.height); 20 | 21 | // Adding the Text 22 | ctx.font = "bold 55px tommy"; 23 | ctx.fillStyle = "#ff4d00"; 24 | ctx.textAlign = "center"; 25 | ctx.lineWidth = 2; 26 | 27 | // Text Shadow 28 | ctx.shadowBlur = 1.5; 29 | ctx.shadowColor = "#ff4d00"; 30 | 31 | ctx.fillText(`${member.user.tag}`, canvas.width / 2, 285, 800); 32 | ctx.strokeText(`${member.user.tag}`, canvas.width / 2, 285, 800); 33 | 34 | ctx.font = "bold 65px tommy"; 35 | 36 | ctx.fillText("Left The Community", canvas.width / 2, 360, 800); 37 | ctx.strokeText("Left The Community", canvas.width / 2, 360, 800); 38 | 39 | // Removing the shadow 40 | ctx.shadowBlur = 0; 41 | 42 | // Border of the Avatar 43 | ctx.beginPath(); 44 | ctx.arc(canvas.width / 2, canvas.height / 2.9, r / 2, 0, 2 * Math.PI); 45 | ctx.lineWidth = 2; 46 | ctx.strokeStyle = "white"; 47 | ctx.stroke(); 48 | ctx.closePath(); 49 | 50 | // Clipping the avatar 51 | ctx.beginPath(); 52 | ctx.arc((canvas.width / 2), (canvas.height / 2.9), r / 2, 0, 2 * Math.PI); 53 | ctx.clip(); 54 | ctx.closePath(); 55 | 56 | // Adding the avatar 57 | ctx.drawImage(av, (canvas.width / 2 - r / 2), (canvas.height / 2 - r) + 10, r, r); 58 | 59 | res(canvas.toBuffer()); 60 | } catch (e) { 61 | rej(e); 62 | } 63 | }) 64 | } -------------------------------------------------------------------------------- /src/utility/createProfile.js: -------------------------------------------------------------------------------- 1 | module.exports = async (username, avatarUrl, badges) => { 2 | const { createCanvas, loadImage, registerFont } = require('canvas'); 3 | const { fillTextWithTwemoji } = require('node-canvas-with-twemoji-and-discord-emoji'); 4 | 5 | registerFont("./tommy.ttf", { 6 | family: "tommy" 7 | }); 8 | 9 | const canvas = createCanvas(400, 135 + (badges.length / 5 * 45)); 10 | const ctx = canvas.getContext('2d'); 11 | 12 | // For Colored Background 13 | // ctx.fillStyle = '#000000'; // hex code color for the background 14 | // ctx.fillRect(0, 0, canvas.width, canvas.height); 15 | 16 | // For Image Backgroumd 17 | const bg = await loadImage("https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR8mA2D-Ye7VZhUL9GV7vpCUnxoetlYVac2UQns-M8DsbULCNFSqaaQEdx12k1KsPM2I40&usqp=CAU"); // background image url 18 | ctx.drawImage(bg, 0, 0, canvas.width, canvas.height); 19 | 20 | const av = await loadImage(avatarUrl); 21 | 22 | ctx.drawImage(av, 5, 5, 140, 140); 23 | 24 | ctx.fillStyle = "#ffffff"; 25 | ctx.font = "bold 30px tommy" 26 | 27 | ctx.fillText(username, 155, 40, 220); 28 | 29 | for (let i = 0; i < badges.length; i++) { 30 | let row = Math.floor(i / 5), element = i % 5; 31 | 32 | await fillTextWithTwemoji(ctx, badges[i], 155 + (element * 40), 80 + (row * 50)) 33 | } 34 | 35 | return canvas.toBuffer(); 36 | } -------------------------------------------------------------------------------- /src/utility/getMdnSource.js: -------------------------------------------------------------------------------- 1 | const { gunzipSync } = require("zlib"); 2 | const { XMLParser } = require("fast-xml-parser"); 3 | const fetch = require("node-fetch"); 4 | const flexsearch = require("flexsearch"); 5 | const MDN_BASE_URL = "https://developer.mozilla.org/en-US/docs/"; 6 | 7 | let sources = {}; 8 | 9 | module.exports = async () => { 10 | if (sources.lastUpdated && Date.now() - sources.lastUpdated < 43200000) return sources; 11 | 12 | const res = await fetch("https://developer.mozilla.org/sitemaps/en-us/sitemap.xml.gz"); 13 | if (!res.ok) return sources; 14 | 15 | const sitemap = new XMLParser() 16 | .parse(gunzipSync(await res.arrayBuffer()).toString()) 17 | .urlset.url.map((entry) => ({ 18 | loc: entry.loc.slice(MDN_BASE_URL.length), 19 | lastmod: new Date(entry.lastmod).valueOf(), 20 | })); 21 | 22 | const index = new flexsearch.Index(); 23 | sitemap.forEach((entry, idx) => index.add(idx, entry.loc)); 24 | 25 | sources = { index, sitemap, lastUpdated: Date.now() }; 26 | return sources; 27 | } 28 | 29 | -------------------------------------------------------------------------------- /src/utility/pagination.js: -------------------------------------------------------------------------------- 1 | const { MessageActionRow, MessageButton } = require("discord.js"); 2 | 3 | module.exports = async (interaction, pages, time = 60000) => { 4 | if (!interaction || !pages || !(pages?.length > 0) || !(time > 10000)) throw new Error("Invalid parameters"); 5 | 6 | let index = 0, row = new MessageActionRow().addComponents([new MessageButton({ 7 | type: "BUTTON", 8 | customId: "1", 9 | emoji: "◀", 10 | style: "PRIMARY", 11 | disabled: true 12 | }), new MessageButton({ 13 | type: "BUTTON", 14 | customId: "2", 15 | emoji: "▶", 16 | style: "PRIMARY", 17 | disabled: pages.length < 2 18 | }), new MessageButton({ 19 | type: "BUTTON", 20 | customId: "3", 21 | emoji: "❌", 22 | style: "DANGER" 23 | })]); 24 | 25 | let data = { 26 | embeds: [pages[index]], 27 | components: [row], 28 | fetchReply: true 29 | }; 30 | 31 | const msg = interaction.replied ? await interaction.followUp(data) : await interaction.reply(data); 32 | 33 | const col = msg.createMessageComponentCollector({ 34 | filter: i => i.user.id === interaction?.user?.id || interaction?.author?.id, 35 | time 36 | }); 37 | 38 | col.on('collect', (i) => { 39 | if (i.customId === "1") index--; 40 | else if (i.customId === "2") index++; 41 | else return col.stop(); 42 | 43 | row.components = [new MessageButton({ 44 | type: "BUTTON", 45 | customId: "1", 46 | emoji: "◀", 47 | style: "PRIMARY", 48 | disabled: index === 0 49 | }),new MessageButton({ 50 | type: "BUTTON", 51 | customId: "2", 52 | emoji: "▶", 53 | style: "PRIMARY", 54 | disabled: index === pages.length - 1 55 | }),new MessageButton({ 56 | type: "BUTTON", 57 | customId: "3", 58 | emoji: "❌", 59 | style: "DANGER" 60 | })]; 61 | 62 | i.update({ 63 | components: [row], 64 | embeds: [pages[index]] 65 | }) 66 | }); 67 | 68 | col.on('end', () => { 69 | msg.edit({ 70 | components: [] 71 | }) 72 | }) 73 | } -------------------------------------------------------------------------------- /src/utility/pagination2.js: -------------------------------------------------------------------------------- 1 | const { MessageSelectMenu, MessageActionRow } = require("discord.js"); 2 | 3 | module.exports = async (interaction, pages, options, time = 60000, placeholder = "Select a Page") => { 4 | if (!interaction || !Array.isArray(pages) || !Array.isArray(options) || pages.length < 1 || pages.length !== options.length, typeof (time) !== 'number' || typeof (placeholder) !== "string") throw Error('Invalid Parameters'); 5 | 6 | const menu = new MessageSelectMenu({ 7 | customId: 'menu_1', 8 | placeholder, 9 | options: options.map((v, i) => { 10 | v.value = i.toString(); 11 | v.default = i === 0; 12 | 13 | return v; 14 | }) 15 | }); 16 | 17 | let index = 0; 18 | 19 | const data = { 20 | fetchReply: true, 21 | components: [new MessageActionRow().addComponents(menu)], 22 | embeds: [pages[index]] 23 | }, 24 | msg = interaction.replied ? await interaction.followUp(data) : await interaction.reply(data); 25 | 26 | const col = msg.createMessageComponentCollector({ 27 | filter: i => i.user.id === interaction.user.id, 28 | time 29 | }); 30 | 31 | col.on('collect', async (i) => { 32 | index = parseInt(i.values[0]); 33 | 34 | menu.options = menu.options.map(v => { 35 | v.default = v.value === index.toString(); 36 | 37 | return v; 38 | }) 39 | 40 | i.update({ 41 | embeds: [pages[index]], 42 | components: [new MessageActionRow().addComponents(menu)] 43 | }) 44 | }); 45 | 46 | col.on('end', () => { 47 | msg.edit({ 48 | components: [] 49 | }) 50 | }) 51 | } -------------------------------------------------------------------------------- /src/utility/randomId.js: -------------------------------------------------------------------------------- 1 | const STRING = "QWERTYUIOPASDFGHJKLZXCVBNM", 2 | STRING2 = STRING.toLowerCase(), 3 | NUMBER = "1234567890", 4 | chars = STRING + STRING2 + NUMBER; 5 | 6 | module.exports = (length = 12) => { 7 | let pass = ""; 8 | 9 | while (pass.length < length) pass += chars[Math.floor(Math.random() * chars.length)]; 10 | 11 | return pass; 12 | } -------------------------------------------------------------------------------- /src/utility/startTimer.js: -------------------------------------------------------------------------------- 1 | const timers = require('../models/timer'); 2 | 3 | module.exports = (client, timer) => { 4 | const embed = { 5 | title: "⏰ Timer Ended! ⏰", 6 | description: `Your timer for \`${timer.reason || "no reason"}\`, is ended now`, 7 | fields: [ 8 | { name: "Server", value: client.guilds.cache.get(timer.guild)?.name || "Unknown", inline: true }, 9 | { name: "Channel", value: client.channels.cache.get(timer.channel)?.name || "Unknown", inline: true }, 10 | { name: "Setted At", value: new Date(parseInt(timer.createdAt)).toTimeString(), inline: true }, 11 | ], 12 | footer: { 13 | text: "Timer ended at " + new Date(Date.now()).toTimeString() 14 | } 15 | }; 16 | 17 | const timeLeft = Date.now() >= timer?.endAt ? 0 : timer.endAt - Date.now(); 18 | 19 | setTimeout(async () => { 20 | try { 21 | client.users.cache.get(timer.user).send({ embeds: [embed] }) 22 | } catch (e) { 23 | client.channels.cache.get(timer.channel).send({ embeds: [embed], content: `<@${timer.user}>,I was unable to dm you, So I messaged here` }).catch(async() => { 24 | await new Promise(res => setTimeout(res, 2000)); 25 | client.channels.cache.get(timer.channel).send({ embeds: [embed], content: `<@${timer.user}>,I was unable to dm you, So I messaged here` }) 26 | }); 27 | } 28 | 29 | await timers.findOneAndDelete({ id: timer.id, user: timer.user, guild: timer.guild }); 30 | }, timeLeft) 31 | } -------------------------------------------------------------------------------- /tommy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KartikeSingh/tutorial_bot/e2ebdc078d4654c08c507be06eb63a0436d682b1/tommy.ttf --------------------------------------------------------------------------------