├── .env.example ├── .gitattributes ├── .github └── FUNDING.yml ├── LICENSE ├── README.md ├── commands ├── Context │ ├── Message.js │ └── User.js ├── General │ ├── Channel.js │ ├── Integer.js │ ├── Role.js │ ├── String.js │ ├── SubCommand.js │ ├── SubGroupCommand.js │ └── User.js └── Ping.js ├── deploySlash.js ├── events ├── client │ ├── disconnect.js │ ├── error.js │ ├── rateLimit.js │ ├── ready.js │ └── reconnecting.js └── guild │ └── interactionCreate.js ├── handlers ├── loadCommand.js └── loadEvent.js ├── index.js ├── package.json └── settings └── config.js /.env.example: -------------------------------------------------------------------------------- 1 | # Bot 2 | TOKEN=REPLACE_HERE 3 | OWNER_ID=REPLACE_HERE 4 | EMBED_COLOR=#000001 -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: [Adivise] 2 | ko_fi: nanotect -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Nanotect 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 |

2 | 3 |

4 | 5 |

6 | 7 |

8 | 9 |

10 | 11 |

12 | 13 | ## 📑 Feature 14 | - [x] Example (Command!) 15 | - [x] SlashCommand (Base, Group, Sub) 16 | - [x] Handlers 17 | - [x] Context Menu (Message, User) 18 | - [x] Easy to use 19 | 20 | ## 📎 Requirements 21 | 22 | - Node.js v16+ **[Download](https://nodejs.org/en/download/)** 23 | - Discord Bot Token **[Guide](https://discordjs.guide/preparations/setting-up-a-bot-application.html#creating-your-bot)** 24 | 25 | 26 | ## 📚 Installation 27 | 28 | ``` 29 | git clone https://github.com/Adivise/NanoStyle 30 | cd NanoStyle 31 | npm install 32 | ``` 33 | 34 | 35 | ## 📄 Configuration 36 | 37 | Copy or Rename `.env.example` to `.env` and fill out the values: 38 | 39 | ```.env 40 | # Bot 41 | TOKEN=REPLACE_HERE 42 | EMBED_COLOR=#000001 43 | OWNER_ID=REPLACE_HERE 44 | ``` 45 | 46 | After installation or finishes all you can use `node .` to start the bot. 47 | -------------------------------------------------------------------------------- /commands/Context/Message.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandType } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: ["Context | Message"], 5 | type: ApplicationCommandType.Message, 6 | run: async (client, interaction) => { 7 | await interaction.deferReply({ ephemeral: false }); 8 | 9 | const args = (interaction.channel.messages.cache.get(interaction.targetId).content ?? await interaction.channel.messages.fetch(interaction.targetId)); 10 | 11 | const embed = new EmbedBuilder() 12 | .setDescription(`I Copy you message: ${args}`) 13 | .setColor(client.color) 14 | 15 | return interaction.reply({ embeds: [embed] }); 16 | } 17 | } -------------------------------------------------------------------------------- /commands/Context/User.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandType } = require('discord.js'); 2 | 3 | module.exports = { 4 | name: ["Context | User"], 5 | type: ApplicationCommandType.User, 6 | run: async (client, interaction) => { 7 | await interaction.deferReply({ ephemeral: false }); 8 | 9 | const args0 = interaction.guild.members.cache.get(interaction.targetId) || interaction.member; 10 | const args1 = client.users.cache.get(interaction.targetId) || interaction.user; 11 | 12 | const embed = new EmbedBuilder() 13 | .setDescription(`I Pinging: ${args0} | Who are you? ${args1}`) 14 | .setColor(client.color) 15 | 16 | return interaction.reply({ embeds: [embed] }); 17 | } 18 | } -------------------------------------------------------------------------------- /commands/General/Channel.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["channel"], // Base Commands! 5 | description: "Channel Commands!", 6 | options: [ 7 | { 8 | name: "target", 9 | description: "Mention channel", 10 | type: ApplicationCommandOptionType.Channel, 11 | required: true 12 | } 13 | ], 14 | run: async (client, interaction) => { 15 | const args = interaction.options.getChannel("target"); 16 | 17 | const embed = new EmbedBuilder() 18 | .setDescription(` 19 | CHANNEL: ${args} 20 | CHANNEL NAME: ${args.name} 21 | CHANNEL ID: ${args.id} 22 | `) 23 | .setColor(client.color) 24 | 25 | return interaction.reply({ embeds: [embed] }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /commands/General/Integer.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["integer"], // Base Commands! 5 | description: "Integer Commands!", 6 | options: [ 7 | { 8 | name: "number", 9 | description: "String message", 10 | type: ApplicationCommandOptionType.Integer, 11 | required: true 12 | } 13 | ], 14 | run: async (client, interaction) => { 15 | const args = interaction.options.getInteger("number"); 16 | 17 | const embed = new EmbedBuilder() 18 | .setDescription(`${args}`) 19 | .setColor(client.color) 20 | 21 | return interaction.reply({ embeds: [embed] }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /commands/General/Role.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["role"], // Base Commands! 5 | description: "Role Commands!", 6 | options: [ 7 | { 8 | name: "mention", 9 | description: "Mention a role", 10 | type: ApplicationCommandOptionType.Channel, 11 | required: true 12 | } 13 | ], 14 | run: async (client, interaction) => { 15 | const args = interaction.options.getRole("mention"); 16 | 17 | const embed = new EmbedBuilder() 18 | .setDescription(` 19 | ROLE: ${args} 20 | ROLE NAME: ${args.name} 21 | ROLE ID: ${args.id} 22 | `) 23 | .setColor(client.color) 24 | 25 | return interaction.reply({ embeds: [embed] }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /commands/General/String.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["string"], // Base Commands! 5 | description: "String Commands!", 6 | options: [ 7 | { 8 | name: "message", 9 | description: "String message", 10 | type: ApplicationCommandOptionType.String, 11 | required: true 12 | } 13 | ], 14 | run: async (client, interaction) => { 15 | const args = interaction.options.getString("message"); 16 | 17 | const embed = new EmbedBuilder() 18 | .setDescription(`${args}`) 19 | .setColor(client.color) 20 | 21 | return interaction.reply({ embeds: [embed] }); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /commands/General/SubCommand.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["base-command", "sub-command"], // Base Commands! // Sub Commands! 5 | description: "Sub Commands!", 6 | run: async (client, interaction) => { 7 | const embed = new EmbedBuilder() 8 | .setDescription(`THIS IS SUB COMMAND!`) 9 | .setColor(client.color) 10 | 11 | return interaction.reply({ embeds: [embed] }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /commands/General/SubGroupCommand.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["base-command", "sub-group-command", "sub-command"], // Base Commands! // SubGroup Commands! // Sub Commands! 5 | description: "SubGroup Commands!", 6 | run: async (client, interaction) => { 7 | const embed = new EmbedBuilder() 8 | .setDescription(`THIS IS SUB GROUP COMMAND!`) 9 | .setColor(client.color) 10 | 11 | return interaction.reply({ embeds: [embed] }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /commands/General/User.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder, ApplicationCommandOptionType } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["user"], // Base Commands! 5 | description: "User Commands!", 6 | options: [ 7 | { 8 | name: "target", 9 | description: "Mention user", 10 | type: ApplicationCommandOptionType.User, 11 | required: true 12 | } 13 | ], 14 | run: async (client, interaction) => { 15 | const args = interaction.options.getUser("target"); 16 | 17 | const embed = new EmbedBuilder() 18 | .setDescription(` 19 | USER: ${args} 20 | USER NAME: ${args.username} 21 | USER ID: ${args.id} 22 | `) 23 | .setColor(client.color) 24 | 25 | return interaction.reply({ embeds: [embed] }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /commands/Ping.js: -------------------------------------------------------------------------------- 1 | const { EmbedBuilder } = require("discord.js"); 2 | 3 | module.exports = { 4 | name: ["ping"], // Base Commands! 5 | description: "Check latency of bot!", 6 | run: async (client, interaction) => { 7 | const embed = new EmbedBuilder() 8 | .setDescription(`Pong....`) 9 | .setColor(client.color) 10 | 11 | return interaction.reply({ embeds: [embed] }); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /deploySlash.js: -------------------------------------------------------------------------------- 1 | const { plsParseArgs } = require('plsargs'); 2 | const args = plsParseArgs(process.argv.slice(2)); 3 | const chillout = require("chillout"); 4 | const { makeSureFolderExists } = require("stuffs"); 5 | const path = require("path"); 6 | const readdirRecursive = require("recursive-readdir"); 7 | const { TOKEN } = require("./settings/config.js"); 8 | const { ApplicationCommandOptionType, REST, Routes, ApplicationCommandManager } = require('discord.js'); 9 | 10 | (async () => { 11 | 12 | let command = []; 13 | 14 | let cleared = args.get(0) == "guild" ? args.get(2) == "clear" : (args.get(0) == "global" ? args.get(1) == "clear" : false); 15 | let deployed = args.get(0) == "guild" ? "guild" : args.get(0) == "global" ? "global" : null; 16 | 17 | if (!deployed) { 18 | console.error(`Invalid sharing mode! Valid modes: guild, global`); 19 | console.error(`Usage example: node deploySlash.js guild [clear]`); 20 | console.error(`Usage example: node deploySlash.js global [clear]`); 21 | return process.exit(1); 22 | } 23 | 24 | if (!cleared) { 25 | let interactionsFolder = path.resolve("./commands"); 26 | 27 | await makeSureFolderExists(interactionsFolder); 28 | 29 | let store = []; 30 | 31 | console.log("Reading interaction files..") 32 | 33 | let interactionFilePaths = await readdirRecursive(interactionsFolder); 34 | interactionFilePaths = interactionFilePaths.filter(i => { 35 | let state = path.basename(i).startsWith("-"); 36 | return !state; 37 | }); 38 | 39 | await chillout.forEach(interactionFilePaths, (interactionFilePath) => { 40 | const cmd = require(interactionFilePath); 41 | console.log(`Interaction "${cmd.type == "CHAT_INPUT" ? `/${cmd.name.join(" ")}` : `${cmd.name[0]}`}" ${cmd.name[1] || ""} ${cmd.name[2] || ""} added to the transform list!`); 42 | store.push(cmd); 43 | }); 44 | 45 | store = store.sort((a, b) => a.name.length - b.name.length) 46 | 47 | command = store.reduce((all, current) => { 48 | switch (current.name.length) { 49 | case 1: { 50 | all.push({ 51 | type: current.type, 52 | name: current.name[0], 53 | description: current.description, 54 | defaultPermission: current.defaultPermission, 55 | options: current.options 56 | }); 57 | break; 58 | } 59 | case 2: { 60 | let baseItem = all.find((i) => { 61 | return i.name == current.name[0] && i.type == current.type 62 | }); 63 | if (!baseItem) { 64 | all.push({ 65 | type: current.type, 66 | name: current.name[0], 67 | description: `${current.name[0]} commands.`, 68 | defaultPermission: current.defaultPermission, 69 | options: [ 70 | { 71 | type: ApplicationCommandOptionType.Subcommand, 72 | description: current.description, 73 | name: current.name[1], 74 | options: current.options 75 | } 76 | ] 77 | }); 78 | } else { 79 | baseItem.options.push({ 80 | type: ApplicationCommandOptionType.Subcommand, 81 | description: current.description, 82 | name: current.name[1], 83 | options: current.options 84 | }) 85 | } 86 | break; 87 | } 88 | case 3: { 89 | let SubItem = all.find((i) => { 90 | return i.name == current.name[0] && i.type == current.type 91 | }); 92 | if (!SubItem) { 93 | all.push({ 94 | type: current.type, 95 | name: current.name[0], 96 | description: `${current.name[0]} commands.`, 97 | defaultPermission: current.defaultPermission, 98 | options: [ 99 | { 100 | type: ApplicationCommandOptionType.SubcommandGroup, 101 | description: `${current.name[1]} commands.`, 102 | name: current.name[1], 103 | options: [ 104 | { 105 | type: ApplicationCommandOptionType.Subcommand, 106 | description: current.description, 107 | name: current.name[2], 108 | options: current.options 109 | } 110 | ] 111 | } 112 | ] 113 | }); 114 | } else { 115 | let GroupItem = SubItem.options.find(i => { 116 | return i.name == current.name[1] && i.type == ApplicationCommandOptionType.SubcommandGroup 117 | }); 118 | if (!GroupItem) { 119 | SubItem.options.push({ 120 | type: ApplicationCommandOptionType.SubcommandGroup, 121 | description: `${current.name[1]} commands.`, 122 | name: current.name[1], 123 | options: [ 124 | { 125 | type: ApplicationCommandOptionType.Subcommand, 126 | description: current.description, 127 | name: current.name[2], 128 | options: current.options 129 | } 130 | ] 131 | }) 132 | } else { 133 | GroupItem.options.push({ 134 | type: ApplicationCommandOptionType.Subcommand, 135 | description: current.description, 136 | name: current.name[2], 137 | options: current.options 138 | }) 139 | } 140 | } 141 | } 142 | break; 143 | } 144 | 145 | return all; 146 | }, []); 147 | 148 | command = command.map(i => ApplicationCommandManager.transformCommand(i)); 149 | } else { 150 | console.info("No interactions read, all existing ones will be cleared..."); 151 | } 152 | 153 | const rest = new REST({ version: "9" }).setToken(TOKEN); 154 | const client = await rest.get(Routes.user()); 155 | console.info(`Account information received! ${client.username}#${client.discriminator} (${client.id})`); 156 | 157 | console.info(`Interactions are posted on discord!`); 158 | switch (deployed) { 159 | case "guild": { 160 | let guildId = args.get(1); 161 | console.info(`Deploy mode: guild (${guildId})`); 162 | 163 | await rest.put(Routes.applicationGuildCommands(client.id, guildId), { body: command }); 164 | 165 | console.info(`Shared commands may take 3-5 seconds to arrive.`); 166 | break; 167 | } 168 | case "global": { 169 | console.info(`Deploy mode: global`); 170 | 171 | await rest.put(Routes.applicationCommands(client.id), { body: command }); 172 | 173 | console.info(`Shared commands can take up to 1 hour to arrive. If you want it to come immediately, you can throw your bot from your server and get it back.`); 174 | break; 175 | } 176 | } 177 | 178 | console.info(`Interactions shared!`); 179 | })(); 180 | 181 | /// Credit https://github.com/akanora/Youtube-Together (Handler) || Edit by: https://github.com/Adivise -------------------------------------------------------------------------------- /events/client/disconnect.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client) => { 2 | console.log('[WARN] Bot Disconnecting'); 3 | } -------------------------------------------------------------------------------- /events/client/error.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, error) => { 2 | console.log('[ERROR] Error' + error); 3 | } -------------------------------------------------------------------------------- /events/client/rateLimit.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client, info) => { 2 | console.log('[WARN] Rate Limited'); 3 | } -------------------------------------------------------------------------------- /events/client/ready.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client) => { 2 | console.log(`[INFO] ${client.user.tag} (${client.user.id}) is Ready!`); 3 | 4 | let guilds = client.guilds.cache.size; 5 | let members = client.guilds.cache.reduce((a, b) => a + b.memberCount, 0); 6 | let channels = client.channels.cache.size; 7 | 8 | const activities = [ 9 | `/help | ${guilds} servers`, 10 | `/simple | ${members} users`, 11 | `/nanohandler | ${channels} channels`, 12 | ] 13 | 14 | setInterval(() => { 15 | client.user.setPresence({ 16 | activities: [{ name: `${activities[Math.floor(Math.random() * activities.length)]}`, type: 2 }], 17 | status: 'online', 18 | }); 19 | }, 15000) 20 | 21 | }; 22 | -------------------------------------------------------------------------------- /events/client/reconnecting.js: -------------------------------------------------------------------------------- 1 | module.exports = async (client) => { 2 | console.log('[WARN] Bot Reconnecting'); 3 | } -------------------------------------------------------------------------------- /events/guild/interactionCreate.js: -------------------------------------------------------------------------------- 1 | module.exports = async(client, interaction) => { 2 | if (interaction.isCommand || interaction.isContextMenuCommand || interaction.isModalSubmit || interaction.isChatInputCommand) { 3 | if (!interaction.guild) return; 4 | 5 | let subCommandName = ""; 6 | try { 7 | subCommandName = interaction.options.getSubcommand(); 8 | } catch { }; 9 | let subCommandGroupName = ""; 10 | try { 11 | subCommandGroupName = interaction.options.getSubcommandGroup(); 12 | } catch { }; 13 | 14 | const command = client.slash.find(command => { 15 | switch (command.name.length) { 16 | case 1: return command.name[0] == interaction.commandName; 17 | case 2: return command.name[0] == interaction.commandName && command.name[1] == subCommandName; 18 | case 3: return command.name[0] == interaction.commandName && command.name[1] == subCommandGroupName && command.name[2] == subCommandName; 19 | } 20 | }); 21 | 22 | if (!command) return; 23 | if (!client.dev.includes(interaction.user.id) && client.dev.length > 0) { 24 | interaction.reply(`The bot is under maintenance. (Please come back again later)`); 25 | console.log(`[COMMAND] ${interaction.user.tag} trying request the command from ${interaction.guild.name} (${interaction.guild.id})`); 26 | return; 27 | } 28 | 29 | const msg_cmd = [ 30 | `[COMMAND] ${command.name[0]}`, 31 | `${command.name[1] || ""}`, 32 | `${command.name[2] || ""}`, 33 | `used by ${interaction.user.tag} from ${interaction.guild.name} (${interaction.guild.id})`, 34 | ] 35 | 36 | console.log(`${msg_cmd.join(" ")}`); 37 | 38 | if (command) { 39 | try { 40 | command.run(client, interaction); 41 | } catch (error) { 42 | console.log(error) 43 | await interaction.reply({ content: `Something went wrong!`, ephmeral: true }); 44 | }} 45 | } 46 | } -------------------------------------------------------------------------------- /handlers/loadCommand.js: -------------------------------------------------------------------------------- 1 | const chillout = require("chillout"); 2 | const readdirRecursive = require("recursive-readdir"); 3 | const { resolve, relative } = require("path"); 4 | 5 | module.exports = async (client) => { 6 | let interactionsPath = resolve("./commands"); 7 | let interactionFiles = await readdirRecursive(interactionsPath); 8 | 9 | await chillout.forEach(interactionFiles, (interactionFile) => { 10 | const start = Date.now(); 11 | const rltPath = relative(__dirname, interactionFile); 12 | // console.log(`[INFO] Loading interaction at.. "${interactionFile}"`) 13 | const command = require(interactionFile); 14 | 15 | if (command.name.length > 3) { 16 | console.log(`[WARN] "${rltPath}" The name list of the interaction file is too long. (>3) Skipping..`); 17 | return; 18 | } 19 | 20 | if (!command.name?.length) { 21 | console.log(`[WARN] "${rltPath}" The interaction file does not have a name. Skipping..`); 22 | return; 23 | } 24 | 25 | if (client.slash.has(command.name)) { 26 | console.log(`[WARN] "${command.name[1]}" interaction has already been installed. It's skipping.`) 27 | return; 28 | } 29 | 30 | client.slash.set(command.name, command); 31 | // console.log(`[INFO] "${command.type == "CHAT_INPUT" ? `/${command.name.join(" ")}` : `${command.name[0]}`}" ${command.name[1] || ""} ${command.name[2] || ""} The interaction has been uploaded. (it took ${Date.now() - start}ms)`); 32 | }); 33 | 34 | if (client.slash.size) { 35 | console.log(`[INFO] ${client.slash.size} Interactions are Loaded!`); 36 | } else { 37 | console.log(`[WARN] No interactions loaded, is everything ok?`); 38 | } 39 | } -------------------------------------------------------------------------------- /handlers/loadEvent.js: -------------------------------------------------------------------------------- 1 | const { readdirSync } = require('fs'); 2 | 3 | module.exports = async (client) => { 4 | const loadcommand = dirs =>{ 5 | const events = readdirSync(`./events/${dirs}/`).filter(d => d.endsWith('.js')); 6 | for (let file of events) { 7 | const evt = require(`../events/${dirs}/${file}`); 8 | const eName = file.split('.')[0]; 9 | client.on(eName, evt.bind(null, client)); 10 | } 11 | }; 12 | ["client", "guild"].forEach((x) => loadcommand(x)); 13 | console.log("[INFO] Events are Loaded!"); 14 | }; -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const { Client, Collection, GatewayIntentBits } = require("discord.js"); 2 | 3 | const client = new Client({ 4 | intents: [ 5 | GatewayIntentBits.Guilds, 6 | GatewayIntentBits.GuildMembers, 7 | GatewayIntentBits.GuildMessages, 8 | ], 9 | }); 10 | 11 | client.config = require('./settings/config.js'); 12 | client.owner = client.config.OWNER_ID; 13 | client.dev = client.config.DEV_ID; 14 | client.color = client.config.EMBED_COLOR; 15 | if(!client.token) client.token = client.config.TOKEN; 16 | 17 | process.on('unhandledRejection', error => console.log(error)); 18 | process.on('uncaughtException', error => console.log(error)); 19 | 20 | ["slash"].forEach(x => client[x] = new Collection()); 21 | ["loadCommand", "loadEvent"].forEach(x => require(`./handlers/${x}`)(client)); 22 | 23 | client.login(client.token); -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nanohandler", 3 | "version": "1.0.1", 4 | "description": "✈ Join Discord: https://discord.gg/4pk97A2 👌", 5 | "main": "index.js", 6 | "dependencies": { 7 | "chillout": "^5.0.0", 8 | "discord.js": "^14.3.0", 9 | "path": "^0.12.7", 10 | "plsargs": "^0.1.6", 11 | "recursive-readdir": "^2.2.2", 12 | "dotenv": "^16.0.2", 13 | "stuffs": "^0.1.17" 14 | }, 15 | "scripts": { 16 | "start": "node --no-warnings index.js" 17 | }, 18 | "author": "Adivise", 19 | "license": "MIT", 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/Adivise/NanoHandler.git" 23 | }, 24 | "bugs": { 25 | "url": "https://github.com/Adivise/NanoHandler/issues" 26 | }, 27 | "homepage": "https://github.com/Adivise/NanoHandlereadme", 28 | "devDependencies": { 29 | "node": "^17.0.1" 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /settings/config.js: -------------------------------------------------------------------------------- 1 | require("dotenv").config(); 2 | 3 | module.exports = { 4 | TOKEN: process.env.TOKEN || "YOUR_TOKEN", // your bot token 5 | EMBED_COLOR: process.env.EMBED_COLOR || "#000001", //<= default is "#000001" 6 | OWNER_ID: process.env.OWNER_ID || "YOUR_CLIENT_ID", //your owner discord id example: "515490955801919488" 7 | DEV_ID: [], // if you want to use command bot only, you can put your id here example: ["123456789", "123456789"] 8 | } --------------------------------------------------------------------------------