Setup turborepo (#2610)

* chore: BREAKING move to monorepo structure

* chore: setup turborepo
This commit is contained in:
Jonathan Ho
2022-12-01 01:59:02 +08:00
committed by GitHub
parent 42719cd2c1
commit d04a040f28
821 changed files with 8763 additions and 4396 deletions

View File

@@ -0,0 +1 @@
TOKEN=

View File

@@ -0,0 +1,136 @@
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
const fs = require("fs");
const path = require("path");
class CommandManager {
constructor(client) {
this.client = client;
this.cache = new Map();
this.aliases = new Map();
}
load(options = {}) {
const commandFolderPath = options.path || "../Plugins";
const commandFolder = resolveFolder(commandFolderPath);
if (options.category === undefined) options.category = true;
if (options.plugins === undefined) options.plugins = true;
//PluginMode will iterate through all SubFolders
fs.readdirSync(commandFolder).map(async (dir) => {
if (dir.endsWith(".txt")) return;
if (!options.category && dir.endsWith(".js")) {
const commandPath = path.join(commandFolder, dir);
this.loadCommand(commandPath);
} else {
fs.readdirSync(path.join(commandFolder, dir)).map((cmd) => {
if (cmd.endsWith(".js") && !options.plugins) {
const commandPath = path.join(commandFolder, dir, cmd);
this.loadCommand(commandPath);
} else if (commandFolderPath === "../Plugins") {
if (cmd !== "commands") return;
fs.readdirSync(path.join(commandFolder, dir, cmd)).map((cmdfile) => {
if (!cmdfile.endsWith(".js")) return;
const commandPath = path.join(commandFolder, dir, cmd, cmdfile);
this.loadCommand(commandPath);
});
}
});
}
});
}
loadCommand(commandPath) {
const pull = require(path.join(commandPath));
if (pull.name) {
pull.path = commandPath;
this.cache.set(pull.name, pull);
}
if (pull.aliases) {
pull.aliases.map((p) => this.aliases.set(p, pull));
}
return pull;
}
reloadCommand(commandName) {
const command = this.cache.get(commandName);
if (!command) return;
const commandPath = path.join(command.path);
delete require.cache[require.resolve(commandPath)];
return this.loadCommand(commandPath);
}
isCommand(message) {
if (message.isFromBot) return false;
const prefix = "!";
const escapeRegex = (str) => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
const prefixRegex = new RegExp(`^(<@!?${this.client.id}>|${escapeRegex(prefix)})\\s*`);
if (!prefixRegex.test(message.content)) return false;
const [, matchedPrefix] = message.content.match(prefixRegex);
const args = message.content.slice(matchedPrefix.length).trim().split(/ +/);
this.onMessage(message, prefix, args);
return true;
}
isInteraction(interaction) {
if (interaction.type !== 2) return;
this.onInteraction(interaction);
}
async onMessage(message, guild, args) {
const commandName = args.shift().toLowerCase();
const command = this.cache.get(commandName); //|| this.cache.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
if (!command && message.content.includes(this.client.id)) {
//Handle, when Command has not been found
const options = { content: "I did not found the Command!" };
this.client.helpers.sendMessage(message.channelId, options);
}
if (!command) return;
const messagecommand = new command({
manager: this,
message: message,
client: this.client,
args: args,
settings: {},
commandName: command.name,
});
messagecommand.execute()?.catch?.((error) => {
console.log(error);
// Call Function on CommandResponse.js, handle the error
return messagecommand.onError(error ?? "custom");
});
}
async onInteraction(interaction) {
const command = this.cache.get(interaction.data.name);
if (!command) return;
const args = [];
//Map all Values and Args
interaction.data.options?.map((o) => {
if (o.name) args.push(o.name);
if (o.options) {
o.options.map((o2) => {
if (o2.value) return args.push(o2.value);
if (o2.name) args.push(o2.name);
if (o2.options) o2.options.map((v) => args.push(v.value));
});
}
});
const messagecommand = new command({
manager: this,
interaction: interaction,
client: this.client,
args: args,
settings: {},
commandName: command.name,
});
messagecommand.execute()?.catch?.((error) => {
console.log(error);
// Call Function on CommandResponse.js, handle the error
return messagecommand.onError(error ?? "custom");
});
}
}
module.exports = CommandManager;

View File

@@ -0,0 +1,32 @@
const fs = require("fs");
const path = require("path");
const resolveFolder = (folderName) => path.resolve(__dirname, ".", folderName);
const EventEmitter = require("events");
class EventManager extends EventEmitter {
constructor() {
super();
this.cache = new Map();
this.allEvents = {};
}
load(options = {}) {
const eventsFolder = resolveFolder("../events");
let i = 0;
fs.readdirSync(eventsFolder).map(async (file) => {
if (!file.endsWith(".js")) return;
i++;
const fileName = path.join(eventsFolder, file);
const event = require(fileName);
const eventName = file.split(".")[0];
this.allEvents[`${eventName}`] = (...args) => {
this.emit(eventName, ...args);
return event(...args);
};
});
return this.allEvents;
}
}
module.exports = EventManager;

View File

@@ -0,0 +1,50 @@
const Discord = require("discordeno.js");
const BaseCommand = require("../../../Structures/BaseCommand.js");
class evalcommand extends BaseCommand {
static name = "eval";
static description = "danger !!!";
static category = "Developer";
static slash = { name: "eval", category: "dev" };
constructor(data) {
super(data);
}
async execute() {
if (!this.client.config.owners.includes(String(this.user.id))) return;
if (!(this.args.length > 0)) return this.reply({ content: "**You must provide something to eval!**" });
let inputOfEval = this.args.join(" ");
let outputOfEval;
let typeOfEval;
try {
if (this.args.includes("await")) {
outputOfEval = await eval("(async () => {" + inputOfEval + "})()");
} else {
outputOfEval = await eval(inputOfEval);
}
} catch (e) {
outputOfEval = e.message;
typeOfEval = e.name;
}
var seen = [];
outputOfEval = typeof outputOfEval === "object"
? JSON.stringify(outputOfEval, (_, value) => {
if (value == `Bot ${this.client.config.token}`) return `BOT_TOKEN`;
if (typeof value === "bigint") value = value.toString();
if (typeof value === "object" && value !== null) {
if (seen.indexOf(value) !== -1) return;
else seen.push(value);
}
return value;
}, 1)
: outputOfEval;
const embed = new Discord.Embed()
.addField({ name: "Input", value: "```js\n" + inputOfEval + "```" })
.addField({ name: "Output", value: "```json\n" + `${outputOfEval}`.slice(0, 1000) + "```" });
this.reply({ embeds: [embed] });
}
}
module.exports = evalcommand;

View File

@@ -0,0 +1,18 @@
const BaseCommand = require("../../../Structures/BaseCommand.js");
class reloadcommand extends BaseCommand {
static name = "reload";
static description = "Reloads a Command";
static category = "Developer";
static slash = { name: "reload", category: "dev" };
constructor(data) {
super(data);
}
async execute() {
if (!this.client.config.owners.includes(String(this.user.id))) return;
if (!this.args[0]) return this.reply({ content: "**You must provide a command to reload!**" });
const op = this.client.commands.reloadCommand(this.args[0]);
if (!op) return this.reply({ content: "**That command doesn't exist!**" });
return this.reply({ content: "**Reloaded Command: `" + this.args[0] + "`**" });
}
}
module.exports = reloadcommand;

View File

@@ -0,0 +1,24 @@
const BaseCommand = require("../../../Structures/BaseCommand.js");
const Discord = require("discordeno.js");
class pingcommand extends BaseCommand {
static name = "ping";
static description = "See if the bot latency is okay";
static usage = "";
static category = "General";
static slash = { name: "ping", category: "info" };
constructor(data) {
super(data);
}
async execute() {
const msg = await this.channel.send({ content: `Pinging...` });
//Assign properties to the response
const ping = msg.timestamp - (this.message ? this.message.timestamp : this.interaction.timestamp);
const embed = new Discord.Embed()
.setTitle(`The Bots ping is ${ping} ms`)
.toJSON();
//Edit Message with the Embed
return this.reply({ embeds: [embed] });
}
}
module.exports = pingcommand;

View File

View File

@@ -0,0 +1,40 @@
const BaseCommand = require("../../../Structures/BaseCommand.js");
const Discord = require("discordeno.js");
class bancommand extends BaseCommand {
static name = "ban";
static description = "Ban a user from the server";
static usage = "";
static category = "Moderation";
static slash = { name: "ban", category: "mod" };
constructor(data) {
super(data);
}
async execute() {
//Show Case Modal
// Because no permission system has not been added
if (!this.client.config.owners.includes(String(this.user.id))) return;
const textinput = new Discord.Component()
.setType("TEXT_INPUT")
.setStyle("SHORT")
.setCustomId("t1")
.setLabel("User ID")
.setPlaceholder("User ID")
.setRequired(true)
.setMaxLength(20)
.setMinLength(1)
.setValue(this.args[0])
.toJSON();
const textinput2 = new Discord.Component().setType("TEXT_INPUT").setStyle("PARAGRAPH").setCustomId("t2")
.setLabel("Reason").setPlaceholder("Reason for Ban").setRequired(false)
.setMaxLength(300).toJSON();
const actionrow = new Discord.Component().setType(1).setComponents(textinput).toJSON();
const actionrow2 = new Discord.Component().setType(1).setComponents(textinput2).toJSON();
this.interaction.popupModal({ customId: "ban_modal", title: "Ban User", components: [actionrow, actionrow2] });
}
}
module.exports = bancommand;

View File

@@ -0,0 +1,81 @@
const BaseCommand = require("../../../Structures/BaseCommand.js");
const { Interaction, Collector, ComponentOptions, Embed, Component } = require("discordeno.js");
class warncommand extends BaseCommand {
static name = "warn";
static description = "Warn a user from the server";
static usage = "";
static category = "Moderation";
static slash = { name: "warn", category: "mod" };
constructor(data) {
super(data);
}
async execute() {
//Show Case Modal
if (!this.interaction) return this.reply("You currently can just use this command as slash command.");
if (!this.interaction.member.permissions.has("KICK_MEMBERS")) {
return this.reply("You need the permission `KICK_MEMBERS` to use this command.");
}
const textinput = new Component()
.setType("TEXT_INPUT")
.setStyle("SHORT")
.setCustomId("t1")
.setLabel("User ID")
.setPlaceholder("User ID")
.setRequired(true)
.setMaxLength(20)
.setMinLength(1)
.setValue(this.args[0])
.toJSON();
const textinput2 = new Component().setType("TEXT_INPUT").setStyle("PARAGRAPH").setCustomId("t2")
.setLabel("Reason").setPlaceholder("Reason for Warning").setRequired(false)
.setMaxLength(300).toJSON();
const actionrow = new Component().setType(1).setComponents(textinput).toJSON();
const actionrow2 = new Component().setType(1).setComponents(textinput2).toJSON();
this.interaction.popupModal({ customId: "warn_modal", title: "Warn User", components: [actionrow, actionrow2] });
const filter = (m) => m.data?.customId === "warn_modal";
const collector = new Collector("interactionCreate", { client: this.client, timeout: 60000, filter });
collector.on("collect", (m) => {
const options = new ComponentOptions(m.data.components);
const i = new Interaction(this.client, m);
collector.stop();
const memberId = options.get("t1").value;
const reason = options.get("t2").value;
const embed = new Embed()
.setTitle("Warned User:")
.setDescription(`User ID: <@${memberId}> \n Reason: ${reason}`)
.setColor(0x00ff00)
.toJSON();
const warnMessage = new Embed()
.setTitle("Warning:")
.setDescription(`You have been warned in **${this.guild.name}** for ${"`" + reason + "`"}`)
.toJSON();
this.guild.members.fetch(memberId).then((m) => {
m.send({ embeds: [warnMessage] }).then(() => {
i.reply({ embeds: [embed] });
}).catch((e) => {
console.log(e);
i.reply({ content: `Could not warn user ${"<@" + m.id + ">"} | They likely do not have their DMs open.` });
});
}).catch((e) => {
const embed = new Embed()
.setTitle("Member not found")
.setDescription(`The member with the ID of ${"`" + memberId + "`"} has not been found in this Server.`)
.setColor(0xff0000)
.toJSON();
i.reply({ embeds: [embed] });
});
});
}
}
module.exports = warncommand;

13
examples/nodejs/README.md Normal file
View File

@@ -0,0 +1,13 @@
# Nodejs Bot Template
This template is a minimal template that uses [discordeno.js](https://www.npmjs.com/package/discordeno.js), a wrapper
around discordeno, which brings up a djs-like interface but also includes the core Features (Cross Ratelimit, Zero
Downtime Restart, Resharding...)
## Setup
Rename `.env.example` to `.env` and fill your bot token there.
## Run Bot
- node index.js

View File

@@ -0,0 +1,15 @@
const UtilCommand = require("./CommandResponse.js");
class BaseCommand extends UtilCommand {
constructor(data) {
super(data);
this.message = data.message;
this.interaction = data.interaction;
this.user = this.message ? this.message.author : this.interaction.user;
this.guild = this.message ? this.message.guild : this.interaction.guild;
this.member = this.message ? this.message.member : this.interaction.member;
this.channel = this.message ? this.message.channel : this.interaction.channel;
this.client = data.client;
this.settings = data.settings ?? {};
}
}
module.exports = BaseCommand;

View File

@@ -0,0 +1,50 @@
class Responses {
constructor(data) {
this.manager = data.manager;
this.args = this._validateArguments(data.args);
this.replied = false;
}
async reply(content) {
// When just a string is passed, we assume it's the content -> transform to correct formatted payload
if (typeof content === "string") content = { content };
if (this.interaction) {
if (this.replied) return this.followUp(content);
const reply = await this.interaction.reply(content);
this.replied = true;
return {};
}
if (this.message) {
if (this.replied) return this.followUp(content);
const msg = await this.message.channel.send(content);
//Assign properties to the response
const response = this.client.messages.forge(msg);
this.replied = true;
return response;
}
}
async followUp(content) {
if (this.interaction) {
const reply = await this.interaction.followUp(content);
return {};
}
if (this.message) {
const msg = await this.message.channel.send(content);
const response = this.client.messages.forge(msg);
return response;
}
}
onError(error) {
return this.reply({ content: `A unknown Error happend: \n> ${error}` });
}
_validateArguments(args) {
this.args = args;
return args;
}
}
module.exports = Responses;

View File

@@ -0,0 +1,4 @@
module.exports = async (client, interaction) => {
interaction = client.interactions.forge(interaction);
client.commands.isInteraction(interaction);
};

View File

@@ -0,0 +1,4 @@
module.exports = async (client, message) => {
message = client.messages.forge(message);
client.commands.isCommand(message);
};

View File

@@ -0,0 +1,7 @@
module.exports = async (client, payload) => {
client.user = client.users.forge(payload.user);
if (payload.shardId === client.gateway.lastShardId) {
//All Shards are ready
console.log("Successfully connected to the gateway as " + client.user.tag);
}
};

32
examples/nodejs/index.js Normal file
View File

@@ -0,0 +1,32 @@
require("dotenv").config();
const Discord = require("discordeno.js");
// Ideally you should switch this to .env but for a template a config json is enough
const config = require("./config.json");
const EventManager = require("./Managers/EventManager.js");
// looping through all events and registering them
const events = new EventManager({});
const baseBot = Discord.createBot({
events: events.load({}),
intents: Discord.Intents.Guilds | Discord.Intents.GuildMessages | Discord.Intents.MessageContent,
token: process.env.TOKEN,
});
const client = Discord.enableCachePlugin(baseBot, {});
client.config = config;
// looping through all commands and registering them in .cache of the class
const CommandManager = require("./Managers/CommandManager.js");
client.commands = new CommandManager(client);
client.commands.load({});
// Starts your Bot
Discord.startBot(client);
/*
* You should handle all errors and fix the issues in your codes...
* process.on('unhandledRejection', (reason, p) => {console.log(reason, p)})
*/

View File

@@ -0,0 +1,16 @@
{
"name": "nodejs-template",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"discordeno.js": "github:meister03/discordeno.js",
"dotenv": "^16.0.3"
}
}