├── .gitignore ├── LICENSE ├── README.md ├── SECURITY.md ├── package.json └── src ├── commands ├── Account │ ├── server │ │ └── server.js │ └── user │ │ ├── link.js │ │ ├── new.js │ │ ├── premium.js │ │ ├── resetPassword.js │ │ ├── unlink.js │ │ └── user.js ├── General │ ├── help.js │ ├── snipe.js │ └── stats.js └── _ignored │ ├── eval.js │ ├── pull.js │ ├── restart.js │ └── staff │ ├── ban.js │ ├── forceunlink.js │ ├── kick.js │ ├── purge.js │ ├── staff.js │ ├── unban.js │ └── userinfo.js ├── database └── schemas │ ├── Domains.js │ ├── UserData.js │ └── UserPrem.js ├── events ├── guildBanAdd.js ├── messageCreate.js ├── messageDelete.js ├── messageUpdate.js └── ready.js ├── example-config.json ├── example.env ├── index.js ├── utils ├── Cache.js ├── Email.js ├── Transporter.js ├── commandHandler.js ├── fetchNodes.js ├── libs │ └── emailTemplate.html └── mongo.js └── wrapper ├── Application ├── Application.js ├── Modules │ ├── createServer.js │ ├── createUser.js │ ├── deleteServer.js │ ├── deleteUser.js │ ├── getAllLocations.js │ ├── getAllNests.js │ ├── getAllNodes.js │ ├── getAllServers.js │ ├── getAllUsers.js │ ├── getLocation.js │ ├── getNest.js │ ├── getNode.js │ ├── getServer.js │ ├── getUser.js │ └── updateUser.js └── utils.js └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package-lock.json 3 | config.json 4 | .git 5 | .env 6 | log.json 7 | test.js 8 | .idea 9 | tickets 10 | interactionCreate.js 11 | WordBlacklist.js 12 | vote -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021-2022 Solo 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 | ## Host Bot 2 | 3 | A Bot for all your hosting needs. Allows Users to make accounts, Create servers and more all In discord! No need for Dashboards or other bots. Use this one! 4 | 5 | ## Selfhosting 6 | 7 | - Make sure You have Node.JS v16 installed 8 | - Download this repo by clicking the download code button or by executing `git clone https://github.com/Hadimhz/bot-rewrite.git` 9 | - Make sure that `Guild Members` intent is enabled for your bot application 10 | - Rename example-config.json/example.env to config.json/.env and fill in all fields 11 | - Once everything is done execute `npm install` to intall packages; to run the bot use `node .` 12 | 13 | ## Contributing 14 | 15 | Do you want to help? If so, it's very simple, just follow these steps: 16 | 17 | - Fork this repository using `Fork` button in the right upper corner; 18 | - Make changes to forked repo; 19 | - Test if Your changes don't break the bot; 20 | - Create a Pull Request presenting all Your changes; 21 | - And that's how You do it. Now wait for us to review it :D 22 | 23 | ## Misc 24 | 25 | If you decide to use this bot, You must give credit to the people that have worked on. Not doing so will void the LICENSE set in place. 26 | 27 | If you need further info on rewrite please join out rewrite Discord server using [this](https://discord.gg/V3KvPQET5v) link. 28 | 29 | This bot uses [Solo](https://github.com/Hadimhz)'s command handler. You can check it [here](https://github.com/Hadimhz/Discord-Bot). 30 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | 3 | ## Reporting a Vulnerability 4 | 5 | If you think you found a vulnerability but not sure report it still, This way we can make sure it is. It's better to be safe than sorry. 6 | 7 | If you have found a vulnerability Please [join our discord server](https://discord.gg/V3KvPQET5v) and dm one of the admins. 8 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "chalk": "^4.1.1", 4 | "child_process": "^1.0.2", 5 | "common-tags": "^1.8.0", 6 | "discord.js": "^13.1.0", 7 | "dotenv": "^10.0.0", 8 | "humanize-duration": "^3.27.0", 9 | "jsdom": "^16.6.0", 10 | "marked": "^2.1.3", 11 | "moment": "^2.29.1", 12 | "mongoose": "^5.13.3", 13 | "node-fetch": "^2.6.1", 14 | "node-os-utils": "^1.3.5", 15 | "nodemailer": "^6.6.3", 16 | "pm2": "^5.1.0", 17 | "validator": "^13.6.0" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/commands/Account/server/server.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | module.exports.info = { 4 | name: "server", 5 | description: "Commands related to servers.", 6 | aliases: ['s'] 7 | } -------------------------------------------------------------------------------- /src/commands/Account/user/link.js: -------------------------------------------------------------------------------- 1 | const userdb = require('../../../database/schemas/UserData') 2 | const validator = require('validator'); 3 | const config = require('../../../config.json'); 4 | const { panel } = require('../../../index'); 5 | const Discord = require('discord.js'); 6 | const { genPassword } = require('./user'); 7 | const Transporter = require('../../../utils/Transporter'); 8 | 9 | module.exports.run = async (client, message, args) => { 10 | 11 | if (!config.email.enabled) return; 12 | 13 | // Check to see if they already have an account 14 | const userData = await userdb.findOne({ userID: message.author.id }); 15 | if (userData) return message.reply({ 16 | content: "You already have a `panel account` linked to your discord account!" 17 | }) 18 | 19 | // Locate the category 20 | let category = message.guild.channels.cache.get(config.discord.tickets.accountCreation) 21 | 22 | let channel = await message.guild.channels.create(message.author.tag, { 23 | parent: category.id, 24 | permissionOverwrites: [ 25 | { 26 | id: message.author.id, 27 | allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'] 28 | }, 29 | { 30 | id: message.guild.id, 31 | deny: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'] 32 | } 33 | ] 34 | }).catch(e => { }); 35 | 36 | // Tell the user to check the channel. 37 | message.reply(`Please check <#${channel.id}> to link an account.`); 38 | 39 | let code = genPassword(20); 40 | 41 | // Questions user needs to answer 42 | let questions = [ 43 | { 44 | id: "email", 45 | question: "Whats your email? *(must be a valid email)*" + "\n\n" + "*This will unlink other accounts if you have them linked*", 46 | filter: (m) => m.author.id === message.author.id, 47 | afterChecks: [ 48 | { 49 | check: (msg) => validator.isEmail(msg.toLowerCase().trim()), 50 | errorMessage: "The email must be valid.", 51 | }, 52 | { 53 | check: async (msg) => (await panel.fetchUsers({ 54 | filter: { 55 | key: "email", 56 | value: msg.trim().toLowerCase() 57 | } 58 | })).success, 59 | errorMessage: "Couldn't find a panel account with that email.", 60 | } 61 | ], 62 | callback: (value) => { 63 | new Transporter().setSender(config.email.from) 64 | .setReceiver(value).setSubject("Identity Verification!") 65 | .setText("Someone has attempted to link their discord account to your " + message.guild.name + " panel account! Your code is: " + code 66 | + "\n\n" + "If that was not you, safely ignore this message. ") 67 | .send(); 68 | 69 | }, 70 | time: 30000, 71 | value: null 72 | }, { 73 | id: "code", 74 | question: "You have been sent an email with a code to confirm your identity." 75 | + "\n" + "You have 2 minutes to post the code in this channel.", 76 | filter: (m) => m.author.id === message.author.id, 77 | if: () => config.email.enabled, 78 | afterChecks: [ 79 | { 80 | check: (msg) => msg.trim() == code, 81 | errorMessage: "The code must be the exact one sent to your email.", 82 | } 83 | ], 84 | time: 120000, 85 | value: null 86 | } 87 | ]; 88 | 89 | // prompt the user with the questions. 90 | let msg = null; 91 | 92 | questions = questions.filter(q => q.if == null || q.if() == true); 93 | 94 | for (let question of questions) { 95 | if (msg == null) { 96 | msg = await channel.send({ 97 | content: `<@!${message.member.id}>`, 98 | embeds: [new Discord.MessageEmbed() 99 | .setColor(0x36393e) 100 | .setDescription(question.question) 101 | .setFooter("You can type 'cancel' to cancel the request")] 102 | }); 103 | } else { 104 | msg.edit({ 105 | content: `<@!${message.member.id}>`, 106 | embeds: [msg.embeds[0].setDescription(question.question)] 107 | }); 108 | } 109 | 110 | let awaitMessages = await channel.awaitMessages({ 111 | filter: (m) => m.author.id === message.author.id, 112 | max: 1, 113 | time: question.time, 114 | errors: ['time'], 115 | }).catch(x => { 116 | channel.send("User failed to provide an input!\nAccount Cancelled! :thumbsup:"); 117 | setTimeout(() => { 118 | channel.delete(); 119 | }, 5000); 120 | return; 121 | }); 122 | if (!awaitMessages) return; 123 | 124 | // Log the value... 125 | 126 | question.value = awaitMessages.first().content.trim(); 127 | 128 | await awaitMessages.first().delete(); 129 | 130 | if (question.value == 'cancel') { 131 | 132 | msg.delete(); 133 | channel.send("Cancelled! :thumbsup:"); 134 | 135 | setTimeout(() => { 136 | channel.delete(); 137 | }, 5000); 138 | return; 139 | } 140 | 141 | for (const aftercheck of question.afterChecks) { 142 | if ((await aftercheck.check(question.value)) == false) { 143 | channel.send(aftercheck.errorMessage); 144 | channel.send("Account Cancelled! :thumbsup:"); 145 | setTimeout(() => { 146 | channel.delete(); 147 | }, 5000); 148 | return; 149 | }; 150 | } 151 | 152 | if (question.callback != null) question.callback(question.value); 153 | 154 | } 155 | 156 | const { data } = await panel.fetchUsers({ 157 | filter: { 158 | key: "email", 159 | value: questions.find(question => question.id == 'email').value.toLowerCase() 160 | } 161 | }); 162 | 163 | 164 | 165 | msg.edit({ 166 | content: `<@!${message.member.id}>`, 167 | embeds: [msg.embeds[0] 168 | .setDescription('Attempting to link your account...\n\n>>> ' 169 | + questions.map(question => `**${question.id}:** ${question.value.toLowerCase()}`).join('\n')) 170 | .setFooter('').setTimestamp()] 171 | }); 172 | 173 | await userdb.findOneAndRemove({ email: questions.find(question => question.id == 'email').value.toLowerCase() }) 174 | await userdb.create({ 175 | userID: message.author.id, 176 | consoleID: data.id, 177 | email: data.email, 178 | username: data.username, 179 | createdTimestamp: Date.now(), 180 | }) 181 | 182 | 183 | msg.edit({ 184 | content: "Hello! You have linked an account to your discord, Heres the login information", 185 | embeds: [new Discord.MessageEmbed() 186 | .setColor("GREEN") 187 | .setDescription("URL: " + config.pterodactyl.hosturl + "\n" + "Username: " + data.username 188 | + "\n" + "Email: " + data.email) 189 | .setFooter("Please note: It is recommended that you change the password")] 190 | }) 191 | 192 | } 193 | 194 | module.exports.info = { 195 | name: "link", 196 | description: "Links your account to a panel account.", 197 | } 198 | -------------------------------------------------------------------------------- /src/commands/Account/user/new.js: -------------------------------------------------------------------------------- 1 | const userdb = require('../../../database/schemas/UserData') 2 | const validator = require('validator'); 3 | const config = require('../../../config.json'); 4 | const { panel } = require('../../../index'); 5 | const Discord = require('discord.js'); 6 | const { genPassword } = require('./user'); 7 | const Transporter = require('../../../utils/Transporter'); 8 | const userprem = require('../../../database/schemas/UserPrem') 9 | 10 | module.exports.run = async (client, message, args) => { 11 | 12 | // Check to see if they already have an account 13 | const userData = await userdb.findOne({ userID: message.author.id }); 14 | if (userData) return message.reply({ 15 | content: "You already have a `panel account` linked to your discord account!" 16 | }) 17 | 18 | // Locate the category 19 | let category = message.guild.channels.cache.get(config.discord.tickets.accountCreation) 20 | 21 | let channel = await message.guild.channels.create(message.author.tag, { 22 | parent: category.id, 23 | permissionOverwrites: [ 24 | { 25 | id: message.author.id, 26 | allow: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'] 27 | }, 28 | { 29 | id: message.guild.id, 30 | deny: ['VIEW_CHANNEL', 'SEND_MESSAGES', 'READ_MESSAGE_HISTORY'] 31 | } 32 | ] 33 | }).catch(e => { }); 34 | 35 | // Tell the user to check the channel. 36 | message.reply(`Please check <#${channel.id}> to create an account.`); 37 | 38 | 39 | let code = genPassword(20); 40 | 41 | // Questions user needs to answer 42 | let questions = [ 43 | { 44 | id: "username", 45 | question: "What should your username be? (**Please dont use spaces or special characters**)", // The questions... 46 | filter: (m) => m.author.id === message.author.id, // Filter to use... 47 | afterChecks: [{ 48 | check: (msg) => msg.trim().split(" ").length == 1, 49 | errorMessage: "Username must not contain any spaces", 50 | }], 51 | time: 30000, // how much time a user has to answer the question before it times out 52 | value: null // The user's response. 53 | }, { 54 | id: "email", 55 | question: "Whats your email? *(must be a valid email)*", 56 | filter: (m) => m.author.id === message.author.id, 57 | afterChecks: [ 58 | { 59 | check: (msg) => validator.isEmail(msg.toLowerCase().trim()), 60 | errorMessage: "The email must be valid.", 61 | } 62 | ], 63 | callback: (value) => { 64 | if (config.email.enabled) { 65 | new Transporter().setSender(config.email.from) 66 | .setReceiver(value).setSubject("Account verification!") 67 | .setText("Your email address has been used to create an account with " + message.guild.name + "! Your code is: " + code 68 | + "\n\n" + "If that was not you, safely ignore this message. ") 69 | .send(); 70 | } 71 | }, 72 | time: 30000, 73 | value: null 74 | }, { 75 | id: "code", 76 | question: "You have been sent an email with a code to confirm your identity." 77 | + "\n" + "You have 2 minutes to post the code in this channel.", 78 | filter: (m) => m.author.id === message.author.id, 79 | if: () => config.email.enabled, 80 | afterChecks: [ 81 | { 82 | check: (msg) => msg.trim() == code, 83 | errorMessage: "The code must be the exact one sent to your email.", 84 | } 85 | ], 86 | time: 120000, 87 | value: null 88 | } 89 | ]; 90 | 91 | // prompt the user with the questions. 92 | let msg = null; 93 | 94 | questions = questions.filter(q => q.if == null || q.if() == true); 95 | 96 | for (let question of questions) { 97 | if (msg == null) { 98 | msg = await channel.send({ 99 | content: `<@!${message.member.id}>`, 100 | embeds: [new Discord.MessageEmbed() 101 | .setColor(0x36393e) 102 | .setDescription(question.question) 103 | .setFooter("You can type 'cancel' to cancel the request")] 104 | }); 105 | } else { 106 | msg.edit({ 107 | content: `<@!${message.member.id}>`, 108 | embeds: [msg.embeds[0].setDescription(question.question)] 109 | }); 110 | } 111 | 112 | let awaitMessages = await channel.awaitMessages({ 113 | filter: (m) => m.author.id === message.author.id, 114 | max: 1, 115 | time: question.time, 116 | errors: ['time'], 117 | }).catch(x => { 118 | channel.send("User failed to provide an input!\nAccount Cancelled! :thumbsup:"); 119 | setTimeout(() => { 120 | channel.delete(); 121 | }, 5000); 122 | return; 123 | }); 124 | if (!awaitMessages) return; 125 | 126 | // Log the value... 127 | 128 | question.value = awaitMessages.first().content.trim(); 129 | 130 | await awaitMessages.first().delete(); 131 | 132 | if (question.value == 'cancel') { 133 | 134 | msg.delete(); 135 | channel.send("Cancelled! :thumbsup:"); 136 | 137 | setTimeout(() => { 138 | channel.delete(); 139 | }, 5000); 140 | return; 141 | } 142 | 143 | for (const aftercheck of question.afterChecks) { 144 | if (aftercheck.check(question.value) == false) { 145 | channel.send(aftercheck.errorMessage); 146 | channel.send("Account Cancelled! :thumbsup:"); 147 | setTimeout(() => { 148 | channel.delete(); 149 | }, 5000); 150 | return; 151 | }; 152 | } 153 | 154 | if (question.callback != null) question.callback(question.value); 155 | 156 | } 157 | 158 | msg.edit({ 159 | content: `<@!${message.member.id}>`, 160 | embeds: [msg.embeds[0] 161 | .setDescription('Attempting to create an account for you...\n\n>>> ' 162 | + questions.map(question => `**${question.id}:** ${question.value.toLowerCase()}`).join('\n')) 163 | .setFooter('').setTimestamp()] 164 | }); 165 | 166 | const data = { 167 | "username": questions.find(question => question.id == 'username').value.toLowerCase(), 168 | "email": questions.find(question => question.id == 'email').value.toLowerCase(), 169 | "first_name": questions.find(question => question.id == 'username').value, 170 | "last_name": ".", 171 | "password": genPassword(), 172 | "root_admin": false, 173 | "language": "en" 174 | } 175 | 176 | panel.createUser(data.username, data.password, data.email, data.first_name, data.last_name, data.root_admin, data.language) 177 | .then(async (user) => { 178 | 179 | if (user.success) { 180 | await userdb.create({ 181 | userID: message.author.id, 182 | consoleID: user.data.id, 183 | email: user.data.email, 184 | username: user.data.username, 185 | createdTimestamp: Date.now() 186 | }) 187 | await userprem.create({ 188 | consoleID: user.data.id, 189 | amount: 0, 190 | used: 0 191 | }) 192 | msg.edit({ 193 | content: "Hello! You created an new account, Heres the login information", 194 | embeds: [new Discord.MessageEmbed() 195 | .setColor("GREEN") 196 | .setDescription("URL: " + config.pterodactyl.hosturl + "\n" + "Username: " + data.username 197 | + "\n" + "Email: " + data.email + " \nPassword: " + data.password) 198 | .setFooter("Please note: It is recommended that you change the password")] 199 | }) 200 | 201 | channel.send('**You have 30mins to keep note of this info before the channel is deleted.**') 202 | message.guild.members.cache.get(message.author.id).roles.add(config.discord.roles.client); 203 | setTimeout(function () { 204 | channel.delete(); 205 | }, 1800000); 206 | 207 | } else { 208 | let errEmbed = new Discord.MessageEmbed(); 209 | if (user.error.length > 1) { 210 | errEmbed 211 | .setColor("RED") 212 | .setTitle("An error has occured:") 213 | .setDescription("**ERRORS:**\n\n● " + user.error.map(error => error.detail.replace('\n', ' ')).join('\n● ')) 214 | .setTimestamp().setFooter('Deleting in 30 seconds...') 215 | } else { 216 | errEmbed 217 | .setColor("RED") 218 | .setTitle("An error has occured:") 219 | .setDescription("**ERROR:**\n\n● " + user.error.detail) 220 | .setTimestamp().setFooter('Deleting in 30 seconds...') 221 | } 222 | 223 | msg.edit({ 224 | content: '\u200b', 225 | embeds: [errEmbed] 226 | }) 227 | setTimeout(() => channel.delete(), 30000); 228 | } 229 | }) 230 | } 231 | 232 | module.exports.info = { 233 | name: "new", 234 | description: "Creates a new panel account", 235 | aliases: ['n'], 236 | } -------------------------------------------------------------------------------- /src/commands/Account/user/premium.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require('discord.js'); 2 | const userprem = require('../../../database/schemas/UserPrem') 3 | const userdb = require('../../../database/schemas/UserData') 4 | const config = require('../../../config.json') 5 | module.exports.run = async (client, message, args) => { 6 | //Fetching the members so stuff doesn't come back as undefined 7 | message.guild.members.fetch() 8 | const person = message.mentions.users.first() || await message.guild.members.cache.get(args[0]) || message.author; 9 | //Getting Users console ID 10 | const userData = await userdb.findOne({ 11 | userID: person.id 12 | }); 13 | if (message.author.id === person.id && !userData) return message.reply({ 14 | content: "You do not have a `panel account` linked to your discord!" + 15 | "\n" + `Use \`${config.discord.bot.prefix}user new\` to create an account and get started or \`${config.discord.bot.prefix}user link\` to link a existing account.` 16 | }) 17 | if (!userData) return message.channel.send('The User you mentioned doesn\'t have a account or isn\'t linked.') 18 | // This is where you get the amount of servers the user has and has used 19 | const pp = await userprem.findOne({ 20 | consoleID: userData.consoleID //The users Console ID instead of saving it to a User's ID 21 | }); 22 | if (message.author.id === person.id && !pp) return message.reply(`You have No premium servers, You can buy them for ${config.premiumprice}$ by donating to ${config.donationlink}`) 23 | if (message.author.id === person.id && pp.amount === '0' && pp.used === '0') return message.reply(`You have No premium servers, You can buy them for $${config.premiumprice} by donating to ${config.donationlink}`) 24 | const embed = new MessageEmbed() 25 | .setTitle('Premium Servers For ' + `${person.tag || person.user.tag}`) 26 | .setDescription(`${pp.used} out of ${pp.amount} Servers used`) 27 | .setColor('BLURPLE') 28 | message.reply({ 29 | embeds: [embed] 30 | }) 31 | } 32 | 33 | module.exports.info = { 34 | name: "premium", 35 | description: "Get your premium user data", 36 | aliases: ['p'] 37 | } -------------------------------------------------------------------------------- /src/commands/Account/user/resetPassword.js: -------------------------------------------------------------------------------- 1 | const userdb = require('../../../database/schemas/UserData') 2 | const config = require('../../../config.json'); 3 | const { panel } = require('../../../index'); 4 | const Discord = require('discord.js'); 5 | const { genPassword } = require('./user'); 6 | const Transporter = require('../../../utils/Transporter'); 7 | 8 | // Questions user needs to answer 9 | 10 | module.exports.run = async (client, message, args) => { 11 | 12 | // Check to see if they already have an account 13 | const userData = await userdb.findOne({ userID: message.author.id }); 14 | if (!userData) return message.reply({ 15 | content: "You do not have a `panel account` linked to your discord!" 16 | + "\n" + `Use \`${config.discord.bot.prefix}user new\` to create an account and get started.` 17 | }) 18 | 19 | const embed = new Discord.MessageEmbed() 20 | .setTitle("Password Reset").setColor("BLUE") 21 | .setDescription("Resetting your password...") 22 | .setTimestamp() 23 | 24 | let msg = await message.author.send({ 25 | embeds: [embed] 26 | }).catch(e => { 27 | message.channel.send({ content: "Failed to send you a DM, please Make sure your dms are open." }); 28 | return; 29 | }); 30 | 31 | message.reply("Check your DMs! 📬"); 32 | 33 | const password = genPassword(); 34 | 35 | let res = await panel.updateUser(userData.consoleID, { password }); 36 | 37 | if (res.success) { 38 | 39 | if (config.email.enabled) { 40 | embed.setDescription("Success! You're password has been changed and sent to your email."); 41 | new Transporter().setReceiver(userData.email).setSubject("Password Reset!") 42 | .setText("Your password has been reset!" 43 | + "\n" + "new password is: " + password 44 | + "\n\n" + "It is suggested that you change your password.").send(); 45 | 46 | } else { 47 | embed.setDescription("Your new password is: ||" + password + "||" 48 | + "\n\n" + "*It is suggested that you change your password.*"); 49 | } 50 | 51 | embed.setColor("GREEN"); 52 | 53 | } else embed.setDescription("An error has occured while attempting to change your password.").setColor("DARK_RED"); 54 | 55 | msg.edit({ embeds: [embed] }); 56 | 57 | } 58 | 59 | module.exports.info = { 60 | name: "resetpassword", 61 | description: "Reset your account's password.", 62 | aliases: ['reset'], 63 | } -------------------------------------------------------------------------------- /src/commands/Account/user/unlink.js: -------------------------------------------------------------------------------- 1 | const userdb = require('../../../database/schemas/UserData') 2 | const config = require('../../../config.json') 3 | const { MessageEmbed } = require('discord.js') 4 | module.exports.run = async (client, message, args) => { 5 | e = await message.channel.send('Checking DataBase...') 6 | const userData = await userdb.findOneAndDelete({ 7 | userID: message.author.id 8 | }); 9 | if (!userData) return e.edit(`You don\'t Seem to have a account link, \`${config.discord.bot.prefix}user link\` to link your account`); 10 | const embed = new MessageEmbed() 11 | .setTitle("Account Unlink") 12 | .setColor("#36393F") 13 | .setDescription(`Unlinked your account, do \`${config.discord.bot.prefix}user link\` To relink your account`) 14 | e.edit({content: ' ', embeds: [embed]}) 15 | } 16 | module.exports.info = { 17 | name: "unlink", 18 | description: "Unlink your account.", 19 | aliases: ['ul'], 20 | } 21 | -------------------------------------------------------------------------------- /src/commands/Account/user/user.js: -------------------------------------------------------------------------------- 1 | 2 | // Do not add a run method to it, isnt needed 3 | const CAPSNUM = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; 4 | 5 | let genPassword = (length = 10) => { 6 | var password = ""; 7 | while (password.length < length) { 8 | password += CAPSNUM[Math.floor(Math.random() * CAPSNUM.length)]; 9 | } 10 | return password; 11 | }; 12 | 13 | 14 | // Exporting genPassword for new and reset. 15 | module.exports.genPassword = genPassword; 16 | 17 | module.exports.info = { 18 | name: "user", 19 | description: "Commands related to user", 20 | aliases: ['u'] 21 | } -------------------------------------------------------------------------------- /src/commands/General/help.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require('discord.js') 2 | const config = require("../../config.json") 3 | module.exports.run = (client, message, args) => { 4 | 5 | let { log: parsed, findCommand } = require(ROOT_PATH + '/utils/commandHandler'); 6 | let rrole; 7 | let embed = new MessageEmbed() 8 | .setTitle("Commands Help!").setColor("#36393F").setDescription(`Here is a list of commands that you can use! Use \`${config.discord.bot.prefix}help \` to get help with a specific command!`) 9 | .setFooter(`Requested by ${message.author.tag}`).setTimestamp(); 10 | 11 | if (args[0] == null) { 12 | for (const category of parsed.categories.filter(x => x.name != '_ignored')) { 13 | embed.addField(category.name, "`" + category.children.map(x => x.name).join('`, `') + "`"); 14 | } 15 | } else { 16 | 17 | let cmd = findCommand([...args], client.commands); 18 | 19 | if (cmd == null) { 20 | embed.setDescription(`Couldn't find a command with the name ${args[0]}.`).setColor("RED"); 21 | } else { 22 | let usage = config.discord.bot.prefix + cmd.usage; 23 | 24 | let aliases = "`" + cmd.aliases.join('`, `') + "`"; 25 | let subCommands = cmd.subCommands != null ? `\`${cmd.subCommands.map(x => x.name).join('`, `')}\`` : null; 26 | rrole = cmd.requiredRole == null ? "none" : cmd.requiredRole; 27 | if(rrole != "none") rrole = message.guild.roles.cache.find(r => r.id === rrole); 28 | let help = [ 29 | `**name:** ${cmd.name}`, 30 | `**description:** ${cmd.description}`, 31 | cmd.aliases.length == 0 ? null : `**aliases:** ${aliases}`, 32 | `**usage:** ${usage}`, 33 | `**requiredPermission:** ${cmd.requiredPermission == null ? "none" : cmd.requiredPermission}`, 34 | `**requiredRoles:** ${rrole}`, 35 | subCommands != null ? `**subcommands:** ${subCommands}` : null 36 | ] 37 | 38 | embed.addField(`${args.slice(0, cmd.depth).join(' ')}'s Help:`, help.filter(x => x != null).join('\n')) 39 | } 40 | 41 | } 42 | 43 | message.channel.send({embeds: [embed]}); 44 | } 45 | 46 | module.exports.info = { 47 | name: 'help',// default = file name (without the extention) 48 | description: "Shows you the list of commands.",// default is "None" 49 | requiredPermission: null,// default is null 50 | aliases: ['?', "h"], // default is null 51 | usage: '[command] [subcommand]' // default is null 52 | } 53 | -------------------------------------------------------------------------------- /src/commands/General/snipe.js: -------------------------------------------------------------------------------- 1 | const config = require('../../config.json') 2 | const { 3 | MessageEmbed 4 | } = require('discord.js') 5 | const Discord = require('discord.js') 6 | module.exports.run = async (client, message, args) => { 7 | if (args[0] != null) { 8 | console.log(args) 9 | if (args[0].toLowerCase() == 'dump' && message.member.roles.cache.get(config.discord.roles.botdev) != null) { 10 | let file = new Discord.MessageAttachment(Buffer.from(JSON.stringify(Array.from(client.messageSnipes)), "utf8"), "Snipes-Dump.json"); 11 | message.author.send({ 12 | files: [file] 13 | }); 14 | message.channel.send('Check your dms.'); 15 | return; 16 | } 17 | 18 | /** 19 | * -- Can only be used by staff -- 20 | * Usage: snipe purge [user | *] 21 | * if user is not specified the bot will purge all the logs for that current channel 22 | * if you pass * as user, it will completely dump the logs. 23 | */ 24 | 25 | if (args[0].toLowerCase() == 'purge' && (message.member.roles.cache.get(config.discord.roles.staff) != null || message.member.roles.cache.get(config.discord.roles.botdev) != null)) { 26 | //return console.log('User trying to purge'); 27 | let reason = args.slice(1); 28 | 29 | if (reason.length == 0) { 30 | message.channel.send({ 31 | embeds: [new MessageEmbed().setTitle('Snipe Dump') 32 | .setDescription(` \* -- Can only be used by staff --\n\* Usage: ${config.discord.bot.prefix}snipe purge [user | \*] \n\* if user is not specified the bot will purge all the logs for that current channel\n\* if you pass \* as user, it will completely dump the logs.`) 33 | .setColor('BLUE') 34 | ] 35 | }) 36 | return; 37 | } 38 | let target; 39 | if (reason[0] == '*' || message.guild.members.cache.get((reason[0].match(/[0-9]{18}/) == null ? reason[0] : reason[0].match(/[0-9]{18}/)[0]))) { 40 | target = (!reason[0].match(/[0-9]{18}/) || reason[0].match(/[0-9]{18}/).length == 0) ? reason[0] : reason[0].match(/[0-9]{18}/)[0]; 41 | reason.shift(); 42 | } 43 | 44 | if (reason.length == 0) { 45 | message.channel.send('You are required to provide a reason when purging snipe logs.') 46 | return; 47 | } 48 | let file; 49 | 50 | if (target != '*') { 51 | file = new Discord.MessageAttachment(Buffer.from(JSON.stringify(client.messageSnipes.get(message.channel.id).filter(x => x.member == target)), "utf8"), "Snipe-Logs.json"); 52 | client.messageSnipes.set(message.channel.id, client.messageSnipes.get(message.channel.id).filter(x => x.member != target)); 53 | } else if (message.member.roles.cache.get(config.discord.roles.botdev) != null && message.member.roles.cache.get(config.discord.roles.botdev) != null) { 54 | file = new Discord.MessageAttachment(Buffer.from(JSON.stringify(Array.from(client.messageSnipes)), "utf8"), "Snipe-Logs.json"); 55 | 56 | client.messageSnipes.clear(); 57 | } else { 58 | message.channel.send("You don't have permission to do this."); 59 | return; 60 | } 61 | 62 | client.channels.cache.get(config.discord.channels.snipelogs).send({ 63 | content: `${message.member} purged ${target == '*'? `all messages`: `${target}'s messages in ${message.channel}`} for the reason: ${reason}.`, 64 | files: [file] 65 | }) 66 | message.channel.send('purged.') 67 | return; 68 | } 69 | 70 | } 71 | let embed3 = new MessageEmbed().setDescription(`Theres nothing to snipe`) 72 | 73 | let snipe = client.messageSnipes.get(message.channel.id) 74 | 75 | if (snipe == null) return message.channel.send({ 76 | embeds: [embed3] 77 | }) 78 | let isntNumber = isNaN(args[0]) 79 | if(isntNumber == true) return message.channel.send({embeds: [new MessageEmbed().setDescription(`Please provide a number!`)]}) 80 | 81 | snipe = [...snipe.values()] 82 | 83 | //Reversing the array 84 | snipe.reverse(); 85 | 86 | // getting the number 87 | let number = 0; 88 | 89 | if (args[0] == null) number = 0; 90 | else number = (parseInt(args[0]) - 1); 91 | //setting a min and max 92 | if (number >= snipe.length) number = snipe.length - 1; 93 | if (number < 0) number = 0; 94 | 95 | // getting the message 96 | let snipedMessage = snipe[number]; 97 | 98 | //console.log("SNIPE", snipedMessage, snipe, number); 99 | 100 | //sending the message 101 | const embed = new MessageEmbed() 102 | .setTitle(`Message ${snipedMessage.action} by ${snipedMessage.member.user.tag}`) 103 | .setDescription("`" + snipedMessage.message + "`") 104 | .setFooter(`${number + 1}/${snipe.length}`).setTimestamp(snipedMessage.timestamp) 105 | .setColor("GREEN"); 106 | message.channel.send({ 107 | embeds: [embed] 108 | }); 109 | } 110 | 111 | 112 | module.exports.info = { 113 | name: 'snipe', 114 | description: "Gets the messages that were deleted or edited." 115 | } -------------------------------------------------------------------------------- /src/commands/General/stats.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed }= require('discord.js'); 2 | const moment = require('moment'); 3 | const { mem, cpu, os } = require('node-os-utils'); 4 | const { stripIndent } = require('common-tags'); 5 | module.exports.run = async (client, message, args) => { 6 | const d = moment.duration(message.client.uptime); 7 | const days = (d.days() == 1) ? `${d.days()} day` : `${d.days()} days`; 8 | const hours = (d.hours() == 1) ? `${d.hours()} hour` : `${d.hours()} hours`; 9 | const minutes = (d.hours() == 1) ? `${d.minutes()} minutes` : `${d.minutes()} minutes`; 10 | const seconds = (d.hours() == 1) ? `${d.seconds()} seconds` : `${d.seconds()} seconds`; 11 | const clientStats = stripIndent` 12 | Users :: ${message.client.users.cache.size} 13 | Channels :: ${message.client.channels.cache.size} 14 | Uptime :: ${days}, ${hours} ${minutes}, ${seconds} 15 | `; 16 | const { totalMemMb, usedMemMb } = await mem.info(); 17 | const serverStats = stripIndent` 18 | OS :: ${await os.oos()} 19 | CPU :: ${cpu.model()} 20 | Cores :: ${cpu.count()} 21 | CPU Usage :: ${await cpu.usage()} % 22 | RAM :: ${totalMemMb} MB 23 | RAM Usage :: ${usedMemMb} MB 24 | `; 25 | let now = Date.now() 26 | let msg = await message.channel.send({embeds: [new MessageEmbed().setTitle("Pinging...")]}) 27 | const embed = new MessageEmbed() 28 | .setTitle(`Bot\'s Statistics`) 29 | .addField('Commands fetched', `\`${client.commands.size}\` commands`, true) 30 | .addField(`> 🖥 API Latency:`, `**${client.ws.ping}ms**`, true) 31 | .addField(`> 🤖 Bot Latency:`, `**${Math.round(Date.now() - now)}ms**`, true) 32 | .addField(`Client`, `\`\`\`asciidoc\n${clientStats}\`\`\``) 33 | .addField(`Server`, `\`\`\`asciidoc\n${serverStats}\`\`\``) 34 | .setFooter(message.member.displayName, message.author.displayAvatarURL({ dynamic: true })) 35 | .setTimestamp() 36 | .setColor('#36393F'); 37 | msg.edit({embeds: [embed]}); 38 | }; 39 | module.exports.info = { 40 | name: 'stats', 41 | description: "A stats command that shows detailed information about the bot", 42 | requiredPermission: null, 43 | aliases: ['statistics', 'ping', 'uptime'], 44 | } -------------------------------------------------------------------------------- /src/commands/_ignored/eval.js: -------------------------------------------------------------------------------- 1 | const { DiscordAPIError, MessageEmbed } = require('discord.js'); 2 | const { 3 | inspect 4 | } = require('util'); 5 | module.exports.run = async (client, message, args) => { 6 | if (!args[0]) return messsage.channel.send('what do you want to test?') 7 | const code = args.join(" "); 8 | try { 9 | let evaled = eval(code); 10 | if (typeof evaled !== "string") evaled = require("util").inspect(evaled); 11 | if (evaled.length > 2000) { 12 | console.log(evaled) 13 | const embed = new MessageEmbed() 14 | .setTitle('Evaled') 15 | .addField('Input', '```js\n' + code + '\n```') 16 | .addField(`OutPut`, `Output too long console logged it`) 17 | message.channel.send({ 18 | embeds: [embed] 19 | }) 20 | } else { 21 | const embed = new MessageEmbed() 22 | .setTitle('Evaled') 23 | .addField('Input', '```js\n' + code + '\n```') 24 | .addField(`OutPut`, '```js\n' + evaled + '\n```') 25 | message.channel.send({ 26 | embeds: [embed] 27 | }) 28 | } 29 | } catch (err) { 30 | const embed = new MessageEmbed() 31 | .setTitle('ERROR') 32 | .addField(`Input`, '```js\n' + code + '\n```') 33 | .addField(`OutPut`, '```js\n' + err + '\n```') 34 | message.channel.send({ 35 | embeds: [embed] 36 | }) 37 | } 38 | } 39 | 40 | module.exports.info = { 41 | name: "eval", 42 | description: "eval code.", 43 | requiredPermission: "ADMINISTRATOR", 44 | } -------------------------------------------------------------------------------- /src/commands/_ignored/pull.js: -------------------------------------------------------------------------------- 1 | const exec = require('child_process').exec; 2 | module.exports.run = async (client, message, args) => { 3 | e = await message.channel.send('Pulling from github....'); 4 | exec(`git pull`, (error, stdout) => { 5 | let response = (error || stdout); 6 | if (!error) { 7 | if (response.includes("Already up to date.")) { 8 | e.edit(`Bot is already up to date`) 9 | } else { 10 | e.edit(`Pulled From github\n\n\`\`\`js\n${response}\n\`\`\`\n\nRunning \`npm i\``) 11 | exec(`npm i`, (error, stdout) => { 12 | let response = (error || stdout); 13 | e.edit(`**NPM I Response**\n\n\`\`\`js${response}\`\`\``) 14 | }) 15 | } 16 | } 17 | }) 18 | } 19 | 20 | /** 21 | * This is completely optional... 22 | */ 23 | 24 | module.exports.info = { 25 | name: 'pull', 26 | description: "", 27 | requiredPermission: "ADMINISTRATOR", 28 | aliases: ['git-pull'], 29 | usage: '' 30 | } -------------------------------------------------------------------------------- /src/commands/_ignored/restart.js: -------------------------------------------------------------------------------- 1 | module.exports.run = async (client, message, args) => { 2 | message.channel.send(`Restarting bot, New changes will take effect after restart`) 3 | setTimeout(() => { 4 | process.exit(); 5 | }, 1000) 6 | } 7 | 8 | module.exports.info = { 9 | name: 'restart', 10 | description: "", 11 | requiredPermission: "ADMINISTRATOR", 12 | aliases: [], 13 | usage: '' 14 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/ban.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js') 2 | const config = require("../../../config.json") 3 | module.exports.run = async (client, message, args) => { 4 | 5 | let user = message.mentions.users.first() 6 | let member = message.mentions.members.first() 7 | 8 | if(!user) return message.channel.send(`🚧 | You didnt mention anyone.`) 9 | if(member === message.member) return message.channel.send('🚧 | You cant ban yourself.') 10 | 11 | let HighRole = message.member.roles.highest.position; 12 | let getHighRole = member.roles.highest.position; 13 | 14 | if (HighRole < getHighRole) return message.channel.send(`🚧 | You cant use this command on users that have bigger role than yours.`) 15 | if (HighRole === getHighRole) return message.channel.send(`🚧 | You cant use this command on users that have same role as you.`) 16 | 17 | let reason = args.splice(1).join(' ') || `${message.author.tag} Banned with No reason.` 18 | 19 | message.guild.members.ban(user, {reason}) 20 | 21 | .catch((error) => { 22 | message.channel.send(`\`\`\`js\n${error}\`\`\``) 23 | }) 24 | 25 | } 26 | 27 | module.exports.info = { 28 | name: 'ban', 29 | description: "Bans a member.", 30 | requiredPermission: "BAN_MEMBERS" 31 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/forceunlink.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require('discord.js') 2 | const userdb = require('../../../database/schemas/UserData') 3 | const config = require('../../../config.json') 4 | module.exports.run = async (client, message, args) => { 5 | try { 6 | if (!args[0]) return message.reply('Who are you unlinking') 7 | e = await message.channel.send(`Fetching users Data...`) 8 | setTimeout(() => { 9 | message.guild.members.fetch() 10 | }, 5000) 11 | const person = message.mentions.users.first() || await message.guild.members.cache.get(args[0]); 12 | if (!person) return e.edit('User doesn\'t exist ') 13 | const userData = await userdb.findOneAndDelete({ 14 | userID: person.id 15 | }); 16 | if (!userData) return e.edit('<@' + person + '> Doesn\'t have a account or Isn\'t linked') 17 | const embed = new MessageEmbed() 18 | .setTitle(`${person.username || person.user.username}` + "'s Data") 19 | .addField('UserID', `${userData.get('userID')}`) 20 | .addField('Console ID', `${userData.get('consoleID')}`) 21 | .addField('Email', `${userData.get('email')}`) 22 | .addField('Username', `${userData.get('username')}`) 23 | .addField('Creation Date', `${userData.get('createdTimestamp').toLocaleString()}`) 24 | .setColor('BLURPLE') 25 | message.author.send({ 26 | embeds: [embed] 27 | }) 28 | message.channel.send('User Data Deleted, Sent a Dm with their data') 29 | } catch (err) { 30 | console.log(err) 31 | } 32 | } 33 | 34 | 35 | module.exports.info = { 36 | name: "forceunlink", 37 | description: "Unlinks a User", 38 | requiredPermission: "ADMINISTRATOR", 39 | requiredRole: config.discord.roles.botdev, 40 | aliases: [] 41 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/kick.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js') 2 | const config = require("../../../config.json") 3 | module.exports.run = async (client, message, args) => { 4 | 5 | let user = message.mentions.users.first() 6 | let member = message.mentions.members.first() 7 | 8 | if(!user) return message.channel.send(`🚧 | You didnt mention anyone.`) 9 | if(member === message.member) return message.channel.send('🚧 | You cant Kick yourself.') 10 | 11 | let HighRole = message.member.roles.highest.position; 12 | let getHighRole = member.roles.highest.position; 13 | 14 | if (HighRole < getHighRole) return message.channel.send(`🚧 | You cant use this command on users that have bigger role than yours.`) 15 | if (HighRole === getHighRole) return message.channel.send(`🚧 | You cant use this command on users that have same role as you.`) 16 | if(user == client.user) return message.channe 17 | let reason = args.splice(1).join(' ') || `${message.author.tag} Kicked with No reason.` 18 | 19 | message.guild.members.kick(user, {reason}) 20 | 21 | .then(() => { 22 | 23 | message.channel.send(`✅ | Succesfully kicked user **${user.tag}**.`) 24 | 25 | const embed = new Discord.MessageEmbed() 26 | .setAuthor(`${client.user.username} | Kick`, client.user.avatarURL() || "https://cdn.discordapp.com/embed/avatars/0.png") 27 | .addField(`✅ | Kick`, `> Moderator: **${message.author.tag}**\n> User Kicked: **${user.tag}**\n> Reason: **${reason || 'None'}**`) 28 | .setThumbnail(`${message.guild.iconURL({ dynamic:true }) || "https://cdn.discordapp.com/embed/avatars/0.png"}`) 29 | .setColor(message.guild.me.displayHexColor) 30 | .setTimestamp() 31 | client.channels.cache.get(config.discord.channels.modLogs).send({embeds: [embed]}) 32 | }) 33 | 34 | .catch((error) => { 35 | message.channel.send(`\`\`\`js\n${error}\`\`\``) 36 | }) 37 | } 38 | 39 | module.exports.info = { 40 | name: 'kick', 41 | description: "Kick someone from the server.", 42 | requiredPermission: 'KICK_MEMBERS', 43 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/purge.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js') 2 | const config = require("../../../config.json") 3 | module.exports.run = async (client, message, args) => { 4 | 5 | if(!message.member.roles.cache.find(r => r.id === config.DiscordRoles.staff)) { 6 | return message.channel.send(`🚧 | You **do not** have enough **permissions** to use this **command**.`) 7 | } 8 | 9 | let prefix = config.prefix 10 | 11 | const embed = new Discord.MessageEmbed() 12 | .setAuthor(`${client.user.username} | Purge`, client.user.avatarURL()) 13 | .addField(`❓ | Usage:`, `> ${prefix}purge <@someone> `) 14 | .addField(`💡 | Example:`, `> ${prefix}purge 20 @mqrkelich`) 15 | .setColor(message.guild.me.displayHexColor) 16 | .setTimestamp() 17 | 18 | if(!args[0]) return message.channel.send({embeds: [embed]}) 19 | 20 | let user = message.mentions.users.first() 21 | let amount = !!parseInt(message.content.split(' ')[2]) ? parseInt(message.content.split(' ')[2]) : parseInt(message.content.split(' ')[1]) 22 | 23 | if (!amount) return message.channel.send({embeds: [embed]}) 24 | if(isNaN(amount)) return message.channel.send({embeds: [embed]}) 25 | if (!amount && !user) return message.channel.send({embeds: [embed]}) 26 | 27 | if (amount < 1 || amount > 99) return message.channel.send(`💡 | Specify a **number** between **1-99** to delete.`) 28 | 29 | message.channel.messages.fetch({ limit: amount }).then(messages => { 30 | 31 | if (user) { 32 | const filterBy = user ? user.id : client.user.id; 33 | messages = messages.filter(m => m.author.id === filterBy).array().slice(0, amount + 1); 34 | } 35 | 36 | message.channel.bulkDelete(messages, true).catch(error => { return message.channel.send(`\`\`\`js\n${error}\`\`\``)}); 37 | message.channel.send(`✅ | Succesfully purged **${amount}** messages.`) 38 | 39 | const success = new Discord.MessageEmbed() 40 | .setAuthor(`${client.user.username} | Purge`, client.user.avatarURL()) 41 | .addField(`💡 | Info:`, `> Moderator: **${message.author.tag}**\n> Amount: **${amount}**\n> Channel: ${message.channel}`) 42 | .setThumbnail('https://cdn.discordapp.com/emojis/860696522659463199.png?v=1') 43 | .setColor(message.guild.me.displayHexColor) 44 | .setTimestamp() 45 | return client.channels.cache.get(config.DiscordBot.modLogs).send({ embeds: [success] }); 46 | }) 47 | } 48 | 49 | module.exports.info = { 50 | name: 'purge', 51 | description: "Clears a number of amount messages.", 52 | aliases: ['clear'], 53 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/staff.js: -------------------------------------------------------------------------------- 1 | module.exports.info = { 2 | name: "staff", 3 | description: "staff commands.", 4 | aliases: [] 5 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/unban.js: -------------------------------------------------------------------------------- 1 | const Discord = require('discord.js') 2 | const config = require("../../../config.json") 3 | module.exports.run = async (client, message, args) => { 4 | 5 | if(!args[0]) return message.channel.send(`🚧 | Specify **ID** of the **user** you want to **unban**.`) 6 | 7 | if(message.mentions.users.first()) return message.channel.send(`🚧 | Use ID's to unban people.`) 8 | 9 | let member = await client.users.fetch(args[0]) 10 | 11 | message.guild.bans.fetch().then(bans => { 12 | 13 | const user = bans.find(ban => ban.user.id === member.id); 14 | 15 | if(!user) return message.channel.send('🚧 | That user is not banned.') 16 | 17 | let reason = args.slice(1).join(" "); 18 | 19 | if (user) { 20 | 21 | message.guild.members.unban(member).then(() => { 22 | 23 | message.channel.send(`✅ | Succesfully unbanned user **${member.tag}**.`) 24 | 25 | const embed = new Discord.MessageEmbed() 26 | .setAuthor(`${client.user.username} | Unban`, client.user.avatarURL()) 27 | .addField(`✅ | Unban`, `> Moderator: **${message.author.tag}**\n> User Unbanned: **${member.tag}**\n> Reason: **${reason || 'None'}**`) 28 | .setThumbnail(`${message.guild.iconURL({ dynamic:true })}`) 29 | .setColor(message.guild.me.displayHexColor) 30 | .setTimestamp() 31 | client.channels.cache.get(config.DiscordChannels.modLogs).send({embeds: [embed]}) 32 | 33 | }).catch((error) => { message.channel.send(`\`\`\`js\n${error}\`\`\``) }) 34 | } 35 | }) 36 | } 37 | 38 | module.exports.info = { 39 | name: 'unban', 40 | description: "Unbans a user thats banned from server.", 41 | requiredPermission: "BAN_MEMBERS" 42 | } -------------------------------------------------------------------------------- /src/commands/_ignored/staff/userinfo.js: -------------------------------------------------------------------------------- 1 | const { MessageEmbed } = require('discord.js'); 2 | const userdb = require('../../../database/schemas/UserData') 3 | 4 | module.exports.run = async (client, message, args) => { 5 | try { 6 | if (!args[0]) return message.reply('Who are you checking for user Data?') 7 | e = await message.channel.send(`Fetching users Data...`) 8 | setTimeout(() => { 9 | message.guild.members.fetch() 10 | }, 5000) 11 | const person = message.mentions.users.first() || await message.guild.members.cache.get(args[0]); 12 | const userData = await userdb.findOne({ 13 | userID: person.id 14 | }); 15 | if (!userData) return e.edit('You or the person you mentioned doesn\'t have any Data. Do they have a account?'); 16 | const embed = new MessageEmbed() 17 | .setTitle(`${person.username || person.user.username}` + "'s Data") 18 | .addField('UserID', `${userData.get('userID')}`) 19 | .addField('Console ID', `${userData.get('consoleID')}`) 20 | .addField('Email', `${userData.get('email')}`) 21 | .addField('Username', `${userData.get('username')}`) 22 | .addField('Creation Date', `${userData.get('createdTimestamp').toLocaleString()}`) 23 | .setColor('BLURPLE') 24 | message.author.send({ 25 | embeds: [embed] 26 | }) 27 | e.edit(`Fetched ${person.username || person.user.username}'s Data, Sent a Dm with info`) 28 | } catch (err) { 29 | console.log(err) 30 | } 31 | } 32 | 33 | module.exports.info = { 34 | name: "userinfo", 35 | description: "Get Info about a user", 36 | requiredPermission: "ADMINISTRATOR", 37 | aliases: ['ui'] 38 | } -------------------------------------------------------------------------------- /src/database/schemas/Domains.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const DomainsSchema = new mongoose.Schema({ 4 | 5 | // User's discord ID 6 | userID: { 7 | type: mongoose.SchemaTypes.String, 8 | required: true 9 | }, 10 | 11 | // Domain 12 | domain: { 13 | type: mongoose.SchemaTypes.String, 14 | required: true, 15 | unique: true 16 | } 17 | }); 18 | 19 | module.exports = mongoose.model("Domains", DomainsSchema); -------------------------------------------------------------------------------- /src/database/schemas/UserData.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const reqString = { 4 | type: mongoose.SchemaTypes.String, 5 | required: true 6 | } 7 | 8 | const UserDataSchema = new mongoose.Schema({ 9 | // User's discord ID 10 | userID: reqString, 11 | 12 | // User's console ID 13 | consoleID: reqString, 14 | 15 | // User's console email 16 | email: reqString, 17 | 18 | // User's console username 19 | username: reqString, 20 | 21 | // Timestamp when the accounts was created 22 | createdTimestamp: { 23 | type: mongoose.SchemaTypes.Date, 24 | required: true 25 | }, 26 | }) 27 | 28 | module.exports = mongoose.model('UserData', UserDataSchema); -------------------------------------------------------------------------------- /src/database/schemas/UserPrem.js: -------------------------------------------------------------------------------- 1 | const mongoose = require('mongoose'); 2 | 3 | const reqString = { 4 | type: mongoose.SchemaTypes.String, 5 | required: true 6 | } 7 | 8 | const UserPremSchema = new mongoose.Schema({ 9 | // User's discord ID 10 | consoleID: reqString, 11 | 12 | // The amount of servers the user can make 13 | amount: reqString, 14 | 15 | // The amount they have used 16 | used: reqString, 17 | }) 18 | module.exports = mongoose.model('UserPrem', UserPremSchema); -------------------------------------------------------------------------------- /src/events/guildBanAdd.js: -------------------------------------------------------------------------------- 1 | const { client } = require('../index.js') 2 | const config = require('../config.json'); 3 | const { MessageEmbed } = require('discord.js'); 4 | 5 | client.on('guildBanAdd', async (ban) => { 6 | setTimeout(async() => { 7 | let guild = ban.guild; 8 | let user = ban.user; 9 | const fetchedLogs = await guild.fetchAuditLogs({ 10 | limit: 10, 11 | type: 'MEMBER_BAN_ADD', 12 | }); 13 | const banLog = fetchedLogs.entries.first(); 14 | 15 | if (!banLog) return client.channels.cache.get(config.discord.channels.modLogs).send({content: `The Audit logs Didn't show anything about the ban.`}) 16 | 17 | const { executor, target, reason } = banLog; 18 | if (target.id === user.id) { 19 | let r = reason 20 | let e = ' ' 21 | if(r === null) e = `${executor} You didn't add a reason, Please provide proof and a reason in the proof channel` 22 | if(r === null) r = "**There was No reason**" 23 | const embed = new MessageEmbed() 24 | .setTitle('New Ban!') 25 | .addField("User Banned:", `${user.tag} (${user.id})`) 26 | .addField("Banned By:", `${executor} (${executor.id})`) 27 | .addField("Reason", r.toString()) 28 | .setColor("ORANGE") 29 | .setTimestamp() 30 | client.channels.cache.get(config.discord.channels.modLogs).send({content: `${e}`, embeds:[embed]}) 31 | } 32 | }, 1000); 33 | }); -------------------------------------------------------------------------------- /src/events/messageCreate.js: -------------------------------------------------------------------------------- 1 | const { findCommand } = require("../utils/commandHandler"); 2 | const { MessageEmbed } = require("discord.js"); 3 | const config = require("../config.json"); 4 | const { client } = require("../index"); 5 | const chalk = require("chalk"); 6 | 7 | client.on('messageCreate', async (message) => { 8 | if(message.channel.type == "DM") { 9 | if(message.author.bot) return 10 | const embed = new MessageEmbed() 11 | .setTitle(`New DM From ${message.author.tag}`) 12 | .setDescription(message.content.toString()) 13 | .setColor("GREEN") 14 | .setFooter(`${message.author.id}`) 15 | .setTimestamp() 16 | return client.channels.cache.get(config.discord.channels.modLogs).send({embeds:[embed]}) 17 | } 18 | if (message.channel.type == "DM" || message.author.bot 19 | || message.guild.id != config.discord.guild || !message.content.startsWith(config.discord.bot.prefix)) return; 20 | if(message.content.startsWith(config.discord.bot.prefix + 'prefix')) { 21 | return message.react('✅') 22 | } 23 | let args = message.content.trim().slice(config.discord.bot.prefix.length).split(/ +/); 24 | 25 | let cmd = findCommand([...args], client.commands, message); 26 | 27 | if (cmd) { 28 | let commandTree = args.slice(0, cmd.depth); 29 | args = args.slice(cmd.depth); 30 | 31 | if (!cmd.subCommands) { 32 | try { 33 | cmd.run(client, message, args, commandTree); 34 | } catch (error) { 35 | console.log(chalk.bgRedBright("[ERROR]"), `An error occured while trying to execute the ${cmd.name} command!`); 36 | console.log(error); 37 | }; 38 | } else { 39 | message.channel.send({ 40 | embeds: [ 41 | new MessageEmbed() 42 | .setTitle(commandTree.join(" ") + "'s subcommands") 43 | .setColor("PURPLE") 44 | .setDescription(cmd.subCommands.map(x => `**${x.name}** - \`${x.description}\`\n*usage:* \`${x.usage}\``).join('\n\n')) 45 | .setFooter(`Executed by ${message.author.tag}`) 46 | .setTimestamp() 47 | ] 48 | }); 49 | 50 | }; 51 | 52 | }; 53 | }); -------------------------------------------------------------------------------- /src/events/messageDelete.js: -------------------------------------------------------------------------------- 1 | const { client } = require("../index"); 2 | const chalk = require("chalk"); 3 | const { MessageEmbed } = require('discord.js') 4 | const config = require('../config.json') 5 | client.on('messageDelete', async (message) => { 6 | if (message.author == null || message.author.bot == true) return; 7 | let logChannel = client.channels.cache.get(config.discord.channels.mLogs); 8 | 9 | if (!message.content != 0 && logChannel) { 10 | 11 | if (message.author.bot) return; 12 | if (message.channel.type === 'dm') return; 13 | if (message.channel.type !== 'GUILD_TEXT') return; 14 | if (message.author == null) return; 15 | 16 | const description = message.cleanContent || "message had no content" 17 | const descriptionfix = description.substr(0, 600); 18 | const embed = new MessageEmbed() 19 | .setColor('RANDOM') 20 | .setThumbnail(message.author.avatarURL) 21 | .addField("Author ", `${message.author.tag} (ID: ${message.author.id})`) 22 | .addField("Message Content:", `${descriptionfix}`) 23 | .setTimestamp() 24 | .setFooter("Message delete in " + message.channel.name); 25 | logChannel.send({ embeds: [embed] }); 26 | 27 | } 28 | if (message.author.bot || !message.content) return; 29 | 30 | let data = { 31 | message: message.content, 32 | member: message.member, 33 | timestamp: Date.now(), 34 | action: "delete" 35 | }; 36 | if (client.messageSnipes.get(message.channel.id) == null) client.messageSnipes.set(message.channel.id, [data]) 37 | else client.messageSnipes.set(message.channel.id, [...client.messageSnipes.get(message.channel.id), data]); 38 | 39 | client.messageSnipes.set(message.channel.id, client.messageSnipes.get(message.channel.id).filter(x => (Date.now() - x.timestamp) < 300000 && x != null)); 40 | }); -------------------------------------------------------------------------------- /src/events/messageUpdate.js: -------------------------------------------------------------------------------- 1 | const { client } = require("../index"); 2 | const config = require('../config.json') 3 | client.on('messageUpdate', async (oldMessage, newMessage) => { 4 | if (oldMessage.author == null || oldMessage.author.bot == true || !oldMessage.content || newMessage == null) return; 5 | 6 | let data = { 7 | message: oldMessage.content, 8 | member: oldMessage.member, 9 | timestamp: Date.now(), 10 | action: "edit" 11 | }; 12 | 13 | if (client.messageSnipes.get(oldMessage.channel.id) == null) client.messageSnipes.set(oldMessage.channel.id, [data]) 14 | else client.messageSnipes.set(oldMessage.channel.id, [...client.messageSnipes.get(oldMessage.channel.id), data]); 15 | 16 | client.messageSnipes.set(oldMessage.channel.id, client.messageSnipes.get(oldMessage.channel.id).filter(x => (Date.now() - x.timestamp) < 300000 && x != null)); 17 | }) -------------------------------------------------------------------------------- /src/events/ready.js: -------------------------------------------------------------------------------- 1 | const config = require("../config.json"); 2 | const { client, updateCache } = require("../index"); 3 | const mongo = require("../utils/mongo"); 4 | const chalk = require("chalk"); 5 | 6 | client.on('ready', async () => { 7 | const guild = client.guilds.cache.get(config.discord.guild); 8 | guild.members.fetch() 9 | console.log(`${chalk.greenBright("[BOT]")} Bot ready and logged in as ${client.user.tag}`); 10 | console.log(`${chalk.greenBright("[BOT]")} Cached All members in ${guild.name}`) 11 | await mongo().then(() => console.log(chalk.green("[DATABASE]") + " Connected to database successfully!")) 12 | .catch(e => console.error(chalk.bgRedBright("[ERROR]"), `An error has occured when attempting to connect to mongo. (${e.message})`)); 13 | 14 | 15 | await updateCache() 16 | .catch(e => console.error(chalk.bgRedBright("[ERROR]"), `An error has occured when fetching nodes. (${e.message})`)) 17 | 18 | setInterval(async () => await updateCache().catch(e => console.error(chalk.bgRedBright("[ERROR]"), `An error has occured when fetching nodes. (${e.message})`)), 60 * 60 * 1000) 19 | }); 20 | 21 | -------------------------------------------------------------------------------- /src/example-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "externalPassword": "This should be the same password as the one thats in the daemon config.json (This is how they talk together)", 3 | "mongoPath": "The mongodb server connection url", 4 | "premiumprice": "The price for getting premium servers", 5 | "donationlink": "The link to buy premium servers", 6 | "pterodactyl": { 7 | "hosturl": "Your pterodactyl panel. dont forget the https", 8 | "apikey": "your admin api key", 9 | "apikeyclient": "your client api key" 10 | }, 11 | "discord": { 12 | "guild": "Main Guild ID", 13 | "bot": { 14 | "prefix": "Bots Prefix", 15 | "missing_permission": "You require the `{PERMISSION}` permission to use this command.", 16 | "clientID": "Bot client ID", 17 | "clientSecret": "Bot client secret", 18 | "callbackURL": "callback url after logging into the site. should end with /api/callback", 19 | "ownerID": "Owner ID (For owner only commands)", 20 | "missing_role": "You require the `{ROLE}` role to use this command" 21 | }, 22 | "channels": { 23 | "ticketVC": "Vc Channel ID Lists the number of tickets", 24 | "botsVC": "Vc or channel ID Shows how many bots are in the server", 25 | "totalMembersVC": "Vc or Channel ID to show how many members In total there are", 26 | "membersVC": "VC or Channel ID To show how many Humans there are", 27 | "staffVC": "Vc or Channel ID how many staff are in the server", 28 | "serversVC": "Vc or Channel ID It shows how many servers are being ran on the host", 29 | "clientsVC": "Vc or Channel ID it shows how many people are registed to the host", 30 | "boostsVC": "Vc or Channel ID shows how many people have boosted the server", 31 | "mLogs": "Message logs channel ID", 32 | "oLogs": "Other logs channel ID", 33 | "modLogs": "Mod logs channel ID", 34 | "requestsChannel": "Channel that request are in. This isnt used yet but will be soon", 35 | "welcome": "Welcome channel ID", 36 | "invitechannel": "Invite logs channel ID", 37 | "inviterewmsg": "Invite reward message channel ID", 38 | "snipelogs": "Channel to log snipe purges" 39 | }, 40 | "tickets": { 41 | "enabled": true, 42 | "other": "Category for other support", 43 | "report": "Category for reporting Bugs or users", 44 | "serverissues": "Category for Issues with the users server", 45 | "accountissues": "Category for Issues with the users account", 46 | "donations": "Category for when a user donates", 47 | "accountCreation": "The category ID in which the channels to create user accounts will be made" 48 | }, 49 | "roles": { 50 | "member": "Member role ID", 51 | "client": "Client role ID", 52 | "bot": "Bot role ID", 53 | "staff": "Staff role ID (Used for staff commands)", 54 | "mute": "Muted role ID", 55 | "botdev": "Bot Dev role ID", 56 | "helper": "Helper role ID", 57 | "mod": "mod role ID", 58 | "admin": "admin role ID", 59 | "invites": { 60 | "5": "5+ invites role ID", 61 | "10": "10+ invites role ID", 62 | "25": "25+ invites role ID", 63 | "50": "50+ invites role ID", 64 | "100": "100+ invites role ID", 65 | "150": "150+ invites role ID", 66 | "200": "200+ invites role ID" 67 | } 68 | } 69 | }, 70 | "email": { 71 | "enabled": false, 72 | "verbose": true, 73 | "host": "SMTP url", 74 | "port": "587", 75 | "user": "SMTP Username", 76 | "password": "SMTP password", 77 | "from": "Email sent from" 78 | }, 79 | "ssh": { 80 | "host": "Reverse proxy IP", 81 | "user": "root", 82 | "password": "Reverse proxy root password", 83 | "port": 22 84 | }, 85 | "ports": { 86 | "webPort": 1144, 87 | "APIPort": 1145 88 | } 89 | } -------------------------------------------------------------------------------- /src/example.env: -------------------------------------------------------------------------------- 1 | Token= -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | 2 | const chalk = require('chalk'); 3 | const fs = require('fs'); 4 | const { loadCommands } = require('./utils/commandHandler'); 5 | const config = require("./config.json"); // Edit example-config.json 6 | require("dotenv").config(); 7 | const Discord = require("discord.js"); 8 | const panel = require('./wrapper/index').Application; 9 | const cache = require('./utils/Cache'); 10 | 11 | panel.login(config.pterodactyl.hosturl, config.pterodactyl.apikey); 12 | 13 | const client = new Discord.Client({ 14 | //I've removed any intents that seemd useless, Add them as you need 15 | intents: ["GUILDS", "GUILD_MESSAGES", "GUILD_VOICE_STATES", "GUILD_MESSAGE_REACTIONS", "GUILD_MEMBERS", "GUILD_BANS", "GUILD_INVITES", "DIRECT_MESSAGES"], 16 | //The bot can only ping users, This way if someone founds a exploit it can't ping that many users 17 | allowedMentions: { 18 | parse: ['users'], 19 | repliedUser: true 20 | }, 21 | partials: ['MESSAGE', 'CHANNEL', 'REACTION'] 22 | }); 23 | client.messageSnipes = new Discord.Collection(); 24 | 25 | exports.client = client; 26 | global.ROOT_PATH = __dirname; 27 | exports.panel = panel; 28 | 29 | const { parse, fetchNodes } = require('./utils/fetchNodes') 30 | 31 | const updateCache = async () => { 32 | var today = new Date(); 33 | const { botNodes, gamingNodes, storageNodes } = parse(await fetchNodes()); 34 | 35 | cache.set('botNodeIds', botNodes); 36 | cache.set('gamingNodeIds', gamingNodes); 37 | cache.set('storageNodeIds', storageNodes); 38 | 39 | console.log(chalk.green("[CACHE]"), "Updated Cache! Time: " + today.getHours() + ":" + today.getMinutes()) 40 | }; 41 | 42 | exports.updateCache = updateCache; 43 | 44 | // Event Handler 45 | let events = fs.readdirSync(ROOT_PATH + '/events').filter(x => x.endsWith(".js")); 46 | events.forEach(x => { 47 | try { 48 | require('./events/' + x); 49 | } catch (error) { 50 | console.log(chalk.bgRedBright("[ERROR]"), `An error occured while trying to load the ${x} event ` + error.stack); 51 | }; 52 | }); 53 | 54 | loadCommands(`${ROOT_PATH}/commands`).then(x => { 55 | // console.log(x); 56 | fs.writeFileSync(ROOT_PATH + '/log.json', JSON.stringify(x.logs, null, 2)); 57 | client.commands = x.commandsCol; 58 | 59 | if (x.logs.stats.errors != 0) 60 | console.log(chalk.bgRedBright("[ERROR]"), `An error occured while loading commands, please check`, chalk.bgWhite("log.json"), `for more information.`); 61 | 62 | console.log(chalk.bgCyan("[CommandHandler]"), `Loaded a total of ${x.logs.stats.commands} commands in ${x.logs.stats.categories} categories.`); 63 | }); 64 | 65 | client.login(process.env.Token); // Login to Discord 66 | -------------------------------------------------------------------------------- /src/utils/Cache.js: -------------------------------------------------------------------------------- 1 | const cache = new Map() 2 | 3 | module.exports = { 4 | has(key) { 5 | return cache.has(key) 6 | }, 7 | 8 | set(key, value) { 9 | return cache.set(key, [value, Date.now()]) 10 | }, 11 | 12 | get(key) { 13 | return cache.get(key)[0] 14 | }, 15 | 16 | delete(key) { 17 | return cache.delete(key) 18 | }, 19 | 20 | clear() { 21 | return cache.clear() 22 | }, 23 | 24 | isExpired(key, seconds) { 25 | const [_, timestamp] = cache.get(key) 26 | 27 | return (Date.now() - timestamp) / 1000 > seconds 28 | }, 29 | } -------------------------------------------------------------------------------- /src/utils/Email.js: -------------------------------------------------------------------------------- 1 | const { JSDOM } = require("jsdom"); 2 | const fs = require('fs'); 3 | const marked = require('marked'); 4 | 5 | class Email { 6 | 7 | #send = fs.readFileSync(global.ROOT_PATH + "/utils/libs/emailTemplate.html", "utf8") 8 | #DOM = new JSDOM(this.#send); 9 | #document = this.#DOM.window.document; 10 | 11 | constructor() { } 12 | 13 | setTitle(string = "") { 14 | let element = this.#document.getElementById("title"); 15 | 16 | element.innerHTML = marked(string); 17 | return this; 18 | } 19 | 20 | setSignature(string = "") { 21 | let element = this.#document.getElementById("signature"); 22 | 23 | element.innerHTML = marked(string); 24 | return this; 25 | } 26 | 27 | setSubText(string = "") { 28 | let element = this.#document.getElementById("subText"); 29 | 30 | element.innerHTML = marked(string); 31 | return this; 32 | } 33 | 34 | setHeader(string = "") { 35 | let element = this.#document.getElementById("header"); 36 | 37 | element.innerHTML = marked(string); 38 | return this; 39 | } 40 | 41 | setMessage(string = "") { 42 | let element = this.#document.getElementById("message"); 43 | 44 | element.innerHTML = marked(string); 45 | return this; 46 | } 47 | 48 | setFooter(string = "") { 49 | let element = this.#document.getElementById("footer"); 50 | 51 | element.innerHTML = marked(string); 52 | return this; 53 | } 54 | 55 | get() { 56 | return this.#DOM 57 | } 58 | 59 | } 60 | 61 | module.exports = Email; 62 | -------------------------------------------------------------------------------- /src/utils/Transporter.js: -------------------------------------------------------------------------------- 1 | const nodemailer = require('nodemailer'); 2 | const config = require('../config.json'); 3 | const chalk = require('chalk'); 4 | 5 | class Transporter { 6 | 7 | /** 8 | * @param {object} emailData 9 | * @param {string} emailData.from 10 | * @param {string} emailData.to 11 | * @param {string} emailData.subject 12 | * @param {string?} emailData.text 13 | * @param {string?} emailData.html 14 | */ 15 | constructor(emailData) { 16 | this.transporter = nodemailer.createTransport({ 17 | host: config.email.host, 18 | port: config.email.port, 19 | auth: { 20 | user: config.email.user, 21 | pass: config.email.password 22 | } 23 | }); 24 | this.email = emailData || { from: config.email.from }; 25 | } 26 | 27 | setSender = (sender) => { this.email.from = sender; return this; } 28 | 29 | setReceiver = (receiver) => { this.email.to = receiver; return this; } 30 | 31 | setSubject = (subject) => { this.email.subject = subject; return this; } 32 | 33 | setText = (txt) => { this.email.text = txt; return this; } 34 | 35 | setHTML = (html) => { this.email.html = html; return this; } 36 | 37 | send = async () => { 38 | 39 | if (this.email.to == null) throw new Error("EmailReceiver can't be null."); 40 | if (this.email.subject == null) throw new Error("EmailSubject can't be null."); 41 | if (this.email.text == null && this.email.html == null) throw new Error("EmailContent can't be null."); 42 | 43 | if (config.email.verbose) console.log(chalk.blueBright("[Email]"), `Email sent to ${this.email.to} (${this.email.subject})`); 44 | 45 | return await this.transporter.sendMail(this.email); 46 | }; 47 | } 48 | 49 | module.exports = Transporter; 50 | -------------------------------------------------------------------------------- /src/utils/commandHandler.js: -------------------------------------------------------------------------------- 1 | const { Collection, Permissions } = require('discord.js'); 2 | const config = require('../config.json'); 3 | const fs = require('fs'); 4 | let log = { 5 | categories: [], 6 | errors: [], 7 | stats: { 8 | categories: 0, 9 | commands: 0, 10 | subCommands: 0, 11 | errors: 0 12 | } 13 | }; 14 | 15 | let merge = (x, y) => { 16 | for (const [key, value] of Object.entries(y)) { 17 | if(value == null) continue; 18 | x[key] = value; 19 | }; 20 | return x; 21 | }; 22 | 23 | let checkForDuplicate = (current, commands, includePath = false) => { 24 | let duplicate = commands.find(x => x.name == current.name || 25 | x.aliases.includes(current.name) || 26 | current.aliases.includes(x.name) || 27 | current.aliases.some(y => x.aliases.includes(y))) || null; 28 | 29 | let toReturn = { 30 | status: duplicate != null, 31 | file: (current.mainCommand != null ? current.mainCommand + "/" : "") + current.file, 32 | in: duplicate != null ? (duplicate.mainCommand != null ? duplicate.mainCommand + "/" : "") + duplicate.file : null, 33 | duplicate: [] 34 | }; 35 | 36 | if (duplicate != null) { 37 | 38 | if (includePath != null) { 39 | current.file = current.path + '/' + current.file; 40 | duplicate.file = duplicate.path + '/' + duplicate.file; 41 | }; 42 | 43 | if (current.name == duplicate.name) { 44 | toReturn.duplicate.push(`${current.file} shares the same name variable with ${duplicate.file}`); 45 | }; 46 | 47 | if (duplicate.aliases.includes(current.name)) { 48 | toReturn.duplicate.push(`${current.file}'s name was found is ${duplicate.file}'s aliases`); 49 | }; 50 | 51 | if (current.aliases.includes(duplicate.name)) { 52 | toReturn.duplicate.push(`${duplicate.file}'s name was found is ${current.file}'s aliases`); 53 | }; 54 | 55 | for (const alias of current.aliases.filter(y => duplicate.aliases.includes(y))) { 56 | toReturn.duplicate.push(`${current.file} and ${duplicate.file} both have the same alias ("${alias}")`); 57 | }; 58 | }; 59 | 60 | return toReturn; 61 | }; 62 | 63 | 64 | let checkPermission = (permission) => { 65 | return Object.keys(Permissions.FLAGS).includes(permission); 66 | }; 67 | 68 | let defaultCommands = { 69 | categories: [], 70 | errors: [], 71 | stats: { 72 | categories: 0, 73 | commands: 0, 74 | subCommands: 0, 75 | errors: 0, 76 | time: 0 77 | } 78 | }; 79 | 80 | let findCommand = (list, commandsList, message) => { 81 | let cmd; 82 | let args = [...list]; 83 | while (list.length > 0 && (cmd != null || args.length == list.length)) { 84 | let command = list.shift().toLowerCase(); 85 | let temp; 86 | 87 | if (cmd == null) temp = commandsList.find(x => x.name == command || x.aliases.includes(command)); 88 | else if (cmd != null && cmd.subCommands != null) temp = cmd.subCommands.find(x => x.name == command || x.aliases.includes(command)); 89 | 90 | if (message != null) { 91 | if (temp != null && temp.requiredRole != null && !message.member.roles.cache.find(r => r.id === temp.requiredRole)) { // role check 92 | let rname = message.guild.roles.cache.find(r => r.id === temp.requiredRole) 93 | message.channel.send({ content: config.discord.bot.missing_role.replace("{ROLE}", rname.name) }); // Missing role message 94 | return; 95 | }; 96 | if (temp != null && temp.requiredPermission != null && !message.member.permissions.has(temp.requiredPermission)) { // Permission check 97 | message.channel.send({ content: config.discord.bot.missing_permission.replace("{PERMISSION}", temp.requiredPermission) }); // Missing Permission message 98 | return; 99 | }; 100 | }; 101 | 102 | if (temp != null) cmd = temp; 103 | if (temp == null || list.length == 0) return cmd; 104 | }; 105 | }; 106 | 107 | let loadCommands = (rootPath) => { 108 | let toReturn = { 109 | commandsCol: new Collection(), 110 | logs: defaultCommands 111 | }; 112 | return new Promise((Resolve, Reject) => { 113 | 114 | toReturn.logs.stats.time = Date.now(); 115 | 116 | let load = (path, parent) => { 117 | 118 | let _toReturn = []; 119 | 120 | let files = fs.readdirSync(path); // Get the list of commands. 121 | for (const file of files) { 122 | 123 | let _command = { 124 | name: file.split('.')[0].toLowerCase(), 125 | description: "none", 126 | usage: null, 127 | aliases: [], 128 | requiredPermission: null, 129 | requiredRole: null, 130 | path: path.split('\\').pop(), 131 | size: 0, 132 | depth: (!parent ? 0 : parent.depth), 133 | file: file, 134 | errors: [], 135 | // subCommands: null, 136 | // run: null, 137 | }; 138 | 139 | _command.depth++; 140 | 141 | let stats = fs.statSync(`${path}/${file}`); 142 | if (stats.isDirectory()) { // If the command is a folder 143 | 144 | let _files = fs.readdirSync(`${path}/${file}`); 145 | let main = _files.find(x => x.toLowerCase() == file.toLowerCase() + '.js'); 146 | if (main) { 147 | let command = require(`${path}/${file}/${main}`); 148 | _command = merge(_command, command.info || {}); 149 | } 150 | _command.usage = `${parent != null ? `${parent.usage} ` : ''}${_command.name}${(_command.usage == null || _command.usage.trim().length == 0) ? '' : " " + _command.usage.trim()}`; 151 | 152 | _command.subCommands = load(`${path}/${file}`, _command); 153 | } else { 154 | _command.size = stats.size; 155 | if (parent != null && (parent.file.toLowerCase() + '.js') == file.toLowerCase()) continue; 156 | let command = require(`${path}/${file}`); 157 | 158 | _command = merge(_command, command.info || {}); 159 | _command.usage = `${parent != null ? `${parent.usage} ` : ''}${_command.name}${(_command.usage == null || _command.usage.trim().length == 0) ? '' : " " + _command.usage.trim()}`; 160 | 161 | _command.run = command.run || ((client, message, args) => console.log("WORKS!")); 162 | }; 163 | 164 | let dirDupeCheck = checkForDuplicate(_command, (_toReturn || [])); // Checking for in this directory; 165 | if (dirDupeCheck.status == true) { 166 | _command.errors.push({ 167 | path: _command.path + '/' + _command.file, 168 | error: dirDupeCheck.duplicate 169 | }); 170 | }; 171 | 172 | if (_command.requiredPermission != null && checkPermission(_command.requiredPermission) == false) { 173 | _command.errors.push({ 174 | path: _command.path + '/' + _command.file, 175 | error: `"${_command.requiredPermission}" is not a valid permission. check https://discord.com/developers/docs/topics/permissions for more information` 176 | }); 177 | }; 178 | 179 | if (parent == null) { 180 | let DupeCheck = checkForDuplicate(_command, ([...toReturn.commandsCol.values()] || []), true); // Checking for in this directory; 181 | if (DupeCheck.status == true) { 182 | _command.errors.push({ 183 | path: _command.path + '/' + _command.file, 184 | error: DupeCheck.duplicate 185 | }); 186 | }; 187 | }; 188 | 189 | if (_command.errors.length == 0) { 190 | delete _command.errors; 191 | if (parent == null) toReturn.commandsCol.set(_command.name, _command); 192 | } 193 | else { 194 | toReturn.logs.errors = toReturn.logs.errors.concat(_command.errors); 195 | }; 196 | 197 | _toReturn.push(_command); 198 | }; 199 | 200 | _toReturn = _toReturn.filter(x => x.errors == null); 201 | toReturn.logs.stats.commands = toReturn.logs.stats.commands + _toReturn.length; 202 | toReturn.logs.stats.subCommands = toReturn.logs.stats.subCommands + _toReturn.filter(x => x.subCommands != null && x.run == null).length; 203 | 204 | return _toReturn; 205 | }; 206 | 207 | 208 | let files = fs.readdirSync(rootPath); // Get the list of categories. 209 | 210 | for (const file of files) { 211 | toReturn.logs.categories.push({ name: file, children: load(`${rootPath}/${file}`) }); 212 | }; 213 | 214 | toReturn.logs.stats.errors = toReturn.logs.errors.length; 215 | toReturn.logs.stats.categories = files.length; 216 | toReturn.logs.stats.time = Date.now() - toReturn.logs.stats.time; 217 | 218 | // save and output log 219 | log = toReturn.logs; 220 | module.exports.log = log; 221 | 222 | Resolve(toReturn); 223 | }); 224 | }; 225 | 226 | module.exports = { 227 | loadCommands, 228 | findCommand, 229 | log 230 | }; -------------------------------------------------------------------------------- /src/utils/fetchNodes.js: -------------------------------------------------------------------------------- 1 | const { panel } = require('../index.js'); 2 | 3 | const fetchNodes = async () => await panel.fetchNodes(); 4 | 5 | const fetchBotNodes = (allNodes) => allNodes.data.filter(x => x.description?.toLowerCase()?.includes('bot')).map(node => node.id); 6 | 7 | 8 | const fetchGamingNodes = (allNodes) => allNodes.data.filter(x => x.description?.toLowerCase()?.includes('gaming')).map(node => node.id); 9 | 10 | 11 | const fetchStorageNodes = (allNodes) => allNodes.data.filter(x => x.description?.toLowerCase()?.includes('storage')).map(node => node.id); 12 | 13 | 14 | 15 | const parse = (nodes) => ({ 16 | botNodes: fetchBotNodes(nodes), 17 | gamingNodes: fetchGamingNodes(nodes), 18 | storageNodes: fetchStorageNodes(nodes) 19 | }); 20 | 21 | 22 | module.exports = { 23 | fetchNodes, 24 | fetchBotNodes, 25 | fetchGamingNodes, 26 | fetchStorageNodes, 27 | parse 28 | } -------------------------------------------------------------------------------- /src/utils/libs/emailTemplate.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 16 | 17 | 18 | 19 | 20 | 21 | 116 | 117 |
22 | 23 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 94 | 95 | 96 | 97 | 98 | 113 | 114 |
26 | a 28 |
35 | 37 | 38 | 91 | 92 |
40 | 41 |

43 |

44 | 45 | 46 |

48 |

49 | 50 |

51 | 52 |

53 | 54 | 55 | 57 | 58 | 67 | 68 |
59 | 60 | 64 | Login and Begin Using! 65 | 66 |
69 | 70 | 71 | 72 | 73 |

75 |

76 | 77 | 78 | 80 | 81 | 88 | 89 |
83 |

85 | 86 |

87 |
90 |
93 |
99 | 102 | 103 | 110 | 111 |
105 | 109 |
112 |
115 |
118 | 119 | 120 | -------------------------------------------------------------------------------- /src/utils/mongo.js: -------------------------------------------------------------------------------- 1 | const mongoose = require("mongoose"); 2 | const { mongoPath } = require("../config.json"); 3 | 4 | module.exports = async () => { 5 | await mongoose.connect(mongoPath, { 6 | useNewUrlParser: true, 7 | useUnifiedTopology: true, 8 | }); 9 | 10 | return mongoose; 11 | }; -------------------------------------------------------------------------------- /src/wrapper/Application/Application.js: -------------------------------------------------------------------------------- 1 | let login = { 2 | url: null, 3 | APIKey: null 4 | }; 5 | 6 | let createUser = require('./Modules/createUser'); 7 | let deleteUser = require('./Modules/deleteUser'); 8 | let createServer = require('./Modules/createServer'); 9 | let deleteServer = require('./Modules/deleteServer'); 10 | 11 | let getServer = require('./Modules/getServer'); 12 | let getNode = require('./Modules/getNode'); 13 | let getUser = require('./Modules/getUser'); 14 | let getNest = require('./Modules/getNest'); 15 | let getLocation = require('./Modules/getLocation'); 16 | 17 | let fetchNests = require('./Modules/getAllNests'); 18 | let fetchUsers = require('./Modules/getAllUsers'); 19 | let fetchServers = require('./Modules/getAllServers'); 20 | let fetchNodes = require('./Modules/getAllNodes'); 21 | let fetchLocations = require('./Modules/getAllLocations'); 22 | 23 | let updateUser = require('./Modules/updateUser'); 24 | 25 | let initialize = (HostURL, APIKey) => { 26 | HostURL = HostURL.trim(); 27 | if (HostURL.endsWith('/')) HostURL = HostURL.slice(0, -1); 28 | login = { 29 | url: HostURL, 30 | APIKey: APIKey.trim() 31 | }; 32 | }; 33 | 34 | let credential = () => { 35 | return login; 36 | }; 37 | 38 | module.exports = { 39 | login: initialize, 40 | cred: credential, 41 | 42 | // post Requests 43 | createUser: createUser, 44 | deleteUser: deleteUser, 45 | createServer: createServer, 46 | deleteServer: deleteServer, 47 | 48 | // get Requests 49 | fetchUsers: fetchUsers, 50 | fetchServers: fetchServers, 51 | fetchNodes: fetchNodes, 52 | fetchNests: fetchNests, 53 | fetchLocations: fetchLocations, 54 | 55 | getServer: getServer, 56 | getNode: getNode, 57 | getUser: getUser, 58 | getNest: getNest, 59 | getLocation: getLocation, 60 | 61 | // patch Requests 62 | updateUser: updateUser, 63 | }; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/createServer.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush } = require('../utils'); 3 | /** 4 | * 5 | * @param {String} ServerName Character limits: a-z A-Z 0-9 _ - . and [Space]. 6 | * @param {Number} UserID User ID 7 | * @param {Number} NestID the Nest that this server will be grouped under. 8 | * @param {Number} EggID the Egg will define how this server should operate. 9 | * @param {Number} Location Node location 10 | * @param {Number} CPU The amount of CPU Power the server can use. (100 = 1 core) 11 | * @param {Number} RAM The maximum amount of memory allowed for this container. 12 | * @param {Number} Swap Setting this to 0 will disable swap space on this server. Setting to -1 will allow unlimited swap. 13 | * @param {Number} Disk This server will not be allowed to boot if it is using more than this amount of space. If a server goes over this limit while running it will be safely stopped and locked until enough space is available. Set to 0 to allow unlimited disk usage. 14 | * @param {Number} IO The IO performance of this server relative to other running containers on the system. Value should be between 10 and 1000 (please keep at 500). 15 | * @param {(String|null)} DockerImage This is the default Docker image that will be used to run this server. Can be null (if null the wrapper will get the dockerimage from the egg) 16 | * @param {(String|null)} StartupCmd Start Up Command. Can be null (if null the wrapper will get the default startupcmd from the egg) 17 | * @param {Object} environment enviroment 18 | * @param {Object} [option] Feature Limits. (databases, allocations, backups) 19 | * @param {Number} [option.databases=0] Amount of databases this server is allowed to have. 20 | * @param {Number} [option.allocations=0] Amount of allocations this server is allowed to have. 21 | * @param {Number} [option.backups=0] Amount of backups this server is allowed to have. 22 | */ 23 | function createServer(ServerName, UserID, NestID, EggID, Location, RAM, Swap, Disk, IO, CPU, DockerImage, StartupCmd, environment, option) { 24 | let cred = require('../Application').cred(); 25 | let getNest = require('./getNest'); 26 | let start = Date.now(); 27 | 28 | if (option == null || option) option = { 29 | databases: 0, 30 | allocations: 0, 31 | backups: 0 32 | }; 33 | return new Promise(async (resolve, reject) => { 34 | if (DockerImage == null || StartupCmd == null) { 35 | let egg = await getNest(NestID); 36 | if (egg.errors != null) { 37 | return resolve({ 38 | success: false, 39 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 40 | info: { 41 | startedAt: start, 42 | endedAt: Date.now(), 43 | } 44 | }); 45 | }; 46 | egg = egg.data.extras.eggs.find(x => x.id == EggID); 47 | } 48 | 49 | const input = { 50 | "name": ServerName, 51 | "user": UserID, 52 | "nest": NestID, 53 | "egg": EggID, 54 | "docker_image": DockerImage == null ? (egg != null ? egg.docker_image : "") : DockerImage, 55 | "startup": StartupCmd == null ? (egg != null ? egg.startup : "") : StartupCmd, 56 | "limits": { 57 | "memory": RAM, 58 | "swap": Swap, 59 | "disk": Disk, 60 | "io": IO, 61 | "cpu": CPU 62 | }, 63 | "environment": environment, 64 | 65 | "feature_limits": { 66 | "databases": option.databases != null ? option.databases : 0, 67 | "allocations": option.allocations != null ? option.allocations : 0, 68 | "backups": option.backups != null ? option.backups : 0 69 | }, 70 | "deploy": { 71 | "locations": [Location], 72 | "dedicated_ip": false, 73 | "port_range": [] 74 | }, 75 | 'oom_disabled': true, 76 | "start_on_completion": false 77 | }; 78 | 79 | let res = await fetch(cred.url + "/api/application/servers", { 80 | method: 'POST', 81 | body: JSON.stringify(input), 82 | headers: { 83 | "Content-Type": 'application/json', 84 | "Authorization": 'Bearer ' + cred.APIKey, 85 | "Accept": 'application/json' 86 | }, 87 | }); 88 | 89 | let data = await res.json(); 90 | if (data.errors != null) { 91 | return resolve({ 92 | success: false, 93 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 94 | info: { 95 | startedAt: start, 96 | endedAt: Date.now(), 97 | } 98 | }); 99 | } else return resolve(toPush(data, start)); 100 | }); 101 | 102 | } 103 | 104 | module.exports = createServer; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/createUser.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush } = require('../utils') 3 | 4 | /** 5 | * @param {String} Username Users username 6 | * @param {String} Password Users password 7 | * @param {String} Email Users email 8 | * @param {String} FirstName Users first name 9 | * @param {String} LastName Users last name 10 | * @param {Boolean} IsAdmin Is the user admin? (true/false) 11 | * @param {String} Language Language, Normally [en/fr] 12 | */ 13 | function createUser(Username, Password, Email, FirstName, LastName, IsAdmin, Language) { 14 | let cred = require('../Application').cred(); 15 | let start = Date.now(); 16 | 17 | 18 | let input = { 19 | 'username': Username, 20 | 'email': Email, 21 | 'first_name': FirstName, 22 | 'last_name': LastName, 23 | 'password': Password, 24 | 'root_admin': IsAdmin, 25 | 'language': Language, 26 | }; 27 | return new Promise(async (resolve, reject) => { 28 | 29 | let res = await fetch(cred.url + "/api/application/users", { 30 | method: 'POST', 31 | body: JSON.stringify(input), 32 | headers: { 33 | "Content-Type": 'application/json', 34 | "Authorization": 'Bearer ' + cred.APIKey, 35 | "Accept": 'application/json' 36 | }, 37 | }); 38 | 39 | let data = await res.json(); 40 | if (data.errors != null) { 41 | return resolve({ 42 | success: false, 43 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 44 | info: { 45 | startedAt: start, 46 | endedAt: Date.now(), 47 | } 48 | }); 49 | } else return resolve(toPush(data, start)) 50 | }); 51 | } 52 | 53 | module.exports = createUser; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/deleteServer.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | /** 4 | * @param {Number} ID Server ID. 5 | * @param {Boolean} force if true This action will attempt to delete the server from both the panel and daemon. If the daemon does not respond, or reports an error the deletion will continue. 6 | */ 7 | 8 | function createUser(ID, force) { 9 | if (ID == null) ID = 0; 10 | if (force == null) force = false; 11 | 12 | let cred = require('../Application').cred(); 13 | let start = Date.now(); 14 | return new Promise(async (resolve, reject) => { 15 | 16 | let res = await fetch(cred.url + "/api/application/servers/" + ID + (force == true ? "/force" : ""), { 17 | method: 'DELETE', 18 | headers: { 19 | "Content-Type": 'application/json', 20 | "Authorization": 'Bearer ' + cred.APIKey, 21 | "Accept": 'application/json' 22 | }, 23 | }); 24 | 25 | let data = await res.json().catch(x => { 26 | return resolve({ 27 | success: true, 28 | info: { 29 | startedAt: start, 30 | endedAt: Date.now(), 31 | } 32 | }) 33 | }); 34 | 35 | if (data != null && data.errors != null) { 36 | return resolve({ 37 | success: false, 38 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 39 | info: { 40 | startedAt: start, 41 | endedAt: Date.now(), 42 | } 43 | }); 44 | } 45 | }) 46 | } 47 | 48 | module.exports = createUser; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/deleteUser.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | 3 | /** 4 | * @param {Number} ID User ID 5 | */ 6 | function createUser(ID) { 7 | let cred = require('../Application').cred(); 8 | let start = Date.now(); 9 | return new Promise(async (resolve, reject) => { 10 | 11 | let res = await fetch(cred.url + "/api/application/users/" + ID, { 12 | method: 'DELETE', 13 | headers: { 14 | "Content-Type": 'application/json', 15 | "Authorization": 'Bearer ' + cred.APIKey, 16 | "Accept": 'application/json' 17 | }, 18 | }); 19 | 20 | let data = await res.json().catch(x => { 21 | return resolve({ 22 | success: true, 23 | info: { 24 | startedAt: start, 25 | endedAt: Date.now(), 26 | } 27 | }) 28 | }); 29 | 30 | if (data != null && data.errors != null) { 31 | return resolve({ 32 | success: false, 33 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 34 | info: { 35 | startedAt: start, 36 | endedAt: Date.now(), 37 | } 38 | }); 39 | } 40 | }) 41 | } 42 | 43 | module.exports = createUser; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getAllLocations.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toIncludes, toPush } = require('../utils'); 3 | 4 | 5 | /** 6 | * @param {Object} [options] What to include with request. 7 | * @param {Boolean} [options.eggs] Include all eggs in that Nest. 8 | * @param {Boolean} [options.servers] Include all serrvers using that Nest. 9 | * */ 10 | 11 | function getAllLocations(options) { 12 | if (options == null || (typeof options) != "object") options = {}; 13 | 14 | 15 | let cred = require('../Application').cred(); 16 | let start = Date.now(); 17 | 18 | let include = toIncludes(options); 19 | 20 | 21 | return new Promise(async (resolve, reject) => { 22 | let locations = [] 23 | let res = await fetch(cred.url + "/api/application/locations" + (include.length > 0 ? `?include=${include.join(',')}` : ""), { 24 | headers: { 25 | "Content-Type": 'application/json', 26 | "Authorization": 'Bearer ' + cred.APIKey, 27 | "Accept": 'application/json' 28 | } 29 | }); 30 | let data = await res.json(); 31 | 32 | if (data.errors != null) { 33 | return resolve({ 34 | success: false, 35 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 36 | info: { 37 | startedAt: start, 38 | endedAt: Date.now(), 39 | } 40 | }); 41 | }; 42 | locations = locations.concat(data.data); 43 | if (data.meta.pagination.current_page != data.meta.pagination.total_pages) { 44 | for (let i = 2; i <= data.meta.pagination.total_pages; i++) { 45 | fetch(cred.url + "/api/application/locations?page=" + i + (include.length > 0 ? `&include=${include.join(',')}` : ""), { 46 | headers: { 47 | "Content-Type": 'application/json', 48 | "Authorization": 'Bearer ' + cred.APIKey, 49 | "Accept": 'application/json' 50 | } 51 | }).then(x => x.json()).then(x => { 52 | locations = locations.concat(x.data); 53 | if (x.meta.pagination.total == servers.length) 54 | return resolve(toPush(locations, start)); 55 | }); 56 | } 57 | } else 58 | return resolve(toPush(locations, start)); 59 | 60 | }); 61 | } 62 | 63 | module.exports = getAllLocations; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getAllNests.js: -------------------------------------------------------------------------------- 1 | const { toIncludes, toPush } = require('../utils'); 2 | const fetch = require('node-fetch'); 3 | 4 | /** 5 | * @param {Object} [options] What to include with request. 6 | * @param {Boolean} [options.nodes] Include all nodes using that Location. 7 | * @param {Boolean} [options.servers] Include all serrvers using that Location. 8 | * */ 9 | 10 | function getAllNests(options) { 11 | if (options == null || (typeof options) != "object") options = {}; 12 | 13 | let cred = require('../Application').cred(); 14 | let start = Date.now(); 15 | 16 | let include = toIncludes(options); 17 | 18 | return new Promise(async (resolve, reject) => { 19 | let nests = [] 20 | let res = await fetch(cred.url + "/api/application/nests" + (include.length > 0 ? `?include=${include.join(',')}` : ""), { 21 | headers: { 22 | "Content-Type": 'application/json', 23 | "Authorization": 'Bearer ' + cred.APIKey, 24 | "Accept": 'application/json' 25 | } 26 | }); 27 | let data = await res.json(); 28 | 29 | if (data.errors != null) { 30 | return resolve({ 31 | success: false, 32 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 33 | info: { 34 | startedAt: start, 35 | endedAt: Date.now(), 36 | } 37 | }); 38 | }; 39 | 40 | nests = nests.concat(data.data); 41 | 42 | if (data.meta.pagination.current_page != data.meta.pagination.total_pages) { 43 | for (let i = 2; i <= data.meta.pagination.total_pages; i++) { 44 | fetch(cred.url + "/api/application/nests?page=" + i + (include.length > 0 ? `&include=${include.join(',')}` : ""), { 45 | headers: { 46 | "Content-Type": 'application/json', 47 | "Authorization": 'Bearer ' + cred.APIKey, 48 | "Accept": 'application/json' 49 | } 50 | }).then(x => x.json()).then(x => { 51 | nests = nests.concat(x.data); 52 | if (x.meta.pagination.total == nests.length) { 53 | return resolve(toPush(nests, start)); 54 | } 55 | }); 56 | } 57 | } else { 58 | return resolve(toPush(nests, start)); 59 | } 60 | }); 61 | 62 | } 63 | 64 | module.exports = getAllNests; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getAllNodes.js: -------------------------------------------------------------------------------- 1 | const { toIncludes, toPush } = require('../utils'); 2 | 3 | const fetch = require('node-fetch'); 4 | 5 | /** 6 | * @param {Object} [options] What to include with request. 7 | * @param {Boolean} [options.allocations] Include all nodes using that Location. 8 | * @param {Boolean} [options.location] Include all serrvers using that Location. 9 | * @param {Boolean} [options.servers] Include all serrvers using that Location. 10 | * */ 11 | 12 | function getAllNodes(options) { 13 | if (options == null || (typeof options) != "object") options = {}; 14 | 15 | let cred = require('../Application').cred(); 16 | let start = Date.now(); 17 | 18 | let include = toIncludes(options); 19 | 20 | return new Promise(async (resolve, reject) => { 21 | let nodes = [] 22 | let res = await fetch(cred.url + "/api/application/nodes" + (include.length > 0 ? `?include=${include.join(',')}` : ""), { 23 | headers: { 24 | "Content-Type": 'application/json', 25 | "Authorization": 'Bearer ' + cred.APIKey, 26 | "Accept": 'application/json' 27 | } 28 | }); 29 | let data = await res.json(); 30 | 31 | if (data.errors != null) { 32 | return resolve({ 33 | success: false, 34 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 35 | info: { 36 | startedAt: start, 37 | endedAt: Date.now(), 38 | } 39 | }); 40 | }; 41 | 42 | nodes = nodes.concat(data.data); 43 | 44 | if (data.meta.pagination.current_page != data.meta.pagination.total_pages) { 45 | for (let i = 2; i <= data.meta.pagination.total_pages; i++) { 46 | fetch(cred.url + "/api/application/nodes?page=" + i + (include.length > 0 ? `&include=${include.join(',')}` : ""), { 47 | headers: { 48 | "Content-Type": 'application/json', 49 | "Authorization": 'Bearer ' + cred.APIKey, 50 | "Accept": 'application/json' 51 | } 52 | }).then(x => x.json()).then(x => { 53 | nodes = nodes.concat(x.data); 54 | if (x.meta.pagination.total == nodes.length) { 55 | return resolve(toPush(nodes, start)); 56 | } 57 | }); 58 | } 59 | } else { 60 | return resolve(toPush(nodes, start)); 61 | } 62 | }); 63 | 64 | } 65 | 66 | module.exports = getAllNodes; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getAllServers.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush } = require('../utils'); 3 | 4 | function getAllServers() { 5 | let cred = require('../Application').cred(); 6 | let start = Date.now(); 7 | 8 | return new Promise(async (resolve, reject) => { 9 | let servers = [] 10 | let res = await fetch(cred.url + "/api/application/servers", { 11 | headers: { 12 | "Content-Type": 'application/json', 13 | "Authorization": 'Bearer ' + cred.APIKey, 14 | "Accept": 'application/json' 15 | } 16 | }); 17 | let data = await res.json(); 18 | 19 | if (data.errors != null) { 20 | return resolve({ 21 | success: false, 22 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 23 | info: { 24 | startedAt: start, 25 | endedAt: Date.now(), 26 | } 27 | }); 28 | }; 29 | servers = servers.concat(data.data); 30 | if (data.meta.pagination.current_page != data.meta.pagination.total_pages) { 31 | for (let i = 2; i <= data.meta.pagination.total_pages; i++) { 32 | fetch(cred.url + "/api/application/servers?page=" + i, { 33 | headers: { 34 | "Content-Type": 'application/json', 35 | "Authorization": 'Bearer ' + cred.APIKey, 36 | "Accept": 'application/json' 37 | } 38 | }).then(x => x.json()).then(x => { 39 | if (x.errors != null) { 40 | return resolve({ 41 | success: false, 42 | error: (x.errors.length == 1 ? x.errors[0] : x.errors), 43 | info: { 44 | startedAt: start, 45 | endedAt: Date.now(), 46 | } 47 | }); 48 | }; 49 | servers = servers.concat(x.data); 50 | if (x.meta.pagination.total == servers.length) { 51 | return resolve(toPush(servers, start)); 52 | } 53 | }); 54 | } 55 | } else 56 | return resolve(toPush(servers, start)); 57 | }); 58 | } 59 | module.exports = getAllServers; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getAllUsers.js: -------------------------------------------------------------------------------- 1 | const { toIncludes, toPush } = require('../utils'); 2 | const fetch = require('node-fetch'); 3 | 4 | /** 5 | * @param {Object} [options] 6 | * @param {Object} [options.filter] What to filter with. 7 | * @param {String} [options.filter.key] What to filter with. [email, uuid, username, external_id] 8 | * @param {String} [options.filter.value] Value to look for. 9 | * @param {Object} [options.include] What to include with request. 10 | * @param {Boolean} [options.include.servers] Include all serrvers using that Location. 11 | * */ 12 | 13 | function getAllUsers(options) { 14 | if (options == null || typeof options != "object") options = {}; 15 | 16 | 17 | let cred = require('../Application').cred(); 18 | let start = Date.now(); 19 | 20 | let filter = ((options.filter != null && options.filter.key != null && options.filter.value != null) ? `filter[${options.filter.key}]=${options.filter.value}` : "") 21 | 22 | let include = [] 23 | if (options.include != null) { 24 | include = toIncludes(options.include); 25 | } 26 | 27 | let addon = ((filter.length > 0 || include.length > 0) ? "?" + (filter.length > 0 ? filter + (include.length > 0 ? `&include=${include.join(',')}` : "") : (include.length > 0 ? `include=${include.join(',')}` : "")) : "") 28 | return new Promise(async (resolve, reject) => { 29 | let users = [] 30 | let res = await fetch(cred.url + "/api/application/users" + addon, { 31 | headers: { 32 | "Content-Type": 'application/json', 33 | "Authorization": 'Bearer ' + cred.APIKey, 34 | "Accept": 'application/json' 35 | } 36 | }); 37 | let data = await res.json(); 38 | 39 | if (data.errors != null) { 40 | return resolve({ 41 | success: false, 42 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 43 | info: { 44 | startedAt: start, 45 | endedAt: Date.now(), 46 | } 47 | }); 48 | }; 49 | 50 | users = users.concat(data.data); 51 | if (data.meta.pagination.current_page != data.meta.pagination.total_pages && filter.length == 0) { 52 | for (let i = 2; i <= data.meta.pagination.total_pages; i++) { 53 | fetch(cred.url + "/api/application/users?page=" + i + (include.length > 0 ? `&include=${include.join(',')}` : ""), { 54 | headers: { 55 | "Content-Type": 'application/json', 56 | "Authorization": 'Bearer ' + cred.APIKey, 57 | "Accept": 'application/json' 58 | } 59 | }).then(x => x.json()).then(x => { 60 | users = users.concat(x.data); 61 | if (x.meta.pagination.total == users.length) { 62 | return resolve(toPush(users, start)); 63 | } 64 | }); 65 | } 66 | } else 67 | resolve(toPush(users, start)) 68 | }); 69 | 70 | } 71 | 72 | module.exports = getAllUsers; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getLocation.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush, toIncludes } = require('../utils'); 3 | 4 | /** 5 | * 6 | * @param {Number} ID Location ID you're trying to fetch. 7 | * @param {Object} [options] What to include with request. 8 | * @param {Boolean} [options.nodes] List of nodes assigned to the location. 9 | * @param {Boolean} [options.servers] List of servers in the location. 10 | */ 11 | 12 | module.exports = (ID, options) => { 13 | if (options == null || typeof options != "object") options = {}; 14 | if (ID == null) ID = 0; 15 | 16 | let cred = require('../Application').cred(); 17 | let start = Date.now(); 18 | 19 | let include = toIncludes(options); 20 | 21 | return new Promise(async (resolve, reject) => { 22 | let res = await fetch(cred.url + "/api/application/locations/" + ID + (include.length > 0 ? "?include=" + include.join(',') : ""), { 23 | headers: { 24 | "Content-Type": 'application/json', 25 | "Authorization": 'Bearer ' + cred.APIKey, 26 | "Accept": 'application/json' 27 | } 28 | }); 29 | let data = await res.json(); 30 | if (data.errors != null) { 31 | return resolve({ 32 | success: false, 33 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 34 | info: { 35 | startedAt: start, 36 | endedAt: Date.now(), 37 | } 38 | }); 39 | }; 40 | return resolve(toPush(data, start)); 41 | }); 42 | } -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getNest.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush } = require('../utils'); 3 | 4 | /** 5 | * @param {Object} [options] 6 | * @param {Object} [options.] What to include with request. 7 | * @param {Boolean} [options.eggs] Include List of eggs in the location. 8 | * @param {Boolean} [options.servers] Include List of servers in the location. 9 | * */ 10 | module.exports = (ID, options) => { 11 | if (options == null || typeof options != "object") options = {}; 12 | if (ID == null) ID = 0; 13 | 14 | let cred = require('../Application').cred(); 15 | let start = Date.now(); 16 | 17 | let include = toIncludes(options); 18 | 19 | return new Promise(async (resolve, reject) => { 20 | let data = await fetch(cred.url + "/api/application/nests/" + ID + (include.length > 0 ? "?include=" + include.join(',') : ""), { 21 | headers: { 22 | "Content-Type": 'application/json', 23 | "Authorization": 'Bearer ' + cred.APIKey, 24 | "Accept": 'application/json' 25 | } 26 | }).then(x => x.json()); 27 | if (data.errors != null) { 28 | return resolve({ 29 | success: false, 30 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 31 | info: { 32 | startedAt: start, 33 | endedAt: Date.now(), 34 | } 35 | }); 36 | }; 37 | 38 | return resolve(toPush(data, start)); 39 | }); 40 | } -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getNode.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush, toIncludes } = require('../utils'); 3 | 4 | /** 5 | * 6 | * @param {Number} ID Node ID you're trying to fetch. 7 | * @param {Object} [options] What to include with request. 8 | * @param {Boolean} [options.allocations] List of allocations added to the node. 9 | * @param {Boolean} [options.location] Information about the location the node is assigned to. 10 | * @param {Boolean} [options.servers] List of servers on the node. 11 | */ 12 | module.exports = (ID, options) => { 13 | if (options == null || typeof options != "object") options = {}; 14 | if (ID == null) ID = 0; 15 | 16 | let cred = require('../Application').cred(); 17 | let start = Date.now(); 18 | 19 | let include = toIncludes(options); 20 | 21 | return new Promise(async (resolve, reject) => { 22 | let res = await fetch(cred.url + "/api/application/nodes/" + ID + (include.length > 0 ? "?include=" + include.join(',') : ""), { 23 | headers: { 24 | "Content-Type": 'application/json', 25 | "Authorization": 'Bearer ' + cred.APIKey, 26 | "Accept": 'application/json' 27 | } 28 | }); 29 | let data = await res.json(); 30 | if (data.errors != null) { 31 | return resolve({ 32 | success: false, 33 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 34 | info: { 35 | startedAt: start, 36 | endedAt: Date.now(), 37 | } 38 | }); 39 | }; 40 | return resolve(toPush(data, start)); 41 | }); 42 | } -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getServer.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush, toIncludes } = require('../utils'); 3 | 4 | /** 5 | * 6 | * @param {Number|String} ID Server ID you're trying to fetch. 7 | * @param {Object} [options] What to include with request. 8 | * @param {Boolean} [options.allocations] Include List of allocations assigned to the server. 9 | * @param {Boolean} [options.user] Include Information about the server owner. 10 | * @param {Boolean} [options.subusers] Include all subusers on that server. 11 | * @param {Boolean} [options.pack] Include Information about the server pack. 12 | * @param {Boolean} [options.nest] Include Information about the server's egg nest. 13 | * @param {Boolean} [options.egg] Include Information about the server's egg. 14 | * @param {Boolean} [options.variables] List of server variables. (causes an error) 15 | * @param {Boolean} [options.location] Include Information about server's node location. 16 | * @param {Boolean} [options.node] Include Information about the server's node. 17 | * @param {Boolean} [options.databases] Include List of databases on the server. 18 | */ 19 | module.exports = (ID, options) => { 20 | if (options == null || typeof options != "object") options = {}; 21 | if (ID == null) ID = 0; 22 | 23 | let cred = require('../Application').cred(); 24 | let start = Date.now(); 25 | 26 | let include = toIncludes(options); 27 | 28 | return new Promise(async (resolve, reject) => { 29 | let res = await fetch(cred.url + "/api/application/servers/" + ID + (include.length > 0 ? "?include=" + include.join(',') : ""), { 30 | headers: { 31 | "Content-Type": 'application/json', 32 | "Authorization": 'Bearer ' + cred.APIKey, 33 | "Accept": 'application/json' 34 | } 35 | }); 36 | let data = await res.json(); 37 | if (data.errors != null) { 38 | return resolve({ 39 | success: false, 40 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 41 | info: { 42 | startedAt: start, 43 | endedAt: Date.now(), 44 | } 45 | }); 46 | }; 47 | 48 | return resolve(toPush(data, start)); 49 | }); 50 | } -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/getUser.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | const { toPush, toIncludes } = require('../utils'); 3 | 4 | /** 5 | * 6 | * @param {Number} ID User ID you're trying to fetch. 7 | * @param {Object} [options] What to include with request. 8 | * @param {Boolean} [options.servers] Include all serrvers owned by that user. 9 | */ 10 | function getUser(ID, options) { 11 | if (options == null || typeof options != "object") options = {}; 12 | 13 | let cred = require('../Application').cred(); 14 | let start = Date.now(); 15 | 16 | let include = toIncludes(options); 17 | 18 | return new Promise(async (resolve, reject) => { 19 | let res = await fetch(cred.url + "/api/application/users/" + ID + (include.length > 0 ? "?include=" + include.join(',') : ""), { 20 | headers: { 21 | "Content-Type": 'application/json', 22 | "Authorization": 'Bearer ' + cred.APIKey, 23 | "Accept": 'application/json' 24 | } 25 | }); 26 | let data = await res.json(); 27 | if (data.errors != null) { 28 | return resolve({ 29 | success: false, 30 | error: (data.errors.length == 1 ? data.errors[0] : data.errors), 31 | info: { 32 | startedAt: start, 33 | endedAt: Date.now(), 34 | } 35 | }); 36 | }; 37 | return resolve(toPush(data, start)); 38 | }); 39 | } 40 | 41 | module.exports = getUser; -------------------------------------------------------------------------------- /src/wrapper/Application/Modules/updateUser.js: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | let getUser = require('./getUser'); 3 | const { toPush } = require('../utils'); 4 | 5 | /** 6 | * @param {Number} userID User's ID 7 | * @param {object} data things you want to update 8 | * @param {String?} data.username Users username 9 | * @param {String?} data.password Users password 10 | * @param {String?} data.email Users email 11 | * @param {String?} data.first_name Users first name 12 | * @param {String?} data.last_name Users last name 13 | * @param {Boolean?} data.root_admin Is the user admin? (true/false) 14 | * @param {String?} data.language Language, Normally [en/fr] 15 | */ 16 | async function createUser(UserID, data) { 17 | let cred = require('../Application').cred(); 18 | let start = Date.now(); 19 | 20 | return new Promise(async (resolve, reject) => { 21 | 22 | let old = await getUser(UserID); 23 | if (old.error != null) { 24 | return resolve({ 25 | success: false, 26 | error: (old.error.length == 1 ? old.error[0] : old.error), 27 | info: { 28 | startedAt: start, 29 | endedAt: Date.now(), 30 | } 31 | }); 32 | }; 33 | 34 | let input = { 35 | 'username': data.username != null ? data.username : old.data.username, 36 | 'email': data.email != null ? data.email : old.data.email, 37 | 'first_name': data.first_name != null ? data.first_name : old.data.first_name, 38 | 'last_name': data.last_name != null ? data.last_name : old.data.last_name, 39 | 'password': data.password != null ? data.password : old.data.password, 40 | 'root_admin': data.root_admin != null ? data.root_admin : old.data.root_admin, 41 | 'language': data.language != null ? data.language : old.data.language, 42 | }; 43 | 44 | let res = await fetch(cred.url + "/api/application/users/" + UserID, { 45 | method: 'PATCH', 46 | body: JSON.stringify(input), 47 | headers: { 48 | "Content-Type": 'application/json', 49 | "Authorization": 'Bearer ' + cred.APIKey, 50 | "Accept": 'application/json' 51 | }, 52 | }); 53 | 54 | let resData = await res.json(); 55 | if (resData.errors != null) { 56 | return resolve({ 57 | success: false, 58 | error: (resData.errors.length == 1 ? resData.errors[0] : resData.errors), 59 | info: { 60 | startedAt: start, 61 | endedAt: Date.now(), 62 | } 63 | }); 64 | } else return resolve(toPush(resData, start)) 65 | }); 66 | } 67 | 68 | module.exports = createUser; -------------------------------------------------------------------------------- /src/wrapper/Application/utils.js: -------------------------------------------------------------------------------- 1 | let toPush = (input, start) => { 2 | if (input.length == 0) { 3 | return { 4 | success: false, 5 | error: { 6 | code: 'NotFoundHttpException', 7 | status: '404', 8 | detail: 'The requested resource does not exist on this server.' 9 | }, 10 | info: { 11 | startedAt: start, 12 | endedAt: Date.now(), 13 | } 14 | }; 15 | }; 16 | 17 | if (input.length != null) { 18 | input = input.map(x => { 19 | x = x.attributes; 20 | if (x.relationships) { 21 | let k = Object.keys(x.relationships); 22 | x.extras = {}; 23 | k.forEach(key => { 24 | if (x.relationships[key].data != null) 25 | x.extras[key] = x.relationships[key].data.map(a => a.attributes); 26 | else 27 | x.extras[key] = x.relationships[key]; 28 | }); 29 | }; 30 | return x; 31 | }); 32 | } else { 33 | if (input.attributes != null) input = input.attributes; 34 | 35 | if (input.relationships) { 36 | let k = Object.keys(input.relationships); 37 | input.extras = {}; 38 | k.forEach(key => { 39 | if (input.relationships[key].data != null) 40 | input.extras[key] = input.relationships[key].data.map(a => a.attributes); 41 | else 42 | input.extras[key] = input.relationships[key]; 43 | }); 44 | delete input.relationships; 45 | }; 46 | }; 47 | 48 | let toReturn = { 49 | success: true 50 | }; 51 | 52 | if (input != null) 53 | toReturn.data = (input.length == 1 ? input[0] : input); 54 | 55 | toReturn.info = { 56 | total_amount: (input != null ? (input.length != null ? input.length : 1) : 0), 57 | startedAt: start, 58 | endedAt: Date.now(), 59 | }; 60 | 61 | return toReturn; 62 | }; 63 | 64 | let toIncludes = (options) => { 65 | let include = []; 66 | if (Object.values(options).includes(true)) { 67 | include = []; 68 | const entries = Object.entries(options); 69 | for (const [flags, value] of entries) { 70 | if (value == true) include.push(flags); 71 | }; 72 | }; 73 | 74 | return include; 75 | }; 76 | 77 | module.exports = { 78 | toPush: toPush, 79 | toIncludes: toIncludes, 80 | }; -------------------------------------------------------------------------------- /src/wrapper/index.js: -------------------------------------------------------------------------------- 1 | const app = require('./Application/Application'); 2 | 3 | module.exports = { 4 | Application: app 5 | }; --------------------------------------------------------------------------------