├── .gitignore ├── LICENSE ├── README.md ├── config.json ├── package-lock.json ├── package.json └── src ├── Handlers ├── CommandHandler.js ├── ComponentsHandler.js └── EventHandler.js ├── bot.js ├── commands ├── LevelSystem │ └── rank.js ├── bot │ ├── invite.js │ └── socials.js ├── developer │ ├── createUpdate.js │ └── reload.js ├── fun │ └── meme.js ├── moderation │ ├── ban.js │ ├── clear.js │ ├── kick.js │ └── timeout.js ├── music │ └── music.js ├── system │ ├── afk.js │ ├── translate.js │ └── voice.js ├── user │ └── together.js └── utils │ └── setup.js ├── components └── buttons │ └── captcha.js ├── events ├── client │ ├── interactionCreate.js │ └── ready.js ├── distube │ └── DistubeEvents.js ├── guild │ └── voice.js └── message │ ├── afkSystem.js │ ├── levels.js │ └── messageLogUpdate.js └── models ├── AFKSystem.js ├── CaptchaSystem.js ├── Features.js ├── LevelSystem.js ├── ModerationLogs.js └── VoiceSystem.js /.gitignore: -------------------------------------------------------------------------------- 1 | .env 2 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 max 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Perplex-Bot 2 | Perplex is a multipurpose Discord Bot, with features like a captcha system, join-to-create system and much more 3 | - Released: 28.07.2022 4 | - [💌 Invite the bot](https://discord.com/api/oauth2/authorize?client_id=1009480009821474936&permissions=8&scope=bot%20applications.commands) 5 |

6 | 7 | Discord server 8 | 9 |

10 | 11 | ## Installation 12 | 13 | 1. Start cloning the repository and installing the dependencies. 14 | ```bash 15 | git clone https://github.com/gokiimax/Perplex-Bot.git 16 | cd Perplex-Bot 17 | npm install 18 | ``` 19 | 2. Make sure you installed [ffmpeg](https://ffmpeg.org/) (for the music system) 20 | 3. Create a free [MongoDB Database](https://www.mongodb.com/) 21 | 4. Edit your config.json file to your preferences, Create a token on the [Discord Developer Portal](https://discord.com/developers/applications) 22 | ### Config: 23 | ```json 24 | { 25 | "token": "YOUR TOKEN HERE", 26 | "developerGuild": "GUILD ID HERE", 27 | "activityInterval": 5, 28 | "botMainColor": "0x9733f5", 29 | "botErrorColor": "0xdb3535", 30 | "database": "MONGO-DB LINK HERE" 31 | } 32 | ``` 33 | 5. If you finished to configurate, you can start the bot 34 | ```bash 35 | npm run start 36 | ``` 37 | 38 | ## Checklist 39 | - [ ] - Help Command 40 | - [ ] - Fun Commands 41 | - [ ] - More features... 42 | 43 | ## Contributing 44 | You are welcome to contribute by submitting a Pull Request to the repository. 45 | 46 | ## Author 47 | [gokimax](https://github.com/gokiimax) 48 | 49 | ## ☕️ Support & Socials 50 | My Bot is open source and free to use. If you found any of my repos useful and would like to support my projects, feel free to donate to my bitcoin address. 51 | 52 | ### 🔗 bc1qg2v8p3pz6u2h8mnhw47azcjhevf800037l64uj 53 | 54 | [![TikTok Link](https://img.shields.io/badge/TikTok-000000?style=for-the-badge&logo=tiktok&logoColor=white)](https://tiktok.com/@maxii.x6) 55 | [![Twitter Link](https://img.shields.io/badge/Twitter-1DA1F2?style=for-the-badge&logo=twitter&logoColor=white)](https://twitter.com/gokimax_x) 56 | [![Insta Link](https://img.shields.io/badge/Instagram-E4405F?style=for-the-badge&logo=instagram&logoColor=white)](https://instagram.com/maxii.x6) 57 | -------------------------------------------------------------------------------- /config.json: -------------------------------------------------------------------------------- 1 | { 2 | "token": "YOUR TOKEN HERE", 3 | "developerGuild": "GUID ID HERE", 4 | "activityInterval": 5, 5 | "botMainColor": "0xff5454", 6 | "botErrorColor": "0xdb3535", 7 | "database": "MONGO-DB LINK HERE" 8 | } 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Perplex", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/bot.js", 6 | "engines": { 7 | "npm": ">=8.15.0", 8 | "node": ">=16.9.0" 9 | }, 10 | "scripts": { 11 | "start": "node ." 12 | }, 13 | "keywords": [], 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "@discordjs/opus": "^0.8.0", 18 | "@discordjs/rest": "^1.0.1", 19 | "@discordjs/voice": "^0.11.0", 20 | "@distube/soundcloud": "^1.2.1", 21 | "@distube/spotify": "^1.3.2", 22 | "@iamtraction/google-translate": "^1.1.2", 23 | "@miudiscord/together": "^1.0.3", 24 | "ascii-table": "^0.0.9", 25 | "canvacord": "^5.4.2", 26 | "captcha-canvas": "^3.1.0", 27 | "chalk": "^4.1.2", 28 | "discord-api-types": "^0.36.3", 29 | "discord-player": "^5.2.2", 30 | "discord-together": "^1.3.3", 31 | "discord.js": "^14.0.3", 32 | "distube": "^4.0.3", 33 | "dotenv": "^16.0.1", 34 | "ffmpeg-static": "^4.4.1", 35 | "figlet": "^1.5.2", 36 | "libsodium-wrappers": "^0.7.10", 37 | "mongoose": "^6.4.6", 38 | "random-puppy": "^1.1.0", 39 | "yt-search": "^2.10.3", 40 | "ytdl-core": "^4.11.0" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/Handlers/CommandHandler.js: -------------------------------------------------------------------------------- 1 | const { Client } = require('discord.js') 2 | 3 | /** 4 | * @param {Client} client 5 | */ 6 | function loadCommands(client) { 7 | const ascii = require('ascii-table') 8 | const fs = require('fs') 9 | const table = new ascii().setHeading("Commands", "Type", "Status") 10 | 11 | let commandsArray = []; 12 | let developerArray = []; 13 | 14 | const commandsFolder = fs.readdirSync("./src/commands"); 15 | for(const folder of commandsFolder) { 16 | const commandFiles = fs.readdirSync(`./src/commands/${folder}/`) 17 | .filter((file) => file.endsWith(".js")); 18 | 19 | for (const file of commandFiles) { 20 | const commandFile = require(`../commands/${folder}/${file}`) 21 | 22 | client.commands.set(commandFile.data.name, commandFile) 23 | 24 | if(commandFile.developer) developerArray.push(commandFile.data.toJSON()) 25 | else commandsArray.push(commandFile.data.toJSON()); 26 | 27 | table.addRow(file, folder, "✅"); 28 | continue; 29 | } 30 | } 31 | 32 | client.application.commands.set(commandsArray) 33 | 34 | const developerGuild = client.guilds.cache.get(client.config.developerGuild) 35 | 36 | developerGuild.commands.set(developerArray); 37 | 38 | return console.log(table.toString(), "\nLoaded Commands!") 39 | } 40 | 41 | module.exports = { loadCommands } -------------------------------------------------------------------------------- /src/Handlers/ComponentsHandler.js: -------------------------------------------------------------------------------- 1 | const { Client } = require('discord.js') 2 | 3 | /** 4 | * @param { Client } client 5 | */ 6 | function loadComponents(client) { 7 | const ascii = require('ascii-table'); 8 | const fs = require('fs') 9 | const table = new ascii().setHeading("Components", "Type", "Status") 10 | 11 | const componentFolder = fs.readdirSync(`./src/components`); 12 | for (const folder of componentFolder) { 13 | const componentFiles = fs.readdirSync(`./src/components/${folder}`).filter(file => file.endsWith('.js')); 14 | 15 | const { modals, buttons } = client; 16 | switch (folder) { 17 | case "buttons": { 18 | for (const file of componentFiles) { 19 | const button = require(`../components/${folder}/${file}`) 20 | buttons.set(button.data.name, button); 21 | table.addRow(file, "button", "✅"); 22 | } 23 | } 24 | break; 25 | 26 | case "modals": { 27 | for (const file of componentFiles) { 28 | const modal = require(`../components/${folder}/${file}`) 29 | modals.set(modal.data.name, modal) 30 | table.addRow(file, "modal", "✅"); 31 | } 32 | } 33 | break; 34 | 35 | default: 36 | break; 37 | } 38 | continue; 39 | } 40 | 41 | return console.log(table.toString(), "\nLoaded Components!"); 42 | } 43 | 44 | module.exports = { loadComponents } -------------------------------------------------------------------------------- /src/Handlers/EventHandler.js: -------------------------------------------------------------------------------- 1 | function loadEvents(client) { 2 | 3 | const ascii = require('ascii-table') 4 | const fs = require('fs') 5 | const table = new ascii().setHeading("Events", "Status"); 6 | 7 | const folders = fs.readdirSync("./src/events"); 8 | for( const folder of folders) { 9 | const files = fs.readdirSync(`./src/events/${folder}`).filter((file) => file.endsWith(".js")); 10 | 11 | for (const file of files) { 12 | const event = require(`../events/${folder}/${file}`) 13 | 14 | if (event.rest) { 15 | if (event.once) { 16 | client.rest.once(event.name, (...args) => event.execute(...args, client)); 17 | } else { 18 | client.rest.on(event.name, (...args) => event.execute(...args, client)); 19 | } 20 | } else { 21 | if (event.once) { 22 | client.once(event.name, (...args) => event.execute(...args, client)); 23 | } else { 24 | client.on(event.name, (...args) => event.execute(...args, client)); 25 | } 26 | } 27 | table.addRow(file, "✅") 28 | continue; 29 | } 30 | } 31 | return console.log(table.toString(), "\nLoaded Events.") 32 | } 33 | 34 | module.exports = { loadEvents }; 35 | -------------------------------------------------------------------------------- /src/bot.js: -------------------------------------------------------------------------------- 1 | const { Client, Collection, GatewayIntentBits, Partials, EmbedBuilder } = require("discord.js"); 2 | const { Guilds, GuildMembers, GuildMessages, GuildVoiceStates, DirectMessages, GuildMessageReactions, GuildEmojisAndStickers, GuildWebhooks, GuildIntegrations, MessageContent } = GatewayIntentBits; 3 | const { User, Message, GuildMember, ThreadMember, GuildScheduledEvent, Reaction } = Partials; 4 | 5 | const client = new Client({ intents: [Guilds, GuildMembers, GuildMessages, GuildVoiceStates, DirectMessages, GuildMessageReactions, GuildEmojisAndStickers, GuildWebhooks, GuildIntegrations, MessageContent], partials: [User, Message, GuildMember, ThreadMember, GuildScheduledEvent, Reaction] }); 6 | 7 | client.config = require('../config.json') 8 | const { botMainColor, botErrorColor } = require('../config.json') 9 | 10 | /* Music System */ 11 | const { DisTube } = require('distube') 12 | const { SpotifyPlugin } = require('@distube/spotify') 13 | const { SoundCloudPlugin } = require('@distube/soundcloud') 14 | 15 | client.distube = new DisTube(client, { 16 | leaveOnEmpty: true, 17 | nsfw: true, 18 | emitNewSongOnly: true, 19 | leaveOnFinish: true, 20 | plugins: [ new SpotifyPlugin(), new SoundCloudPlugin() ] 21 | }) 22 | module.exports = client; 23 | 24 | client.voiceGenerator = new Collection(); 25 | client.commands = new Collection(); 26 | client.modals = new Collection(); 27 | client.buttons = new Collection(); 28 | 29 | const { loadEvents } = require('./Handlers/EventHandler') 30 | const { loadCommands } = require('./Handlers/CommandHandler') 31 | const { loadComponents } = require('./Handlers/ComponentsHandler') 32 | 33 | /* Embed Colors */ 34 | client.mainColor = parseInt(botMainColor); 35 | client.errorColor = parseInt(botErrorColor); 36 | 37 | client.hexMainColor = botMainColor.replace('0x', "#"); 38 | client.hexErrorColor = botErrorColor.replace('0x', "#"); 39 | 40 | /* Mod Logs */ 41 | const modlogsDB = require('./models/ModerationLogs'); 42 | client.modlogs = async function({ Member, Action, Color, Reason }, interaction) { 43 | const data = await modlogsDB.findOne({ GuildID: interaction.guild.id }) 44 | if(!data) return; 45 | 46 | const channel = interaction.guild.channels.cache.get(data.ChannelID); 47 | const logsEmbed = new EmbedBuilder() 48 | .setColor(Color) 49 | .setAuthor({name: Member.user.tag, iconURL: Member.user.displayAvatarURL()}) 50 | .setTitle("📕 Moderation Logs") 51 | .addFields([ 52 | {name: "Reason", value: `${Reason || "No reason given"}`, inline: false}, 53 | {name: "Member", value: `<@${Member.id}>`, inline: false}]) 54 | .setFooter({ text: `Action: ${Action}`}) 55 | 56 | channel.send({embeds: [logsEmbed]}) 57 | } 58 | 59 | client.login(client.config.token).then(() => { 60 | loadEvents(client); 61 | loadCommands(client); 62 | loadComponents(client); 63 | }) 64 | -------------------------------------------------------------------------------- /src/commands/LevelSystem/rank.js: -------------------------------------------------------------------------------- 1 | const { Client, SlashCommandBooleanOption, SlashCommandBuilder, ChatInputCommandInteraction, AttachmentBuilder } = require('discord.js') 2 | const Canvacord = require('canvacord') 3 | const { calculateXP } = require('../../events/message/levels') 4 | 5 | const featuresDB = require('../../models/Features') 6 | const levelsDB = require('../../models/LevelSystem') 7 | 8 | module.exports = { 9 | data: new SlashCommandBuilder() 10 | .setName("rank") 11 | .setDescription("See your rank or the rank from other people! (The level System need to be enabled)") 12 | .addUserOption( 13 | option => 14 | option.setName("member") 15 | .setDescription("Member you want to see the rank") 16 | ), 17 | /** 18 | * 19 | * @param {ChatInputCommandInteraction} interaction 20 | * @param {Client} client 21 | */ 22 | async execute(interaction, client) { 23 | const { options, guild, member } = interaction; 24 | 25 | const levelSystemCheck = await featuresDB.findOne({GuildID: guild.id}) 26 | if(levelSystemCheck) { 27 | const { LevelSystem } = levelSystemCheck 28 | if(!LevelSystem.Enabled) return interaction.reply({content: `I'm sorry to say that to you, but <@${guild.ownerId}> didn't enabled the Level System 🙁`, ephemeral: true}) 29 | 30 | const rankcard = new Canvacord.Rank() 31 | const user = options.getUser("member") 32 | const color = client.hexMainColor 33 | 34 | if (user) { 35 | let levelResult = await levelsDB.findOne({GuildID: guild.id, UserID: user.id}); 36 | 37 | if(levelResult && levelResult.xp) { 38 | rankcard.setAvatar(user.displayAvatarURL({extension: 'png'})) 39 | .setCurrentXP(parseInt(`${levelResult.xp || "0"}`)) 40 | .setLevel(parseInt(`${levelResult.level || "1"}`)) 41 | .setProgressBar(color) 42 | .setRequiredXP(calculateXP(levelResult.level)) 43 | .setOverlay("#000000", 1, false) 44 | .setUsername(`${user.username}`) 45 | .setDiscriminator(`${user.discriminator}`) 46 | .setBackground('IMAGE', LevelSystem.Background || "https://cdn.discordapp.com/attachments/984457148538945546/1003609214222094346/test.png") 47 | .renderEmojis(true) 48 | .setLevelColor(color) 49 | } else { 50 | return interaction.reply({content: `${user} does not have any XP 🙁`, ephemeral: true}) 51 | } 52 | } else { 53 | let levelResult = await levelsDB.findOne({GuildID: guild.id, UserID: member.user.id}); 54 | 55 | if(levelResult && levelResult.xp) { 56 | rankcard.setAvatar(member.user.displayAvatarURL({extension: 'png'})) 57 | .setCurrentXP(parseInt(`${levelResult.xp}`) || 0) 58 | .setLevel(parseInt(`${levelResult.level}` || 1)) 59 | .setRequiredXP(calculateXP(levelResult.level)) 60 | .setProgressBar(color) 61 | .setOverlay("#000000", 1, false) 62 | .setUsername(`${member.user.username}`) 63 | .setDiscriminator(`${member.user.discriminator}`) 64 | .setBackground('IMAGE', LevelSystem.Background || "https://cdn.discordapp.com/attachments/984457148538945546/1003609214222094346/test.png") 65 | .renderEmojis(true) 66 | .setLevelColor(color) 67 | } else { 68 | return interaction.reply({content: `You do not have any XP 🙁`, ephemeral: true}) 69 | } 70 | } 71 | 72 | const img = rankcard.build() 73 | const atta = new AttachmentBuilder(await img).setName("rank.png") 74 | interaction.reply({files: [atta]}); 75 | } else { 76 | return interaction.reply({content: `I'm sorry to say that to you, but <@${guild.ownerId}> didn't enabled the Level System 🙁`, ephemeral: true}) 77 | } 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/commands/bot/invite.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders') 2 | const { Client, SlashCommandBuilder, ChatInputCommandInteraction } = require('discord.js') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName("invite") 7 | .setDescription("Invite me to your own server!"), 8 | /** 9 | * @param {ChatInputCommandInteraction} interaction 10 | * @param {Client} client 11 | */ 12 | async execute(interaction, client) { 13 | const link = `https://discord.com/api/oauth2/authorize?client_id=${client.user.id}&permissions=8&scope=bot%20applications.commands` 14 | const Response = new EmbedBuilder() 15 | .setColor(client.mainColor) 16 | .setTitle("💌 Invite Me") 17 | .setFooter({text: client.user.tag, iconURL: client.user.displayAvatarURL()}) 18 | .setDescription(`[Invite Me](${link})`) 19 | 20 | await interaction.reply({embeds: [Response]}) 21 | 22 | } 23 | } -------------------------------------------------------------------------------- /src/commands/bot/socials.js: -------------------------------------------------------------------------------- 1 | const { Client, SlashCommandBuilder, EmbedBuilder, ChatInputCommandInteraction } = require('discord.js') 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName("socials") 6 | .setDescription("View the Socials of my Creator!"), 7 | /** 8 | * @param {ChatInputCommandInteraction} interaction 9 | * @param {Client} client 10 | */ 11 | async execute(interaction, client) { 12 | 13 | const Response = new EmbedBuilder() 14 | .setTitle("♦️ Socials") 15 | .setDescription( 16 | `💻 │ [Github](https://github.com/gokiimax)\n📹 │ [Youtube](https://www.youtube.com/channel/UCjqJ3HJkiyu12fzFKIGEovQ)\n📱 │ [Instagram](https://www.instagram.com/maxii.x6)\n🐦 │ [Twitter](https://www.twitter.com/gokimax_x)`) 17 | .setTimestamp(Date.now()) 18 | .setColor(client.mainColor) 19 | .setThumbnail('https://github.com/gokiimax.png') 20 | 21 | interaction.reply({embeds: [Response]}) 22 | 23 | } 24 | } -------------------------------------------------------------------------------- /src/commands/developer/createUpdate.js: -------------------------------------------------------------------------------- 1 | const { Client, SlashCommandBuilder, EmbedBuilder, ChatInputCommandInteraction } = require('discord.js') 2 | const {} = require('../../../config.json') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName("setchangelog") 7 | .setDescription("Create an update message for your bot users!") 8 | .addStringOption( 9 | option => 10 | option.setName("changelog") 11 | .setDescription("Create a changelog for your client") 12 | .setRequired(true)), 13 | /** 14 | * 15 | * @param {ChatInputCommandInteraction} interaction 16 | * @param {Client} client 17 | */ 18 | async execute(interaction, client) { 19 | const { options } = interaction; 20 | 21 | client.guilds.cache.each(guild => { 22 | 23 | const guildOwner = guild.fetchOwner({force: true}); 24 | const UpdateEmbed = new EmbedBuilder() 25 | .setTitle("🤖 Perplex System") 26 | .setURL("https://discord.gg/yVWygKS3Xn") 27 | .setDescription(`There is a new Update for this Bot in ***${guild.name}***!\n**Changelog:**\n${options.getString("changelog")}`) 28 | .setFooter({text: client.user.tag, iconURL: client.user.displayAvatarURL()}) 29 | .setColor(client.mainColor) 30 | .setThumbnail(client.user.displayAvatarURL()) 31 | 32 | guildOwner.then((member) => { 33 | member.send({embeds: [UpdateEmbed]}).catch(() => interaction.channel.send({content: `❌ Cannot send message to ${member.user.tag}!`})) 34 | }) 35 | }) 36 | 37 | interaction.reply({content: "✅ Update sent successfully", ephemeral: true}) 38 | }, 39 | developer: true 40 | } -------------------------------------------------------------------------------- /src/commands/developer/reload.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, SlashCommandBuilder, PermissionFlagsBits, ChatInputCommandInteraction } = require('discord.js') 3 | const { loadCommands } = require('../../Handlers/CommandHandler') 4 | const { loadEvents } = require('../../Handlers/EventHandler') 5 | 6 | module.exports = { 7 | data: new SlashCommandBuilder() 8 | .setName("reload") 9 | .setDescription("Reload your events/command!") 10 | .setDefaultMemberPermissions(PermissionFlagsBits.Administrator) 11 | .addSubcommand( 12 | command => 13 | command.setName("events") 14 | .setDescription("Reload your events!")) 15 | .addSubcommand( 16 | command => 17 | command.setName("commands") 18 | .setDescription("Reload your commands!")), 19 | developer: true, 20 | /** 21 | * @param { ChatInputCommandInteraction } interaction 22 | */ 23 | async execute(interaction, client) { 24 | 25 | const sub = interaction.options.getSubcommand(); 26 | const Response = new EmbedBuilder() 27 | .setTitle("💻 Developer") 28 | .setColor(client.mainColor) 29 | 30 | switch (sub) { 31 | case "commands": { 32 | loadCommands(client); 33 | interaction.reply({embeds: [Response.setDescription("✅ Reloaded Commands!")]}) 34 | } 35 | break; 36 | 37 | case "events": { 38 | loadEvents(client); 39 | interaction.reply({embeds: [Response.setDescription("✅ Reloaded Events!")]}) 40 | } 41 | break; 42 | } 43 | 44 | }, 45 | } -------------------------------------------------------------------------------- /src/commands/fun/meme.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, ChatInputCommandInteraction, SlashCommandBuilder } = require('discord.js') 3 | const randomPuppy = require('random-puppy') 4 | 5 | module.exports = { 6 | data: new SlashCommandBuilder() 7 | .setName("meme") 8 | .setDescription("Sends an epic meme"), 9 | /** 10 | * @param {ChatInputCommandInteraction} interaction 11 | * @param {Client} client 12 | */ 13 | async execute(interaction, client) { 14 | const subReddits = ["dankmeme", "meme", "me_irl"]; 15 | const random = subReddits[Math.floor(Math.random() * subReddits.length)]; 16 | 17 | const img = await randomPuppy(random); 18 | const embed = new EmbedBuilder() 19 | .setColor(client.mainColor) 20 | .setDescription(`From [${random}](https://reddit.com/r/${random})`) 21 | .setTitle("🎭 Meme") 22 | .setImage(img) 23 | 24 | interaction.reply({embeds: [embed]}) 25 | } 26 | } -------------------------------------------------------------------------------- /src/commands/moderation/ban.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, SlashCommandBuilder, CommandInteraction, PermissionFlagsBits } = require('discord.js') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName('ban') 7 | .setDescription('Ban a member from the server!') 8 | .addUserOption( 9 | option => 10 | option.setName("target") 11 | .setDescription("Select a target to ban.") 12 | .setRequired(true)) 13 | .addStringOption( 14 | option => 15 | option.setName("reason") 16 | .setDescription("Reason for the ban") 17 | .setRequired(false)) 18 | 19 | .setDMPermission(false) 20 | .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers), 21 | /** 22 | * @param {CommandInteraction} interaction 23 | * @param {Client} client 24 | */ 25 | async execute(interaction, client) { 26 | const { options } = interaction; 27 | 28 | const Target = options.getMember("target") 29 | const Reason = options.getString("reason") 30 | 31 | const Response = new EmbedBuilder() 32 | .setColor(client.mainColor) 33 | .setTimestamp(Date.now()) 34 | 35 | if(Target.bannable) { 36 | client.modlogs({ 37 | Member: Target, 38 | Action: "Ban", 39 | Color: 0xf5425a, 40 | Reason: Reason 41 | }, interaction) 42 | 43 | if (Reason) { 44 | await interaction.guild.bans.create(Target, {reason: Reason}) 45 | Response.setDescription(`<@${interaction.member.id}> banned User <@${Target.id}>`) 46 | Response.addFields([ 47 | { 48 | name: "Reason:", 49 | value: Reason, 50 | inline: false 51 | } 52 | ]) 53 | } else { 54 | await interaction.guild.bans.create(Target) 55 | Response.setDescription(`<@${interaction.member.id}> banned User <@${Target.id}>`) 56 | } 57 | } else { 58 | Response.setDescription(`❌ Could not ban User <@${Target.id}> because of missing Permissions!`).setColor(client.errorColor) 59 | } 60 | 61 | await interaction.reply({embeds: [Response]}) 62 | } 63 | } -------------------------------------------------------------------------------- /src/commands/moderation/clear.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, SlashCommandBuilder, CommandInteraction, PermissionFlagsBits, MessageContextMenuCommandInteraction, CommandInteractionOptionResolver } = require('discord.js') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName('clear') 7 | .setDescription('Clear a amount of messages in the channel') 8 | .addNumberOption( 9 | option => 10 | option.setName("amount") 11 | .setDescription("The amount of messages you wanna delete!") 12 | .setRequired(true) 13 | .setMaxValue(100) 14 | ) 15 | .addUserOption( 16 | option => 17 | option.setName("target") 18 | .setDescription("Select a target to clear their messages.") 19 | .setRequired(false)) 20 | 21 | .setDMPermission(false) 22 | .setDefaultMemberPermissions(PermissionFlagsBits.ManageMessages), 23 | /** 24 | * @param {CommandInteraction} interaction 25 | * @param {Client} client 26 | */ 27 | async execute(interaction, client) { 28 | const { channel, options } = interaction; 29 | 30 | const Amount = options.getNumber("amount") 31 | const Target = options.getUser("target"); 32 | 33 | const Messages = await channel.messages.fetch(); 34 | 35 | const Response = new EmbedBuilder() 36 | .setColor(client.mainColor) 37 | 38 | if (Target) { 39 | let i = 0; 40 | const filtered = []; 41 | (await Messages).filter((m) => { 42 | if(m.author.id === Target.id && Amount > i) { 43 | filtered.push(m); 44 | i++; 45 | } 46 | }) 47 | 48 | await channel.bulkDelete(filtered, true).then(async messages => { 49 | Response.setDescription(`🧹 Cleared ${messages.size} from ${Target}.`) 50 | await interaction.reply({embeds: [Response]}) 51 | }) 52 | } else { 53 | await channel.bulkDelete(Amount, true).then(async messages => { 54 | Response.setDescription(`🧹 Cleared ${messages.size} from this channel.`) 55 | await interaction.reply({embeds: [Response]}) 56 | }) 57 | } 58 | } 59 | } -------------------------------------------------------------------------------- /src/commands/moderation/kick.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, SlashCommandBuilder, CommandInteraction, PermissionFlagsBits } = require('discord.js') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName('kick') 7 | .setDescription('Kick a member from the server!') 8 | .addUserOption( 9 | option => 10 | option.setName("target") 11 | .setDescription("Select a target to kick.") 12 | .setRequired(true)) 13 | .addStringOption( 14 | option => 15 | option.setName("reason") 16 | .setDescription("Reason for the kick") 17 | .setRequired(false)) 18 | 19 | .setDMPermission(false) 20 | .setDefaultMemberPermissions(PermissionFlagsBits.KickMembers), 21 | /** 22 | * @param {CommandInteraction} interaction 23 | * @param {Client} client 24 | */ 25 | async execute(interaction, client) { 26 | const { options } = interaction; 27 | 28 | const Target = options.getMember("target") 29 | const Reason = options.getString("reason") 30 | 31 | const Response = new EmbedBuilder() 32 | .setColor(client.mainColor) 33 | .setTimestamp(Date.now()) 34 | 35 | if(Target.kickable) { 36 | client.modlogs({ 37 | Member: Target, 38 | Action: "Kick", 39 | Color: 0xfff763, 40 | Reason: Reason 41 | }, interaction) 42 | 43 | if (Reason) { 44 | Target.kick(Reason) 45 | Response.setDescription(`<@${interaction.member.id}> kicked User <@${Target.id}>`) 46 | Response.addFields([ 47 | { 48 | name: "Reason:", 49 | value: Reason, 50 | inline: false 51 | } 52 | ]) 53 | } else { 54 | Target.kick() 55 | Response.setDescription(`<@${interaction.member.id}> kicked User <@${Target.id}>`) 56 | } 57 | } else { 58 | Response.setDescription(`❌ Could not kick User <@${Target.id}> because of missing Permissions!`).setColor(client.errorColor) 59 | } 60 | 61 | await interaction.reply({embeds: [Response]}) 62 | } 63 | } -------------------------------------------------------------------------------- /src/commands/moderation/timeout.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, SlashCommandBuilder, CommandInteraction, PermissionFlagsBits } = require('discord.js') 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName('timeout') 7 | .setDescription('Timout a member from the server!') 8 | .addUserOption( 9 | option => 10 | option.setName("user") 11 | .setDescription("The user to timout.") 12 | .setRequired(true)) 13 | .addNumberOption( 14 | option => 15 | option.setName("duration") 16 | .setDescription("The duration of the timout.") 17 | .setRequired(true) 18 | .addChoices( 19 | { name: "60 seconds", value: 60*1000 }, 20 | { name: "5 minutes", value: 5*60*1000 }, 21 | { name: "10 minutes", value: 10*60*1000 }, 22 | { name: "30 minutes", value: 30*60*1000 }, 23 | { name: "1 hour", value: 60*60*1000 }, 24 | { name: "1 day", value: 24*60*60*1000 }, 25 | { name: "1 week", value: 7*24*60*60*1000 } 26 | )) 27 | .addStringOption( 28 | option => 29 | option.setName("reason") 30 | .setDescription("Reason for the timeout") 31 | .setRequired(false)) 32 | 33 | .setDMPermission(false) 34 | .setDefaultMemberPermissions(PermissionFlagsBits.ModerateMembers), 35 | /** 36 | * @param {CommandInteraction} interaction 37 | * @param {Client} client 38 | */ 39 | async execute(interaction, client) { 40 | const { options } = interaction 41 | 42 | let member = options.getMember("user") 43 | let duration = options.getNumber("duration") 44 | let reason = options.getString("reason") || "No reason given" 45 | 46 | const Response = new EmbedBuilder() 47 | .setColor(client.mainColor) 48 | 49 | if (!member) return interaction.reply({embeds: [Response.setDescription("❌ Invalid Member given").setColor(client.errorColor)], ephemeral: true}) 50 | 51 | try { 52 | await member.timeout(duration, reason) 53 | Response.setDescription(`🚫 <@${member.user.id}> has been timed out!`) 54 | .addFields([ 55 | {name: "Reason:", value: reason, inline: false}, 56 | ]) 57 | 58 | client.modlogs({ 59 | Member: member, 60 | Action: "Timeout", 61 | Color: 0xfff763, 62 | Reason: reason 63 | }, interaction) 64 | return interaction.reply({embeds: [Response]}) 65 | } catch (err) { 66 | return console.error(err) 67 | } 68 | 69 | } 70 | } -------------------------------------------------------------------------------- /src/commands/music/music.js: -------------------------------------------------------------------------------- 1 | const { Client, ChatInputCommandInteraction, EmbedBuilder, SlashCommandBuilder, Colors, VoiceChannel, ChannelType } = require('discord.js'); 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName("music") 6 | .setDescription("Complete music system") 7 | .addSubcommand( 8 | command => 9 | command.setName("play") 10 | .setDescription("Play a song") 11 | .addStringOption( 12 | option => 13 | option.setName("query") 14 | .setDescription("Provide a name or a url for the song") 15 | .setRequired(true) 16 | ) 17 | ) 18 | .addSubcommand( 19 | command => 20 | command.setName("volume") 21 | .setDescription("Alter the volume.") 22 | .addNumberOption( 23 | option => 24 | option.setName("percent") 25 | .setDescription("10 = 10%") 26 | .setRequired(true) 27 | ) 28 | ) 29 | .addSubcommand( 30 | command => 31 | command.setName("settings") 32 | .setDescription("Select an option") 33 | .addStringOption( 34 | option => 35 | option.setName("options") 36 | .setDescription("Select an option") 37 | .setRequired(true) 38 | .addChoices( 39 | { name: "🗒️ Queue", value: "queue" }, 40 | { name: "⏩ Skip", value: "skip" }, 41 | { name: "⏸️ Pause", value: "pause" }, 42 | { name: "▶️ Resume", value: "resume" }, 43 | { name: "⏹️ Stop", value: "stop" }, 44 | { name: "🔀 Shuffle", value: "shuffle" }, 45 | ) 46 | ) 47 | ), 48 | /** 49 | * 50 | * @param {ChatInputCommandInteraction} interaction 51 | * @param {Client} client 52 | */ 53 | async execute(interaction, client) { 54 | const { options, member, guild, channel } = interaction; 55 | const voiceChannel = member.voice.channel; 56 | 57 | const Response = new EmbedBuilder() 58 | .setColor(client.mainColor) 59 | .setTitle("🎶 Musik") 60 | 61 | if(!voiceChannel) return interaction.reply({embeds: [Response.setDescription("❌ You must be in a voice channel to be able to use this command.")], ephemeral: true}) 62 | const test = guild.channels.cache.filter(chnl => (chnl.type == ChannelType.GuildVoice)).find(channel => (channel.members.has(client.user.id))) 63 | if(test && voiceChannel.id !== test.id) return interaction.reply({embeds: [Response.setDescription(`❌ I'm already playing in <#${test.id}>`)], ephemeral: true}) 64 | 65 | try { 66 | 67 | switch(options.getSubcommand()) { 68 | case "play": { 69 | client.distube.play( voiceChannel, options.getString("query"), { 70 | textChannel: channel, member: member 71 | }) 72 | 73 | return interaction.reply({content: `🎼 Request recieved`, ephemeral: true}) 74 | } 75 | 76 | case "volume": { 77 | const Volume = options.getNumber("percent") 78 | if(Volume > 100 || Volume < 1) return interaction.reply({embeds: [Response.setDescription("You have to specify a number between 1 and 100")], ephemeral: true}); 79 | 80 | client.distube.setVolume(voiceChannel, Volume) 81 | return interaction.reply({content: `🔊 Volume has been set to \`${Volume}%\``}) 82 | } 83 | 84 | case "settings": { 85 | 86 | const queue = await client.distube.getQueue(voiceChannel); 87 | if(!queue) return interaction.reply({content: '🛑 There is now queue', ephemeral: true}) 88 | 89 | switch(options.getString("options")) { 90 | case "skip": { 91 | await queue.skip(voiceChannel) 92 | return interaction.reply({content: '⏩ Song has been skipped.'}) 93 | } 94 | 95 | case "shuffle": { 96 | await queue.shuffle() 97 | return interaction.reply({content: '🔀 Shuffled songs in the queue.'}) 98 | } 99 | 100 | case "stop": { 101 | await queue.stop(voiceChannel) 102 | return interaction.reply({content: '⏹️ Music has been stopped.'}) 103 | } 104 | 105 | case "pause": { 106 | await queue.pause(voiceChannel) 107 | return interaction.reply({content: '⏸️ Song has been paused.'}) 108 | } 109 | 110 | case "resume": { 111 | await queue.resume(voiceChannel) 112 | return interaction.reply({content: '▶️ Song has been resumed.'}) 113 | } 114 | 115 | case "queue": { 116 | return interaction.reply({embeds: [ 117 | Response.setDescription(`${queue.songs.map( 118 | (song, id) => `\n**${id + 1}** | ${song.name} - \`${song.formattedDuration}\``)}` 119 | )]}); 120 | } 121 | } 122 | 123 | return; 124 | } 125 | } 126 | 127 | } catch (error) { 128 | const errorEmbed = new EmbedBuilder() 129 | .setColor(Colors.Red) 130 | .setDescription(`🛑 Alert: ${error}`) 131 | return interaction.reply({embeds: [errorEmbed], ephemeral: true}) 132 | } 133 | 134 | } 135 | } -------------------------------------------------------------------------------- /src/commands/system/afk.js: -------------------------------------------------------------------------------- 1 | const { CommandInteraction, Client, EmbedBuilder, SlashCommandBuilder } = require('discord.js') 2 | const DB = require("../../models/AFKSystem") 3 | 4 | module.exports = { 5 | data: new SlashCommandBuilder() 6 | .setName("afk") 7 | .setDescription("Set yourself away from keyboard!") 8 | .addSubcommand( 9 | command => 10 | command.setName("set") 11 | .setDescription("Set your AFK status!") 12 | .addStringOption( 13 | option => 14 | option.setName("status") 15 | .setDescription("Set your status message!") 16 | .setRequired(true) 17 | ) 18 | ) 19 | .addSubcommand( 20 | command => 21 | command.setName("return") 22 | .setDescription("Return from being afk!")), 23 | 24 | /** 25 | * @param {Client} client 26 | * @param {CommandInteraction} interaction 27 | */ 28 | async execute(interaction, client) { 29 | const { guild, user, createdTimestamp, options } = interaction; 30 | 31 | const Response = new EmbedBuilder() 32 | .setTitle("💤 AFK System") 33 | .setAuthor({name: user.tag, iconURL: user.displayAvatarURL()}) 34 | 35 | const afkStatus = options.getString("status") 36 | 37 | try { 38 | 39 | switch (options.getSubcommand()) { 40 | case "set": { 41 | await DB.findOneAndUpdate( 42 | {GuildID: guild.id, UserID: user.id}, 43 | {Status: afkStatus, Time: parseInt(createdTimestamp / 1000)}, 44 | {new: true, upsert: true} 45 | ) 46 | 47 | Response.setColor(client.mainColor).setDescription(`✅ Your AFK status has been updated to ${afkStatus}.`); 48 | 49 | return interaction.reply({embeds: [Response], ephemeral: true}) 50 | } 51 | break; 52 | 53 | case "return": { 54 | await DB.deleteOne({ GuildID: guild.id, UserID: user.id }); 55 | 56 | Response.setColor(client.mainColor).setDescription(`❌ Your AFK status has been removed.`); 57 | 58 | return interaction.reply({embeds: [Response], ephemeral: true}) 59 | } 60 | break; 61 | } 62 | 63 | } catch (err) { 64 | return console.error(err) 65 | } 66 | } 67 | } -------------------------------------------------------------------------------- /src/commands/system/translate.js: -------------------------------------------------------------------------------- 1 | const { Client, SlashCommandBuilder, ChatInputCommandInteraction } = require('discord.js') 2 | const translate = require("@iamtraction/google-translate") 3 | const { EmbedBuilder } = require('@discordjs/builders') 4 | 5 | module.exports = { 6 | data: new SlashCommandBuilder() 7 | .setName("translate") 8 | .setDescription("Translate any text to a specific language!") 9 | .addStringOption( 10 | option => 11 | option.setName("text") 12 | .setDescription("The text you wanna translate!") 13 | .setRequired(true)) 14 | .addStringOption( 15 | option => 16 | option.setName("language") 17 | .setDescription("The language you wanna translate to!") 18 | .addChoices( 19 | { name: "English", value: "english"}, 20 | { name: "German", value: "german"}, 21 | { name: "French", value: "french"}, 22 | { name: "Russian", value: "russian"}, 23 | ).setRequired(true)), 24 | /** 25 | * 26 | * @param {ChatInputCommandInteraction} interaction 27 | * @param {Client} client 28 | */ 29 | async execute(interaction, client) { 30 | 31 | const { options } = interaction 32 | const text = options.getString("text") 33 | const language = options.getString("language") 34 | 35 | switch (language) { 36 | case "english": { 37 | const translated = await translate(text, { to: 'en' }) 38 | send_translated(text, translated.text, interaction, client) 39 | } 40 | break; 41 | 42 | case "german": { 43 | const translated = await translate(text, { to: 'de' }) 44 | send_translated(text, translated.text, interaction, client) 45 | } 46 | break; 47 | 48 | case "french": { 49 | const translated = await translate(text, { to: 'fr' }) 50 | send_translated(text, translated.text, interaction, client) 51 | } 52 | break; 53 | 54 | case "spanish": { 55 | const translated = await translate(text, { to: 'sp' }) 56 | send_translated(text, translated.text, interaction, client) 57 | } 58 | 59 | case "russian": { 60 | const translated = await translate(text, { to: 'ru' }) 61 | send_translated(text, translated.text, interaction, client) 62 | } 63 | break; 64 | } 65 | 66 | } 67 | } 68 | 69 | function send_translated(text, translated, interaction, client) { 70 | const Response = new EmbedBuilder() 71 | .setColor(client.mainColor) 72 | .setTitle("🌍 Translator") 73 | .addFields( 74 | { name: "Message:", value: text, inline: true}, 75 | { name: "Translated:", value: translated, inline: true} 76 | ).setFooter({text: `Requested by ${interaction.member.user.tag}`, iconURL: interaction.member.user.displayAvatarURL()}) 77 | 78 | interaction.channel.send({ embeds: [Response] }) 79 | interaction.reply({content: "Successfully translated message!", ephemeral: true}) 80 | } -------------------------------------------------------------------------------- /src/commands/system/voice.js: -------------------------------------------------------------------------------- 1 | const { Client, EmbedBuilder, SlashCommandBuilder, CommandInteraction } = require('discord.js') 2 | 3 | module.exports = { 4 | data: new SlashCommandBuilder() 5 | .setName('voice') 6 | .setDescription('Control your own channel') 7 | .addSubcommand(subcommand => 8 | subcommand 9 | .setName("invite") 10 | .setDescription("Invite a friend to your channel.") 11 | .addUserOption(option => 12 | option.setName("member").setDescription("Select a member you wanna add.").setRequired(true)) 13 | ) 14 | .addSubcommand(subcommand => 15 | subcommand 16 | .setName("disallow") 17 | .setDescription("Remove someone's access to the channel.") 18 | .addUserOption(option => 19 | option.setName("member") 20 | .setDescription("Select a member you wanna remove the access.") 21 | .setRequired(true)) 22 | ) 23 | .addSubcommand(subcommand => 24 | subcommand 25 | .setName("name") 26 | .setDescription("Change the name of your channel") 27 | .addStringOption(option => 28 | option.setName("text") 29 | .setDescription("Provide the name.") 30 | .setRequired(true)) 31 | ) 32 | .addSubcommand(subcommand => 33 | subcommand 34 | .setName("public") 35 | .setDescription("Make your channel public to everyone.") 36 | .addStringOption(option => 37 | option.setName("turn") 38 | .setDescription("Turn on or off.") 39 | .setRequired(true) 40 | .addChoices( 41 | {name: "on", value: "on"}, 42 | {name: "off", value: "off"} 43 | )) 44 | ) 45 | 46 | .setDMPermission(false), 47 | /** 48 | * @param {CommandInteraction} interaction 49 | * @param {Client} client 50 | */ 51 | async execute(interaction, client) { 52 | const { options, member, guild } = interaction; 53 | 54 | const subCommand = options.getSubcommand(); 55 | const voiceChannel = member.voice.channel; 56 | const Embed = new EmbedBuilder().setTitle("🔊 Voice System").setColor(client.mainColor).setTimestamp(Date.now()); 57 | const ownedChannel = client.voiceGenerator.get(member.id); 58 | 59 | if(!voiceChannel) 60 | return interaction.reply({embeds: [Embed.setDescription("🔇 You are currently not in a voice channel.").setColor(client.errorColor)], ephemeral: true}); 61 | 62 | if(!ownedChannel || voiceChannel.id !== ownedChannel) 63 | return interaction.reply({embeds: [Embed.setDescription("❌ You do not own this channel!").setColor(client.errorColor)], ephemeral: true}) 64 | 65 | switch(subCommand) { 66 | case "name": { 67 | const newName = options.getString("text"); 68 | if(newName.length > 22 || newName.length < 1) 69 | return interaction.reply({embeds: [Embed.setDescription("❌ Name cannot exceed the 22 character limit").setColor(client.errorColor)], ephemeral: true}) 70 | 71 | voiceChannel.edit({name: newName}); 72 | interaction.reply({embeds: [Embed.setDescription(`📝 Channel name has been set to ${newName}!`)], ephemeral: true}) 73 | } 74 | break; 75 | 76 | case "invite": { 77 | const targetMember = options.getMember('member'); 78 | voiceChannel.permissionOverwrites.edit(targetMember, {Connect: true}); 79 | const sendEmbed = new EmbedBuilder().setTitle("🔊 Voice System").setColor(client.mainColor).setDescription(`👋 <@${member.id}> has invited you to <#${voiceChannel.id}>`) 80 | 81 | targetMember.send({embeds: [sendEmbed]}).catch(() => {}) 82 | interaction.reply({embeds: [Embed.setDescription(`📨 ${targetMember} has been successfully invited!`)], ephemeral: true}) 83 | } 84 | break; 85 | 86 | case "disallow": { 87 | const targetMember = options.getMember('member'); 88 | voiceChannel.permissionOverwrites.edit(targetMember, {Connect: false}) 89 | 90 | if(targetMember.voice.channel && targetMember.voice.channel.id == voiceChannel.id) targetMember.voice.setChannel(null); 91 | interaction.reply({embeds: [Embed.setDescription(`💢 ${targetMember} has been removed from your channel!`)], ephemeral: true}) 92 | } 93 | break; 94 | 95 | case "public": { 96 | const turnChoice = options.getString("turn"); 97 | 98 | switch(turnChoice) { 99 | case "on": { 100 | voiceChannel.permissionOverwrites.edit(guild.id, {Connect: true}) 101 | interaction.reply({embeds: [Embed.setDescription("🔓 Your channel is now public.")], ephemeral: true}) 102 | } 103 | break; 104 | 105 | case "off": { 106 | voiceChannel.permissionOverwrites.edit(guild.id, {Connect: false}) 107 | interaction.reply({embeds: [Embed.setDescription("🔒 Your channel is now private.")], ephemeral: true}) 108 | } 109 | break; 110 | } 111 | } 112 | break; 113 | } 114 | } 115 | } -------------------------------------------------------------------------------- /src/commands/user/together.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { DiscordTogether } = require('discord-together') 3 | const { Client, SlashCommandBuilder, ChannelType, ChatInputCommandInteraction } = require('discord.js') 4 | 5 | module.exports = { 6 | data: new SlashCommandBuilder() 7 | .setName("together") 8 | .setDescription("Watch youtube videos together!") 9 | .addChannelOption( 10 | option => 11 | option.setName("channel") 12 | .setDescription("Channel you want to acctivate this activity!") 13 | .addChannelTypes(ChannelType.GuildVoice) 14 | .setRequired(true)) 15 | .addStringOption( 16 | option => 17 | option.setName("activity") 18 | .setDescription("The activity you want to perform!") 19 | .setRequired(true) 20 | .addChoices( 21 | { name: "📺 Youtube", value: "youtube" }, 22 | { name: "☕ Word Snack", value: "wordsnack" }, 23 | { name: "📝 Sketch Heads", value: "sketchheads" }, 24 | ) 25 | ), 26 | /** 27 | * 28 | * @param {ChatInputCommandInteraction} interaction 29 | * @param {Client} client 30 | */ 31 | async execute(interaction, client) { 32 | const discordTogether = new DiscordTogether(client); 33 | const { options } = interaction; 34 | const activity = options.getString("activity") 35 | const channel = options.getChannel("channel") 36 | 37 | const Response = new EmbedBuilder() 38 | .setFooter({text: client.user.tag, iconURL: client.user.displayAvatarURL()}) 39 | 40 | switch(activity) { 41 | 42 | case "youtube": { 43 | Response.setTitle("📺 Youtube"); 44 | discordTogether.createTogetherCode( channel.id, 'youtube' ).then(x => { 45 | Response.setDescription(`[Click to watch youtube in ${channel}](${x.code})`) 46 | return interaction.reply({embeds: [Response]}) 47 | }) 48 | } 49 | break; 50 | 51 | case "wordsnack": { 52 | Response.setTitle("☕ Word Snack"); 53 | discordTogether.createTogetherCode( channel.id, 'wordsnack' ).then(x => { 54 | Response.setDescription(`[Click to play wordsnack in ${channel}](${x.code})`) 55 | return interaction.reply({embeds: [Response]}) 56 | }) 57 | } 58 | break; 59 | 60 | case "sketchheads": { 61 | Response.setTitle("✏️ Sketch Heads"); 62 | discordTogether.createTogetherCode( channel.id, 'sketchheads' ).then(x => { 63 | Response.setDescription(`[Click to play Sketch Heads in ${channel}](${x.code})`) 64 | return interaction.reply({embeds: [Response]}) 65 | }) 66 | } 67 | break; 68 | 69 | } 70 | 71 | } 72 | } -------------------------------------------------------------------------------- /src/commands/utils/setup.js: -------------------------------------------------------------------------------- 1 | const { Client, ChatInputCommandInteraction, SlashCommandBuilder, PermissionFlagsBits, ChannelType, EmbedBuilder, ButtonBuilder, ActionRowBuilder, ButtonStyle } = require('discord.js') 2 | 3 | const voiceDB = require('../../models/VoiceSystem') 4 | const captchaDB = require('../../models/CaptchaSystem') 5 | const modlogsDB = require('../../models/ModerationLogs') 6 | const featuresDB = require('../../models/Features') 7 | 8 | module.exports = { 9 | data: new SlashCommandBuilder() 10 | .setName("setup") 11 | .setDefaultMemberPermissions(PermissionFlagsBits.Administrator) 12 | .setDescription("Setup some settings!") 13 | .addSubcommand( 14 | command => 15 | command.setName("voice") 16 | .setDescription("Setup voice configuration") 17 | .addChannelOption( 18 | channel => 19 | channel.setName("channel") 20 | .setDescription("The join to create Channel!") 21 | .setRequired(true) 22 | .addChannelTypes(ChannelType.GuildVoice) 23 | )) 24 | .addSubcommand( 25 | command => 26 | command.setName("levels") 27 | .setDescription("Enable or disable the levels!") 28 | .addStringOption( 29 | option => 30 | option.setName("turn") 31 | .setDescription("Enable or Disable the level System") 32 | .addChoices( 33 | { name: "On", value: "on" }, 34 | { name: "Off", value: "off" }, 35 | )) 36 | .addStringOption( 37 | option => 38 | option.setName("background") 39 | .setDescription("Change the rank card background! (Needs to be a valid link )") 40 | .setMinLength(2))) 41 | .addSubcommand( 42 | command => 43 | command.setName("modlogs") 44 | .setDescription("Setup modlogs configuration") 45 | .addChannelOption( 46 | channel => 47 | channel.setName("log") 48 | .setDescription("The log Channel!") 49 | .setRequired(true) 50 | .addChannelTypes(ChannelType.GuildText) 51 | )) 52 | .addSubcommand( 53 | command => 54 | command.setName("captcha") 55 | .setDescription("Setup captcha configuration") 56 | .addRoleOption( 57 | option => 58 | option.setName("role") 59 | .setDescription("The role a verified user gets!") 60 | .setRequired(true)) 61 | .addChannelOption( 62 | option => 63 | option.setName("captcha_channel") 64 | .setDescription("There is a message coming...") 65 | .setRequired(true) 66 | .addChannelTypes(ChannelType.GuildText) 67 | )) 68 | .addSubcommand( 69 | command => 70 | command.setName("info") 71 | .setDescription("Get Information about your configurations!")) 72 | .addSubcommand( 73 | command => 74 | command.setName("remove") 75 | .setDescription("Remove configurations!") 76 | .addStringOption( 77 | option => 78 | option.setName("configuration") 79 | .setDescription("The configuration you want to remove!") 80 | .setRequired(true) 81 | .addChoices( 82 | { name: '🤖 Captcha', value: 'captcha' }, 83 | { name: '🔊 Voice', value: 'voice' }, 84 | { name: '📕 Modlogs', value: 'modlogs' }, 85 | ))), 86 | /** 87 | * 88 | * @param {ChatInputCommandInteraction} interaction 89 | * @param {Client} client 90 | */ 91 | async execute(interaction, client) { 92 | const { options, guild } = interaction; 93 | 94 | const channel = options.getChannel("channel") 95 | const role = options.getRole("role") 96 | const type = options.getString("configuration") 97 | 98 | const sub = options.getSubcommand(); 99 | 100 | const Response = new EmbedBuilder() 101 | .setColor(client.mainColor) 102 | .setTitle("✨ Setup") 103 | .setTimestamp(Date.now()) 104 | .setDescription("Here can you see your current settings!") 105 | 106 | switch(sub) { 107 | case "voice": { 108 | await voiceDB.findOneAndUpdate( 109 | {GuildID: guild.id}, 110 | {ChannelID: channel.id}, 111 | {new: true, upsert: true}) 112 | 113 | Response.setDescription("✅ Successfully set up the voice system!") 114 | } 115 | break; 116 | 117 | case "levels": { 118 | const background = options.getString("background"); 119 | const level_enabled = await featuresDB.findOne({GuildID: guild.id}); 120 | if(level_enabled) { 121 | const { LevelSystem } = level_enabled; 122 | 123 | if(background) { 124 | if(isValidHttpUrl(background)) { 125 | await featuresDB.findOneAndUpdate( 126 | {GuildID: guild.id}, 127 | {LevelSystem: { 128 | Enabled: LevelSystem ? 129 | LevelSystem.Enabled : 130 | false, 131 | Background: background 132 | }}, 133 | {new: true, upsert: true} 134 | ) 135 | 136 | Response 137 | .setDescription("🖼️ New Background set!") 138 | .setImage(background); 139 | } else { 140 | Response.setDescription("❌ `background` needs to be a valid link!") 141 | return interaction.reply({embeds: [Response], ephemeral: true}) 142 | } 143 | } 144 | 145 | switch(options.getString("turn")) { 146 | 147 | case "on": { 148 | await featuresDB.findOneAndUpdate( 149 | {GuildID: guild.id}, 150 | {LevelSystem: { Enabled: true, Background: LevelSystem ? LevelSystem.Background : "https://cdn.discordapp.com/attachments/965674056080826368/1003622130921001040/background.png" }}, 151 | {new: true, upsert: true}) 152 | 153 | Response.setDescription("✅ Successfully enabled the levels system!") 154 | } 155 | break; 156 | 157 | case "off": { 158 | await featuresDB.findOneAndUpdate( 159 | {GuildID: guild.id}, 160 | {LevelSystem: { Enabled: true, Background: LevelSystem ? LevelSystem.Background : "https://cdn.discordapp.com/attachments/965674056080826368/1003622130921001040/background.png" }}, 161 | {new: true, upsert: true}) 162 | 163 | Response.setDescription("✅ Successfully disabled the levels system!") 164 | } 165 | break; 166 | } 167 | } else { 168 | await featuresDB.findOneAndUpdate( 169 | {GuildID: guild.id}, 170 | {LevelSystem: { Enabled: false, Background: "https://cdn.discordapp.com/attachments/965674056080826368/1003622130921001040/background.png"}}, 171 | {new: true, upsert: true}) 172 | Response.setDescription("Set up the Level System, use `/setup levels turn: On` to turn it on, \n or use `/setup levels background: 'url'` to change the rankcard background!"); 173 | } 174 | } 175 | break; 176 | 177 | case "captcha": { 178 | const button = new ButtonBuilder() 179 | .setCustomId("captcha-btn") 180 | .setLabel("✅ Verify") 181 | .setStyle(ButtonStyle.Success); 182 | 183 | const captcha_channel = options.getChannel("captcha_channel") 184 | const captcha_embed = new EmbedBuilder() 185 | .setColor(client.mainColor) 186 | .setTitle("🤖 Captcha") 187 | .setDescription("Please Click on `✅ Verify` and solve the captcha within 30 seconds!") 188 | 189 | await captchaDB.findOneAndUpdate( 190 | {GuildID: guild.id}, 191 | {Role: role.id}, 192 | {new: true, upsert: true}) 193 | 194 | Response.setDescription("✅ Successfully set up the captcha system!") 195 | captcha_channel.send({embeds: [captcha_embed], components: [new ActionRowBuilder().addComponents(button)]}); 196 | } 197 | break; 198 | 199 | case "modlogs": { 200 | const modChannel = options.getChannel("log") 201 | 202 | await modlogsDB.findOneAndUpdate( 203 | {GuildID: guild.id}, 204 | {ChannelID: modChannel.id}, 205 | {new: true, upsert: true}) 206 | 207 | Response.setDescription("✅ Successfully set up the modlog system!") 208 | } 209 | break; 210 | 211 | case "info": { 212 | 213 | let captchaStatus = '`🔴 Off`' 214 | let voiceStatus = '`🔴 Off`' 215 | let modlogStatus = '`🔴 Off`' 216 | let levelSystemStatus = '`🔴 Off`' 217 | 218 | const levelSystemCheck = await featuresDB.findOne({GuildID: guild.id}) 219 | if(levelSystemCheck) { 220 | const { LevelSystem } = levelSystemCheck 221 | if(LevelSystem.Enabled) levelSystemStatus = '`🟢 On`' 222 | } else{ 223 | levelSystemStatus = '`🔴 Off`' 224 | } 225 | 226 | const voiceCheck = await voiceDB.findOne({GuildID: guild.id}) 227 | if(voiceCheck) voiceStatus = '`🟢 On`' 228 | 229 | const captchaCheck = await captchaDB.findOne({GuildID: guild.id}) 230 | if(captchaCheck) captchaStatus = '`🟢 On`' 231 | 232 | const modlogCheck = await modlogsDB.findOne({GuildID: guild.id}) 233 | if(modlogCheck) modlogStatus = '`🟢 On`' 234 | 235 | await Response.addFields([ 236 | {name: '🤖 Captcha', value: captchaStatus, inline: true }, 237 | {name: '🔊 Voice', value: voiceStatus, inline: true }, 238 | {name: '📕 Mod Log', value: modlogStatus, inline: true }, 239 | {name: '🎉 Level System', value: levelSystemStatus, inline: true }, 240 | ]) 241 | } 242 | break; 243 | 244 | case "remove": { 245 | switch(type) { 246 | case "captcha": { 247 | captchaDB.findOneAndDelete({ GuildID: guild.id }, (err) => { 248 | if(err) console.error(err) 249 | }); 250 | Response.setDescription("🗑️ Successfully removed the captcha system!") 251 | } 252 | break; 253 | 254 | case "voice": { 255 | voiceDB.findOneAndDelete({ GuildID: guild.id }, (err) => { 256 | if(err) console.error(err) 257 | }); 258 | Response.setDescription("🗑️ Successfully removed the voice system!") 259 | } 260 | break; 261 | 262 | case "modlogs": { 263 | modlogsDB.findOneAndDelete({ GuildID: guild.id }, (err) => { 264 | if(err) console.error(err) 265 | }); 266 | Response.setDescription("🗑️ Successfully removed the modlogs system!") 267 | } 268 | break; 269 | } 270 | } 271 | } 272 | 273 | await interaction.reply({embeds: [Response], ephemeral: true}) 274 | } 275 | } 276 | 277 | function isValidHttpUrl(string) { 278 | let url; 279 | 280 | try { 281 | url = new URL(string); 282 | } catch (_) { 283 | return false 284 | } 285 | 286 | return url.protocol === "https:" || url.protocol === "http:"; 287 | } -------------------------------------------------------------------------------- /src/components/buttons/captcha.js: -------------------------------------------------------------------------------- 1 | const { ButtonInteraction, Client, AttachmentBuilder, EmbedBuilder } = require('discord.js') 2 | const DB = require('../../models/CaptchaSystem') 3 | const { Captcha } = require('captcha-canvas') 4 | 5 | module.exports = { 6 | data: { 7 | name: "captcha-btn" 8 | }, 9 | /** 10 | * 11 | * @param {ButtonInteraction} interaction 12 | * @param {Client} client 13 | */ 14 | async execute(interaction, client) { 15 | const { member, guild } = interaction; 16 | 17 | DB.findOne({ GuildID: guild.id }, async (err, data) => { 18 | if(!data) return console.log(`Captcha Disabled for ${guild.name}!`); 19 | 20 | const captcha = new Captcha(); 21 | captcha.async = true; 22 | captcha.addDecoy(); 23 | captcha.drawTrace(); 24 | captcha.drawCaptcha(); 25 | 26 | const captchaAttachment = new AttachmentBuilder(await captcha.png) 27 | .setName("captcha.png"); 28 | 29 | const captchaEmbed = new EmbedBuilder() 30 | .setColor(client.mainColor) 31 | .setDescription("Please complete this captcha within 30 seconds!") 32 | .setImage('attachment://captcha.png') 33 | 34 | try { 35 | const msg = await member.user.send({files: [captchaAttachment], embeds: [captchaEmbed]}) 36 | 37 | const wrongCaptchaEmbed = new EmbedBuilder() 38 | .setColor(client.errorColor) 39 | .setDescription("🚫 Wrong Captcha"); 40 | 41 | const filter_ = (message) => { 42 | if(message.author.id !== member.id) return; 43 | if(message.content === captcha.text) { 44 | return true; 45 | } else { 46 | member.send({embeds: [wrongCaptchaEmbed]}) 47 | } 48 | } 49 | 50 | try { 51 | const response = await msg.channel.awaitMessages({ 52 | filter: filter_, 53 | max: 1, 54 | time: 30*1000, 55 | errors: ["time"]}); 56 | 57 | if(response) { 58 | DB.findOne({ GuildID: member.guild.id }, async (err, data) => { 59 | if(!data) return; 60 | if(!data.Role) return; 61 | 62 | const role = member.guild.roles.cache.get(data.Role) 63 | member.roles.add(role) 64 | member.user.send("`✅ You have been successfully verified!`"); 65 | }) 66 | } else { 67 | member.user.send("`❌ You didn't verify!`"); 68 | } 69 | 70 | } catch (error) { 71 | return console.log(error) 72 | } 73 | 74 | } catch (error) { 75 | return console.log(error) 76 | } 77 | }) 78 | } 79 | } -------------------------------------------------------------------------------- /src/events/client/interactionCreate.js: -------------------------------------------------------------------------------- 1 | const { Client, CommandInteraction, InteractionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: "interactionCreate", 5 | rest: false, 6 | once: false, 7 | /** 8 | * @param {Client} client 9 | * @param {CommandInteraction} interaction 10 | */ 11 | async execute(interaction, client) { 12 | 13 | if(interaction.isChatInputCommand()) { 14 | const { commands } = client; 15 | const { commandName } = interaction; 16 | const command = commands.get(commandName); 17 | if(!command) return; 18 | 19 | try { 20 | await command.execute(interaction, client); 21 | } catch (err) { 22 | console.error(err) 23 | interaction.reply({content: `Something went wrong while executing this command.`, ephemeral: true}) 24 | } 25 | 26 | } else if(interaction.isButton()) { 27 | const { buttons } = client; 28 | const button = buttons.get(interaction.customId); 29 | 30 | if(!button) return new Error("There is no code for this button!") 31 | 32 | try { 33 | await button.execute(interaction, client) 34 | } catch (error) { 35 | console.error(error) 36 | } 37 | 38 | 39 | } else if(interaction.type == InteractionType.ModalSubmit) { 40 | const { modals } = client; 41 | const modal = modals.get(interaction.customId) 42 | 43 | if(!modal) return new Error("There is no code for this modal!") 44 | 45 | try { 46 | await modal.execute(interaction, client) 47 | } catch (error) { 48 | console.error(error) 49 | } 50 | } else if(interaction.isContextMenuCommand()) { 51 | const { commands } = client; 52 | const { commandName } = interaction; 53 | const contextCommand = commands.get(commandName) 54 | if(!contextCommand) return; 55 | 56 | try { 57 | await contextCommand.execute(interaction.client); 58 | } catch (error) { 59 | console.error(error); 60 | } 61 | } 62 | 63 | }, 64 | }; 65 | -------------------------------------------------------------------------------- /src/events/client/ready.js: -------------------------------------------------------------------------------- 1 | const { Client } = require("discord.js"); 2 | const { activityInterval, database } = require("../../../config.json") 3 | const mongoose = require('mongoose') 4 | 5 | module.exports = { 6 | name: "ready", 7 | rest: false, 8 | once: false, 9 | /** 10 | * @param {Client} client 11 | */ 12 | async execute(client) { 13 | 14 | /* Connect to database */ 15 | if(!database) return; 16 | mongoose.connect(database, {}).then(() => console.log("The client is now connected to the database!") 17 | ).catch((err) => console.error(err)) 18 | 19 | console.log( 20 | `Logged in as ${client.user.tag} and running on ${client.guilds.cache.size} Server!` 21 | ); 22 | updateActivity(client) 23 | }, 24 | }; 25 | 26 | /** 27 | * @param {Client} client 28 | */ 29 | async function updateActivity(client) { 30 | 31 | let servercount = await client.guilds.cache.size 32 | 33 | const activities = [ 34 | `/invite | Watching ${servercount} Server`, 35 | `Created by maxシ#6858`, 36 | ] 37 | 38 | setInterval(() => { 39 | const status = activities[Math.floor(Math.random() * activities.length)] 40 | client.user.setActivity(status) 41 | }, activityInterval*1000) 42 | } -------------------------------------------------------------------------------- /src/events/distube/DistubeEvents.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders') 2 | const client = require('../../bot') 3 | 4 | const Response = new EmbedBuilder() 5 | .setColor(client.mainColor) 6 | .setTitle("🎵 Music") 7 | .setTimestamp(Date.now()) 8 | 9 | const status = queue => 10 | `Volume: \`${queue.volume}%\` | Filter: \`${queue.filters.names.join(', ') || 'Off'}\` | Loop: \`${ 11 | queue.repeatMode ? (queue.repeatMode === 2 ? 'All Queue' : 'This Song') : 'Off' 12 | }\` | Autoplay: \`${queue.autoplay ? 'On' : 'Off'}\`` 13 | client.distube 14 | .on('playSong', (queue, song) => 15 | queue.textChannel.send({embeds: [Response.setDescription(`▶️ | Playing \`${song.name}\` - \`${song.formattedDuration}\`\nRequested by: ${ 16 | song.user 17 | }\n${status(queue)}`)]} 18 | ) 19 | ) 20 | .on('addSong', (queue, song) => 21 | queue.textChannel.send({embeds: [Response.setDescription(`✅ | Added ${song.name} - \`${song.formattedDuration}\` to the queue by ${song.user}`)]}) 22 | ) 23 | .on('addList', (queue, playlist) => 24 | queue.textChannel.send({embeds: [Response.setDescription(`✅ | Added \`${playlist.name}\` playlist (${ 25 | playlist.songs.length 26 | } songs) to queue\n${status(queue)}`)]} 27 | ) 28 | ) 29 | .on('error', (channel, e) => { 30 | if (channel) channel.send(`❌ | An error encountered: ${e.toString().slice(0, 1974)}`) 31 | else console.error(e) 32 | }) 33 | .on('empty', channel => channel.send({embeds: [Response.setDescription('Voice channel is empty! Leaving the channel...')]})) 34 | .on('searchNoResult', (message, query) => 35 | message.channel.send({embeds: [Response.setDescription(`❌ | No result found for \`${query}\`!`)]}) 36 | ) 37 | .on('finish', queue => queue.textChannel.send({embeds: [Response.setDescription("`✅ Finished!`")]})) -------------------------------------------------------------------------------- /src/events/guild/voice.js: -------------------------------------------------------------------------------- 1 | const { Client, VoiceState, ChannelType } = require("discord.js"); 2 | const DB = require("../../models/VoiceSystem") 3 | 4 | module.exports = { 5 | name: "voiceStateUpdate", 6 | rest: false, 7 | once: false, 8 | /** 9 | * @param {Client} client 10 | * @param {VoiceState} oldState 11 | * @param {VoiceState} newState 12 | */ 13 | async execute(oldState, newState, client) { 14 | const { member, guild } = newState; 15 | const oldChannel = oldState.channel; 16 | const newChannel = newState.channel; 17 | const joinToCreate = DB.findOne({ GuildID: guild.id }, async (err, data) => { 18 | if(!data) return; 19 | 20 | if(oldChannel !== newChannel && newChannel && newChannel.id === data.ChannelID) { 21 | const voiceChannel = await guild.channels.create({ 22 | name: `🔰 │ ${member.user.tag}`, 23 | type: ChannelType.GuildVoice, 24 | parent: newChannel.parent, 25 | permissionOverwrites: [ 26 | { id: member.user.id, allow: ["Connect"]}, 27 | { id: guild.id, deny: ["Connect"]} 28 | ] 29 | }) 30 | 31 | client.voiceGenerator.set(member.id, voiceChannel.id); 32 | await newChannel.permissionOverwrites.edit(member, {Connect: false}); 33 | setTimeout(() => newChannel.permissionOverwrites.delete(member), 30*1000); 34 | 35 | return setTimeout(() => member.voice.setChannel(voiceChannel), 500); 36 | } 37 | 38 | const ownedChannel = client.voiceGenerator.get(member.id); 39 | 40 | if(ownedChannel && oldChannel.id == ownedChannel && (!newChannel || newChannel.id !== ownedChannel)) { 41 | client.voiceGenerator.set(member.id, null); 42 | oldChannel.delete().catch(() => {}); 43 | } 44 | }); 45 | } 46 | }; -------------------------------------------------------------------------------- /src/events/message/afkSystem.js: -------------------------------------------------------------------------------- 1 | const { Message, EmbedBuilder, Embed } = require('discord.js') 2 | const DB = require("../../models/AFKSystem") 3 | 4 | module.exports = { 5 | name: "messageCreate", 6 | once: false, 7 | /** 8 | * @param {Message} message 9 | */ 10 | async execute(message) { 11 | if(message.author.bot) return; 12 | 13 | //await DB.deleteOne({ GuildID: message.guild.id, UserID: message.author.id }) 14 | 15 | if(message.mentions.members) { 16 | const Response = new EmbedBuilder() 17 | .setColor(0xff5454) 18 | 19 | message.mentions.members.forEach((m) => { 20 | DB.findOne({GuildID: message.guild.id, UserID: m.id}, async(err, data) => { 21 | if(err) throw err; 22 | 23 | if(data) 24 | Response.setDescription(`${m} went AFK \n **Status:** ${data.Status}`); 25 | return message.reply({embeds: [Response]}) 26 | }) 27 | }) 28 | } 29 | } 30 | } -------------------------------------------------------------------------------- /src/events/message/levels.js: -------------------------------------------------------------------------------- 1 | const { Client, Message, MessageType, EmbedBuilder } = require('discord.js') 2 | 3 | const featuresDB = require('../../models/Features') 4 | const levelDB = require('../../models/LevelSystem') 5 | 6 | const calculateXP = (level) => level * level * 100 7 | 8 | module.exports = { 9 | name: "messageCreate", 10 | rest: false, 11 | once: false, 12 | /** 13 | * 14 | * @param {Message} message 15 | * @param {Client} client 16 | */ 17 | async execute(message, client) { 18 | const { guild, member } = message 19 | if(!message.inGuild()) return; 20 | if(member.user.bot) return; 21 | 22 | const levelSystemCheck = await featuresDB.findOne({GuildID: guild.id}) 23 | if(levelSystemCheck && levelSystemCheck.LevelSystem.Enabled) { 24 | addXP(guild.id, member.id, 5, message, client) 25 | } 26 | }, 27 | calculateXP 28 | } 29 | 30 | /** 31 | * @param {Message} message 32 | */ 33 | const addXP = async(guildId, userId, xpToAdd, message, client) => { 34 | const result = await levelDB.findOneAndUpdate({ 35 | GuildID: guildId, 36 | UserID: userId 37 | }, { 38 | GuildID: guildId, 39 | UserID: userId, 40 | $inc: { 41 | xp: xpToAdd 42 | } 43 | }, { 44 | upsert: true, 45 | new: true 46 | }) 47 | 48 | let { xp, level } = result 49 | const needed = calculateXP(level) 50 | 51 | if(xp >= needed) { 52 | level++ 53 | xp -= needed 54 | 55 | const LevelEmbed = new EmbedBuilder() 56 | .setTitle("Level Up") 57 | .setDescription(`Congrats **${message.member.user.username}**! You are now __**Level ${level}**__ 🥳`) 58 | .setThumbnail(message.member.user.displayAvatarURL()) 59 | .setColor(client.mainColor) 60 | .setTimestamp(Date.now()); 61 | 62 | message.reply({embeds: [LevelEmbed]}); 63 | 64 | await levelDB.updateOne({ 65 | GuildID: guildId, 66 | UserID: userId, 67 | }, { 68 | level: level, 69 | xp: xp, 70 | }) 71 | } 72 | } -------------------------------------------------------------------------------- /src/events/message/messageLogUpdate.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require('@discordjs/builders'); 2 | const { Client, Message } = require('discord.js') 3 | const modlogsDB = require('../../models/ModerationLogs'); 4 | 5 | module.exports = { 6 | name: "messageUpdate", 7 | rest: false, 8 | once: false, 9 | /** 10 | * @param {Message} oldMessage 11 | * @param {Message} newMessage 12 | * @param {Client} client 13 | */ 14 | async execute(oldMessage, newMessage, client) { 15 | if(oldMessage.author.bot) return; 16 | if(oldMessage.content === newMessage.content) return; 17 | 18 | const Count = 1950; 19 | 20 | const Original = oldMessage.content.slice(0, Count) + (oldMessage.content.length > 1950 ? " ..." : "") 21 | const Edited = newMessage.content.slice(0, Count) + (newMessage.content.length > 1950 ? " ..." : "") 22 | 23 | const Log = new EmbedBuilder() 24 | .setColor(client.mainColor) 25 | .setDescription(`📘 A [message](${newMessage.url}) by ${newMessage.author} was **edited** in ${newMessage.channel}.\n 26 | **Original:**\n[ ${Original} ] \n**Edited:**\n [ ${Edited} ]`); 27 | 28 | const data = await modlogsDB.findOne({ GuildID: newMessage.guild.id }) 29 | if(!data) return; 30 | 31 | const channel = newMessage.guild.channels.cache.get(data.ChannelID); 32 | channel.send({embeds: [Log]}) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/models/AFKSystem.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("AFK", new Schema({ 4 | GuildID: String, 5 | UserID: String, 6 | Status: String, 7 | Time: String 8 | })) -------------------------------------------------------------------------------- /src/models/CaptchaSystem.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("Captcha", new Schema({ 4 | GuildID: String, 5 | Role: String 6 | })) -------------------------------------------------------------------------------- /src/models/Features.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("Features", new Schema({ 4 | GuildID: String, 5 | LevelSystem: { 6 | Enabled: { 7 | type: Boolean, 8 | default: false, 9 | }, 10 | Background: { 11 | type: String, 12 | default: "https://cdn.discordapp.com/attachments/965674056080826368/1003622130921001040/background.png" 13 | } 14 | } 15 | })) -------------------------------------------------------------------------------- /src/models/LevelSystem.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("LevelSystem", new Schema({ 4 | GuildID: String, 5 | UserID: String, 6 | xp: { 7 | type: Number, 8 | default: 0, 9 | }, 10 | level: { 11 | type: Number, 12 | default: 1, 13 | }, 14 | })) -------------------------------------------------------------------------------- /src/models/ModerationLogs.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("modlogs", new Schema({ 4 | GuildID: String, 5 | ChannelID: String 6 | })) -------------------------------------------------------------------------------- /src/models/VoiceSystem.js: -------------------------------------------------------------------------------- 1 | const { model, Schema } = require('mongoose') 2 | 3 | module.exports = model("VoiceSystem", new Schema({ 4 | GuildID: String, 5 | ChannelID: String 6 | })) --------------------------------------------------------------------------------