-
Notifications
You must be signed in to change notification settings - Fork 3
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
216c381
commit f1b494d
Showing
10 changed files
with
320 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<h1 align="center"> | ||
<a href="https://github.com/LukeIsHereToDevelop/opcommands"><img src="assets/logo.png" alt="OPCommands"></a> | ||
</h1> | ||
|
||
--- | ||
|
||
## What's this? | ||
|
||
OPCommands is an advanced Discord.js Command Handler that supports slash commands and more! | ||
|
||
## Requirements | ||
|
||
* Discord.js v13+ | ||
* Node.js v16.6.0+ | ||
|
||
## Installation | ||
|
||
```bash | ||
npm install --save opcommands | ||
``` | ||
|
||
## Documentation | ||
|
||
Here is the official Documentation of OPCommands: https://opcommands.lukedev.tk | ||
|
||
## Contributing | ||
|
||
Feel free to report bugs, suggest new things or make pull requests to the GitHub repository of OPCommands. It would be really appreciated! |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
{ | ||
"name": "opcommands", | ||
"version": "1.0.0", | ||
"description": "An advanced Discord.js Command Handler that supports slash commands and more!", | ||
"main": "src/OPCommands.js", | ||
"scripts": { | ||
"test": "echo \"Error: no test specified\" && exit 1" | ||
}, | ||
"keywords": [ | ||
"discord.js", | ||
"discord", | ||
"handler", | ||
"command", | ||
"slash" | ||
], | ||
"author": "LukeIsHereToDevelop <[email protected]> (https://lukedev.tk)", | ||
"homepage": "https://opcommands.lukedev.tk", | ||
"bugs": { | ||
"url": "https://github.com/LukeIsHereToDevelop/opcommands/issues" | ||
}, | ||
"repository": "github:LukeIsHereToDevelop/opcommands", | ||
"license": "GPL-3.0-or-later", | ||
"engines": { | ||
"node": "^16.6.0" | ||
}, | ||
"dependencies": { | ||
"@discordjs/rest": "^0.1.0-canary.0", | ||
"discord-api-types": "^0.22.0", | ||
"discord.js": "^13.0.1", | ||
"humanize-ms": "^1.2.1", | ||
"ms": "^2.1.3" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
const Discord = require("discord.js"); | ||
const EventHandler = require("./handlers/Event.js"); | ||
const CommandHandler = require("./handlers/Command.js"); | ||
|
||
/** | ||
* The main class of OPCommands. | ||
* @class | ||
* @requires [Node.js v16.6.0](https://nodejs.org/en/download/current/) & Discord.js v13 | ||
* @param {Discord.Client} client | ||
* @param {Object} options | ||
* @example | ||
* const OPCommands = require("opcommands"); | ||
* const Discord = require("discord.js"); | ||
* const client = new Discord.Client(); | ||
* new OPCommands(client, { | ||
* commandsDir: "commands", | ||
* eventsDir: "events" | ||
* }); | ||
*/ | ||
class OPCommands { | ||
constructor(client, options) { | ||
if (!client) throw new Error("[OPCommands] Missing Discord client."); | ||
if (!options) throw new Error("[OPCommands] Missing options.") | ||
if (!options.commandsDir) throw new Error("[OPCommands] Missing commands' directory parameter on options."); | ||
if (!options.eventsDir) throw new Error("[OPCommands] Missing events' directory parameter on options."); | ||
this.client = client; | ||
this.options = options; | ||
|
||
new CommandHandler(this, options.commandsDir); | ||
new EventHandler(this, options.eventsDir); | ||
} | ||
|
||
/** | ||
* Sets the owner(s) of the bot. | ||
* @param {*} owner Owner ID(s) | ||
*/ | ||
async setBotOwner(owner) { | ||
if (!owner) throw new Error("[OPCommands] Missing Owner ID(s)."); | ||
if (typeof owner === "string") return this.client.owners = [owner]; | ||
if (typeof owner === "array") return this.client.owners = owner; | ||
throw new Error("[OPCommands] Owner parameter must be a String or Array."); | ||
} | ||
|
||
/** | ||
* Adds owner(s) of the bot. | ||
* @param {String} owner Owner ID | ||
*/ | ||
async addBotOwner(owner) { | ||
if (!owner) throw new Error("[OPCommands] Missing Owner ID."); | ||
if (typeof owner != "string") throw new Error("[OPCommands] Owner parameter must be a String."); | ||
return this.client.owners.push(owner); | ||
} | ||
|
||
/** | ||
* Sets the limit messages. | ||
* @param {Object} msgs New messages | ||
*/ | ||
async setMessages(msgs) { | ||
if (!msgs) throw new Error("[OPCommands] Missing the new messages."); | ||
if (typeof msgs != "object") throw new Error("[OPCommands] Msgs parameter must be an Object."); | ||
return this.client.msgs = msgs; | ||
} | ||
} | ||
|
||
module.exports = OPCommands; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
const Discord = require("discord.js"); | ||
const { REST } = require('@discordjs/rest'); | ||
const { Routes } = require('discord-api-types/v9'); | ||
const hms = require("humanize-ms"); | ||
const ms = require("ms"); | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
const { time } = require("console"); | ||
|
||
/** | ||
* Command Handler | ||
* @class | ||
* @param {*} _this | ||
* @param {String} commandsDir | ||
*/ | ||
class CommandHandler { | ||
constructor (_this, commandsDir) { | ||
if (!this) throw new Error("[OPCommands] Internal error: missing _this parameter on Command Handler."); | ||
if (!commandsDir) throw new Error("[OPCommands] Internal error: missing eventsDir parameter on Command Handler."); | ||
if (!fs.existsSync(commandsDir)) throw new Error("[OPCommands] Unexisting command directory."); | ||
|
||
_this.client.commands = new Discord.Collection(); | ||
const files = fs.readdirSync(commandsDir).filter(file => file.endsWith(".js")); | ||
const commands = []; | ||
|
||
if (_this.options.logs) console.log("[OPCommands] Loaded " + files.length + " commands."); | ||
for (const file of files) { | ||
const commandFile = require(path.join(require.main.path, commandsDir, file)); | ||
_this.client.commands.set(commandFile.name, commandFile); | ||
const commandObj = { | ||
name: commandFile.name, | ||
description: commandFile.description | ||
}; | ||
if (commandFile.options) Object.assign(commandObj, {options: commandFile.options}); | ||
commands.push(JSON.stringify(commandObj)); | ||
}; | ||
|
||
_this.client.on("ready", async () => { | ||
const rest = new REST({ version: "9" }).setToken(_this.client.token); | ||
|
||
(async () => { | ||
try { | ||
await rest.put( | ||
Routes.applicationGuildCommands(_this.client.application?.id, "678352388251451433"), | ||
{ body: _this.client.commands }, | ||
); | ||
} catch (error) { | ||
console.error(error); | ||
} | ||
})(); | ||
}); | ||
|
||
const cooldowns = new Discord.Collection(); | ||
_this.client.on("interactionCreate", (interaction) => { | ||
if (!interaction.isCommand()) return; | ||
if (!_this.client.commands.has(interaction.commandName)) return; | ||
const commandFile = _this.client.commands.get(interaction.commandName); | ||
if (commandFile.limits.owner && !_this.client.owners.includes(interaction.user.id)) { | ||
const ownerOnly = _this.client.msgs.ownerOnly; | ||
if (ownerOnly) { | ||
return ownerOnly(interaction); | ||
} else { | ||
return interaction.reply({ content: "You must be a Bot Owner to execute this command!", ephemeral: true }); | ||
}; | ||
}; | ||
if (commandFile.limits.permissions && !interaction.member?.permissions.has(commandFile.limits.permissions)) { | ||
const permissions = _this.client.msgs.permissions; | ||
if (permissions) { | ||
return permissions(interaction, commandFile.limits.permissions); | ||
} else { | ||
return interaction.reply({ content: "You must have the following permissions: " + commandFile.limits.permissions.join(", "), ephemeral: true }); | ||
}; | ||
}; | ||
if (!cooldowns.has(`${commandFile.name}_${interaction.user.id}`)) { | ||
if (!commandFile.limits.cooldown) return; | ||
cooldowns.set(`${commandFile.name}_${interaction.user.id}`, Date.now()); | ||
setTimeout(() => {cooldowns.delete(`${commandFile.name}_${interaction.user.id}`)}, hms(commandFile.limits.cooldown)) | ||
} else { | ||
const expirationTime = cooldowns.get(`${commandFile.name}_${interaction.user.id}`) + hms(commandFile.limits.cooldown); | ||
if (Date.now() < expirationTime) { | ||
const timeLeft = ms(expirationTime - Date.now()); | ||
const cooldown = _this.client.msgs.cooldown; | ||
if (cooldown) { | ||
return cooldown(interaction, timeLeft); | ||
} else { | ||
return interaction.reply({ content: `You are in a cooldown! Please wait **${timeLeft}**.`, ephemeral: true }); | ||
}; | ||
}; | ||
}; | ||
|
||
try { | ||
if (_this.options.logs) console.log("[OPCommands] Command executed: " + interaction.commandName); | ||
_this.client.commands.get(interaction.commandName).run(_this.client, interaction); | ||
} catch (e) { | ||
if (_this.options.logs) console.log("[OPCommands] Command error: " + interaction.commandName); | ||
console.error(e); | ||
} | ||
}); | ||
} | ||
} | ||
|
||
module.exports = CommandHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
const Discord = require("discord.js"); | ||
const fs = require("fs"); | ||
const path = require("path"); | ||
|
||
/** | ||
* Event Handler. | ||
* @class | ||
* @param {*} _this | ||
* @param {String} eventsDir | ||
*/ | ||
class EventHandler { | ||
constructor(_this, eventsDir) { | ||
if (!_this) throw new Error("[OPCommands] Internal error: missing _this parameter on Event Handler."); | ||
if (!eventsDir) throw new Error("[OPCommands] Internal error: missing eventsDir parameter on Event Handler."); | ||
if (!fs.existsSync(eventsDir)) throw new Error("[OPCommands] Unexisting event directory."); | ||
|
||
const files = fs.readdirSync(eventsDir).filter(file => file.endsWith(".js")); | ||
|
||
if (_this.options.logs) console.log("[OPCommands] Loaded " + files.length + " events."); | ||
for (const file of files) { | ||
const eventFile = require(path.join(require.main.path, eventsDir, file)); | ||
if (eventFile.settings.once) { | ||
_this.client.once(eventFile.name, (...args) => eventFile.run(_this.client, ...args)); | ||
} else { | ||
_this.client.on(eventFile.name, (...args) => eventFile.run(_this.client, ...args)); | ||
}; | ||
} | ||
} | ||
} | ||
|
||
module.exports = EventHandler; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module.exports = { | ||
name: "say", | ||
description: "Says something.", | ||
options: [ | ||
{ | ||
type: 3, | ||
name: "input", | ||
description: "The input to return.", | ||
required: true | ||
} | ||
], | ||
limits: { | ||
owner: false, | ||
permissions: ["MANAGE_MESSAGES"], | ||
cooldown: "3s" | ||
}, | ||
run: (client, interaction) => { | ||
interaction.reply({ content: interaction.options.getString("input") }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module.exports = { | ||
name: "test", | ||
description: "Test command", | ||
limits: { | ||
owner: true, | ||
permissions: ["ADMINISTRATOR"], | ||
cooldown: "20s" | ||
}, | ||
run: (client, interaction) => { | ||
interaction.reply({ content: "test" }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
module.exports = { | ||
name: "ready", | ||
settings: { | ||
once: false | ||
}, | ||
run: (client) => { | ||
console.log("I'm online!"); | ||
client.user.setActivity("OPCommands"); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
const OPCommands = require("../src/OPCommands.js"); | ||
const Discord = require("discord.js"); | ||
const client = new Discord.Client({ | ||
intents: 32767 | ||
}); | ||
|
||
const handler = new OPCommands(client, { | ||
commandsDir: "commands", | ||
eventsDir: "events", | ||
logs: true | ||
}); | ||
handler.setBotOwner("OWNER_ID"); | ||
handler.setMessages({ | ||
ownerOnly: (interaction) => interaction.reply("Missing **Bot Owner** permission."), | ||
permissions: (interaction, perms) => interaction.reply(`You are missing the following permissions: **${perms.join(", ")}**`), | ||
cooldown: (interaction, cooldown) => interaction.reply(`You must wait **${cooldown}** before executing another command.`) | ||
}); | ||
|
||
client.login("BOT_TOKEN"); |