Skip to content

Commit

Permalink
1.0.0
Browse files Browse the repository at this point in the history
Initial commit
  • Loading branch information
TeraBaito committed May 6, 2021
0 parents commit f5982f7
Show file tree
Hide file tree
Showing 13 changed files with 399 additions and 0 deletions.
1 change: 1 addition & 0 deletions .env
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DISCORD_TOKEN=
21 changes: 21 additions & 0 deletions LICENSE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2021 TeraBaito

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Discord Bot Skeleton - By TeraBytes
This is a skeleton code with all the common code I (like to) use for Discord Bots. It includes
* Command/Event Handler
* Extended Client structure (for Intellisense and more organization)
* Necessary, ready-to-fill config files
* A colors.json file with a **lot** of color HEX values
* `message` and `ready` events
* `ping`, `help` and `eval` commands

## Installation
I will be sharing compressed artifacts of new releases every now and then, make sure to get those by going [https://github.com/TeraBaito/discord-bot-skeleton/releases]

1. Unzip the file (you can safely remove `README.md` and `LICENSE.md`)
1. Run `npm init` (`npm init -y` to skip prompts)
1. Run `npm i ascii-table beautify chalk common-tags discord.js dotenv`
1. Fill in the `DISCORD_TOKEN=` parameter on `.env` file
1. Go to config.json, and fill in the properties accordingly

Then it's all yours!

Made by TeraBytes, 2021, MIT License
35 changes: 35 additions & 0 deletions colors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"Red": "#FF0000",
"FireBrick": "#B22222",
"Pink": "#FFC0CB",

"Blue": "#0000FF",
"Cyan": "#00FFFF",
"CornflowerBlue": "#6495ED",
"LightBlue": "#ADD8E6",
"PaleBlue": "#293749",
"SteelBlue": "#4682B4",

"ForestGreen": "#228B22",
"Lime": "#00FF00",
"GreenYellow": "#ADFF2F",
"SeaGreen": "#2E8B57",
"Olive": "#808000",

"Orange": "#EB8334",
"OrangeRed": "#FF4500",

"Yellow": "#FFFF00",
"Gold": "#FFD700",
"GoldenRod": "#DAA520",
"Peru": "#CD853F",
"Maroon": "#800000",

"Purple": "#800080",
"Lavender": "#E6E6FA",
"Magenta": "#FF00FF",

"White": "#FFFFFF",
"Black": "#000000",
"Gray": "#808080"
}
4 changes: 4 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"prefix": "",
"ownerID": ""
}
43 changes: 43 additions & 0 deletions index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Modules
const { Client, Collection } = require('discord.js');
require('dotenv').config({ path: './.env'});
const fs = require('fs');
const chalk = require('chalk');
const { stripIndents } = require('common-tags');

const Bot = class extends Client {
constructor() {
super();

this.commands = new Collection();
this.aliases = new Collection();
this.categories = fs.readdirSync('./src/commands');
}
};
module.exports = Bot;

// Client
const bot = new Bot();

// Debugging
//bot.on('raw', console.log);
//bot.on('debug', m => console.log(`${chalk.cyan('[Debug]')} - ${m}`));
bot.on('rateLimit', rl => console.warn(
stripIndents`${chalk.yellow('[Ratelimit]')}
Timeout: ${rl.timeout}
Limit: ${rl.limit}
Route: ${rl.route}`));
bot.on('warn', w => console.warn(`${chalk.yellow('[Warn]')} - ${w}`));
bot.on('error', e => console.error(`${chalk.redBright('[Error]')} - ${e.stack}`));
process.on('uncaughtException', e => console.error(`${chalk.redBright('[Error]')} - ${e.stack}`));
process.on('unhandledRejection', e => console.error(`${chalk.redBright('[Error]')} - ${e.stack}`));
process.on('warning', e => console.warn(`${chalk.yellow('[Error]')} - ${e.stack}`));


// Handlers' modules
['command', 'event'].forEach(handler => {
require(`./src/handlers/${handler}`)(bot);
});

// Login and turn on (default is DISCORD_TOKEN)
bot.login();
56 changes: 56 additions & 0 deletions src/commands/Configuration & Management/eval.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
const { Message, MessageEmbed } = require('discord.js');
const Bot = require('../../../index');
const beautify = require('beautify');
const { ownerID } = require('../../../config.json');
const colors = require('../../../colors.json');


module.exports = {
name: 'eval',
helpName: 'Evaluate',
usage: 'eval [string]',
description: 'Evaluates JavaScript code inputed from args.\nOnwer Only Command\nSelfnote: don\'t use this next to many people idk they could take your token i guess lmao',

/**
* @param {Bot} bot
* @param {Message} message
* @param {string[]} args
*/
run: async(bot, message, args) => {
if (message.author.id !== ownerID) {
return message.channel.send('No dude. I don\'t want anyone but my master mess with code in the bot...')
.then(m => setTimeout(() => { m.delete(); }, 5000));
}

if (!args[0]) {
return message.channel.send('Give me something to evaluate tho')
.then(m => setTimeout(() => { m.delete(); }, 5000));
}

try {
if (args.join(' ').toLowerCase().includes('token')) return message.channel.send('oh nononono you\'re not getting the token you\'re NOT GETTING IT IDNFIABGDJDNWIKG');

const toEval = args.join(' ');
const evaluated = eval(toEval);

let embed = new MessageEmbed()
.setColor(colors.ForestGreen)
.setTimestamp()
.setTitle('Eval')
.addField('To Evaluate', `\`\`\`js\n${beautify(toEval, { format: 'js' })}\n\`\`\``)
.addField('Evaluated', evaluated)
.addField('Type of', typeof(evaluated))
.setFooter(bot.user.username);

message.channel.send(embed);
} catch (e) {
let embed = new MessageEmbed()
.setColor(colors.Red)
.setTitle('Error')
.setDescription(e)
.setFooter(bot.user.username);

message.channel.send(embed);
}
}
};
76 changes: 76 additions & 0 deletions src/commands/Utilities/help.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
const { Message, MessageEmbed } = require('discord.js');
const Bot = require('../../../index');
const { readdirSync } = require('fs');
const { prefix } = require('../../../config.json');
const colors = require('../../../colors.json');


module.exports = {
name: 'help',
aliases: ['commands'],
usage: 'help (command)',
description: 'Shows list of commands',

/**
* @param {Bot} bot
* @param {Message} message
* @param {string[]} args
*/
run: async (bot, message, args) => {
if (args[0]) {
return getCmd(bot, message, args[0]);
} else {
return getAll(bot, message);
}
}
};

function getAll(bot, message) {
const embed = new MessageEmbed()
.setColor(colors.Orange)
.setFooter('Syntax: () = optional, [] = required, {a, b} = choose between a or b');

/* bot.categories is an array
Basically, this reads recursively each directory from src/commands
Then, for each category, it adds a field to the embed with the name and its commands */
bot.categories.forEach(category => {
let filesArr = readdirSync(`./src/commands/${category}`)
.filter(file => file.endsWith('.js')); // Accepts only .js files

embed.addField(category,
filesArr
.map(file => file.substring(0, file.length - 3)) // Removes the .js
.filter(cmd => !bot.commands.get(cmd).hidden) // Removes the ones with a hidden property
.map(str => `\`${str}\``) // Formats the names to include monospace
.join(' ')); // Joints them by spaces instead of newlines

});

// After they're all added, send it
return message.channel.send(embed);
}

function getCmd(bot, message, input) {
const embed = new MessageEmbed()
.setColor(colors.SteelBlue)
.setFooter('Syntax: () = optional; [] = required; {a, b} = choose between a or b');

// Fetching the command data through bot.commands or bot.aliases
const cmd = bot.commands.get(input.toLowerCase()) || bot.commands.get(bot.aliases.get(input.toLowerCase()));

// If the command isn't found (likely doesn't exist)
if(!cmd) {
return message.channel.send(`**${input.toLowerCase()}** is not a command?`);
}

// Adds its name based on helpName || uppercase name
if(cmd.name) embed.setDescription(`**${cmd.helpName ? cmd.helpName : cmd.name[0].toUpperCase() + cmd.name.slice(1)} Command**`);
// Adds aliases by mapping them
if(cmd.aliases) embed.addField('Aliases', `${cmd.aliases.map(a => `\`${a}\``).join(' ')}`);
// The description
if(cmd.description) embed.addField('Description', `${cmd.description}`);
// The usage
if(cmd.usage) embed.addField('Usage', `\`${prefix}${cmd.usage}\``);

return message.channel.send(embed);
}
25 changes: 25 additions & 0 deletions src/commands/Utilities/ping.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
const { Message } = require('discord.js');
const Bot = require('../../../index');
const { stripIndents } = require('common-tags');


module.exports = {
name: 'ping',
aliases: ['pingu', 'pong'],
usage: 'ping',
description: 'Checks the latency of the bot and message latency, and checks if bot is on',

/**
* @param {Bot} bot
* @param {Message} message
* @param {string[]} args
*/
run: async (bot, message, args) => {

const msg = await message.channel.send('Pinging...');

msg.edit(stripIndents`Pong!
Latency: ${Math.floor(msg.createdAt - message.createdAt)}ms
Discord API Latency: ${bot.ws.ping}ms`);
}
};
13 changes: 13 additions & 0 deletions src/events/client/ready.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
const Bot = require('../../../index');
const chalk = require('chalk');

/**
* `ready` event.
* Triggers once the bot loads all the other events and goes online.
* Useful to show ready messages and do/set things at startup.
*
* @param {Client} bot
*/
module.exports = bot => {
console.info(`${chalk.green('[Info]')} - ${bot.user.username} online!`);
};
39 changes: 39 additions & 0 deletions src/events/guild/message.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
const { Message } = require('discord.js');
const Bot = require('../../../index');
const { prefix } = require('../../../config.json');

/**
* `message` event.
*
* Triggers each time any user sends any message in any channel the bot can look into.
*
* This event will include things to do whenever a command is triggered, a blacklisted word is said, etc.
*
* Honestly mostly everything that has to do with user input goes here.
*
* @param {Bot} bot The bot as a Client object
* @param {Message} message The Message object passed with the `message` event.
*/
module.exports = async (bot, message) => {
const args = message.content.slice(prefix.length).trim().split(/ +/g);
const cmd = args.shift().toLowerCase();

/* "\config prefix ?" in which:
\ = prefix
config = cmd
prefix,? = args (args[0],args[1]) */

// Command reading
if (message.author.bot) return; // Prevent from command loops or maymays from bot answers
if (!message.guild) return; // No DMs n stuff
if (!message.member) message.member = await message.guild.members.fetch(message);
if (cmd.length === 0) return; // Come on


// Command handler
let command = bot.commands.get(cmd);
if(!command) command = bot.commands.get(bot.aliases.get(cmd));
if(command && message.content.startsWith(prefix)) {
command.run(bot, message, args);
}
};
Loading

0 comments on commit f5982f7

Please sign in to comment.