Class commands, improved sharding, and many other changes (#88)

* Load commands recursively

* Sort commands

* Missed a couple of spots

* missed even more spots apparently

* Ported commands in "fun" category to new class-based format, added babel eslint plugin

* Ported general commands, removed old/unneeded stuff, replaced moment with day, many more fixes I lost track of

* Missed a spot

* Removed unnecessary abort-controller package, add deprecation warning for mongo database

* Added imagereload, clarified premature end message

* Fixed docker-compose path issue, added total bot uptime to stats, more fixes for various parts

* Converted image commands into classes, fixed reload, ignore another WS event, cleaned up command handler and image runner

* Converted music/soundboard commands to class format

* Cleanup unnecessary logs

* awful tag command class port

* I literally somehow just learned that you can leave out the constructor in classes

* Pass client directly to commands/events, cleaned up command handler

* Migrated bot to eris-sharder, fixed some error handling stuff

* Remove unused modules

* Fixed type returning

* Switched back to Eris stable

* Some fixes and cleanup

* might wanna correct this

* Implement image command ratelimiting

* Added Bot token prefix, added imagestats, added running endpoint to API
This commit is contained in:
Essem 2021-04-12 11:16:12 -05:00 committed by GitHub
parent ff8a24d0e8
commit 40223ec8b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
291 changed files with 5296 additions and 5171 deletions

37
commands/fun/8ball.js Normal file
View file

@ -0,0 +1,37 @@
const Command = require("../../classes/command.js");
const { random } = require("../../utils/misc.js");
class EightBallCommand extends Command {
static responses = [
"It is certain",
"It is decidedly so",
"Without a doubt",
"Yes, definitely",
"You may rely on it",
"As I see it, yes",
"Most likely",
"Outlook good",
"Yes",
"Signs point to yes",
"Reply hazy, try again",
"Ask again later",
"Better not tell you now",
"Cannot predict now",
"Concentrate and ask again",
"Don't count on it",
"My reply is no",
"My sources say no",
"Outlook not so good",
"Very doubtful"
];
async run() {
return `🎱 ${random(EightBallCommand.responses)}`;
}
static description = "Asks the magic 8-ball a question";
static aliases = ["magicball", "magikball", "magic8ball", "magik8ball", "eightball"];
static arguments = ["{text}"];
}
module.exports = EightBallCommand;

23
commands/fun/bird.js Normal file
View file

@ -0,0 +1,23 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class BirdCommand extends Command {
async run() {
this.message.channel.sendTyping();
const imageData = await fetch("http://shibe.online/api/birds");
const json = await imageData.json();
return {
embed: {
color: 16711680,
image: {
url: json[0]
}
}
};
}
static description = "Gets a random bird picture";
static aliases = ["birb", "birds", "birbs"];
}
module.exports = BirdCommand;

28
commands/fun/cat.js Normal file
View file

@ -0,0 +1,28 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class CatCommand extends Command {
async run() {
this.message.channel.sendTyping();
const data = await fetch("https://api.thecatapi.com/v1/images/search?format=json", {
headers: {
"x-api-key": process.env.CAT
}
});
const json = await data.json();
return {
embed: {
color: 16711680,
image: {
url: json[0].url
}
}
};
}
static description = "Gets a random cat picture";
static aliases = ["kitters", "kitties", "kitty", "cattos", "catto", "cats", "cta"];
static requires = ["cat"];
}
module.exports = CatCommand;

22
commands/fun/cowsay.js Normal file
View file

@ -0,0 +1,22 @@
const cowsay = require("cowsay2");
const cows = require("cowsay2/cows");
const Command = require("../../classes/command.js");
class CowsayCommand extends Command {
async run() {
if (this.args.length === 0) {
return `${this.message.author.mention}, you need to provide some text for the cow to say!`;
} else if (cows[this.args[0].toLowerCase()] != undefined) {
const cow = cows[this.args.shift().toLowerCase()];
return `\`\`\`\n${cowsay.say(this.args.join(" "), { cow })}\n\`\`\``;
} else {
return `\`\`\`\n${cowsay.say(this.args.join(" "))}\n\`\`\``;
}
}
static description = "Makes an ASCII cow say a message";
static aliases = ["cow"];
static arguments = ["{cow}", "[text]"];
}
module.exports = CowsayCommand;

17
commands/fun/dice.js Normal file
View file

@ -0,0 +1,17 @@
const Command = require("../../classes/command.js");
class DiceCommand extends Command {
async run() {
if (this.args.length === 0 || !this.args[0].match(/^\d+$/)) {
return `🎲 The dice landed on ${Math.floor(Math.random() * 6) + 1}.`;
} else {
return `🎲 The dice landed on ${Math.floor(Math.random() * parseInt(this.args[0])) + 1}.`;
}
}
static description = "Rolls the dice";
static aliases = ["roll", "die", "rng", "random"];
static arguments = ["{number}"];
}
module.exports = DiceCommand;

24
commands/fun/dog.js Normal file
View file

@ -0,0 +1,24 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class DogCommand extends Command {
async run() {
this.message.channel.sendTyping();
const imageData = await fetch("https://dog.ceo/api/breeds/image/random");
const json = await imageData.json();
return {
embed: {
color: 16711680,
image: {
url: json.message
}
}
};
}
static description = "Gets a random dog picture";
static aliases = ["doggos", "doggo", "pupper", "puppers", "dogs", "puppy", "puppies", "pups", "pup"];
static arguments = ["{number}"];
}
module.exports = DogCommand;

14
commands/fun/fullwidth.js Normal file
View file

@ -0,0 +1,14 @@
const Command = require("../../classes/command.js");
class FullwidthCommand extends Command {
async run() {
if (this.args.length === 0) return `${this.message.author.mention}, you need to provide some text to convert to fullwidth!`;
return this.args.join("").replaceAll(/[A-Za-z0-9]/g, (s) => { return String.fromCharCode(s.charCodeAt(0) + 0xFEE0); });
}
static description = "Converts a message to fullwidth/aesthetic text";
static aliases = ["aesthetic", "aesthetics", "aes"];
static arguments = ["[text]"];
}
module.exports = FullwidthCommand;

20
commands/fun/homebrew.js Normal file
View file

@ -0,0 +1,20 @@
const ImageCommand = require("../../classes/imageCommand.js");
class HomebrewCommand extends ImageCommand {
params(args) {
return {
caption: args.join(" ").toLowerCase().replaceAll("\n", " ")
};
}
static description = "Creates a Homebrew Channel edit";
static aliases = ["hbc", "brew", "wiibrew"];
static arguments = ["[text]"];
static requiresImage = false;
static requiresText = true;
static noText = "you need to provide some text to make a Homebrew Channel edit!";
static command = "homebrew";
}
module.exports = HomebrewCommand;

20
commands/fun/mc.js Normal file
View file

@ -0,0 +1,20 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class MCCommand extends Command {
async run() {
if (this.args.length === 0) return `${this.message.author.mention}, you need to provide some text to generate a Minecraft achievement!`;
this.message.channel.sendTyping();
const request = await fetch(`https://www.minecraftskinstealer.com/achievement/a.php?i=13&h=Achievement+get%21&t=${encodeURIComponent(this.args.join("+"))}`);
return {
file: await request.buffer(),
name: "mc.png"
};
}
static description = "Generates a Minecraft achievement image";
static aliases = ["ach", "achievement", "minecraft"];
static arguments = ["[text]"];
}
module.exports = MCCommand;

39
commands/fun/retro.js Normal file
View file

@ -0,0 +1,39 @@
const magick = require("../../utils/image.js");
const wrap = require("../../utils/wrap.js");
const Command = require("../../classes/command.js");
class RetroCommand extends Command {
async run() {
if (this.args.length === 0) return `${this.message.author.mention}, you need to provide some text to generate some retro text!`;
this.message.channel.sendTyping();
let [line1, line2, line3] = this.args.join(" ").replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%").split(",").map(elem => elem.trim());
if (!line2 && line1.length > 15) {
const [split1, split2, split3] = wrap(line1, { width: 15, indent: "" }).split("\n");
line1 = split1;
line2 = split2 ? split2 : "";
line3 = split3 ? split3 : "";
} else {
if (!line2) {
line2 = "";
}
if (!line3) {
line3 = "";
}
}
const { buffer } = await magick.run({
cmd: "retro",
line1,
line2,
line3
});
return {
file: buffer,
name: "retro.png"
};
}
static description = "Generates a retro text image (separate lines with a comma)";
static arguments = ["[text]", "{middle text}", "{bottom text}"];
}
module.exports = RetroCommand;

34
commands/fun/rps.js Normal file
View file

@ -0,0 +1,34 @@
const misc = require("../../utils/misc.js");
const Command = require("../../classes/command.js");
class RPSCommand extends Command {
async run() {
if (this.args.length === 0 || (this.args[0] !== "rock" && this.args[0] !== "paper" && this.args[0] !== "scissors")) return `${this.message.author.mention}, you need to choose whether you want to be rock, paper, or scissors!`;
let emoji;
let winOrLose;
const result = misc.random(["rock", "paper", "scissors"]);
switch (result) {
case "rock":
emoji = "✊";
if (this.args[0].toLowerCase() === "paper") winOrLose = 1;
break;
case "paper":
emoji = "✋";
if (this.args[0].toLowerCase() === "scissors") winOrLose = 1;
break;
case "scissors":
emoji = "✌";
if (this.args[0].toLowerCase() === "rock") winOrLose = 1;
break;
default:
break;
}
return this.args[0].toLowerCase() === result ? `${emoji} I chose ${result}. It's a tie!` : `${emoji} I chose ${result}. ${winOrLose ? "You win!" : "You lose!"}`;
}
static description = "Plays rock, paper, scissors with me";
static aliases = ["rockpaperscissors"];
static arguments = ["[rock/paper/scissors]"];
}
module.exports = RPSCommand;

21
commands/fun/sonic.js Normal file
View file

@ -0,0 +1,21 @@
const wrap = require("../../utils/wrap.js");
const ImageCommand = require("../../classes/imageCommand.js");
class SonicCommand extends ImageCommand {
params(args) {
const cleanedMessage = args.join(" ").replaceAll("&", "\\&amp;").replaceAll(">", "\\&gt;").replaceAll("<", "\\&lt;").replaceAll("\"", "\\&quot;").replaceAll("'", "\\&apos;").replaceAll("%", "\\%");
return {
text: wrap(cleanedMessage, {width: 15, indent: ""})
};
}
static description = "Creates a Sonic speech bubble image";
static arguments = ["[text]"];
static requiresImage = false;
static requiresText = true;
static noText = "you need to provide some text to make a Sonic meme!";
static command = "sonic";
}
module.exports = SonicCommand;

28
commands/fun/wikihow.js Normal file
View file

@ -0,0 +1,28 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class WikihowCommand extends Command {
async run() {
this.message.channel.sendTyping();
const request = await fetch("https://hargrimm-wikihow-v1.p.rapidapi.com/images?count=1", {
headers: {
"X-RapidAPI-Key": process.env.MASHAPE,
"X-RapidAPI-Host": "hargrimm-wikihow-v1.p.rapidapi.com",
"Accept": "application/json"
}
});
const json = await request.json();
const image = await fetch(json["1"]);
const imageBuffer = await image.buffer();
return {
file: imageBuffer,
name: json["1"].split("/")[json["1"].split("/").length - 1]
};
}
static description = "Gets a random WikiHow image";
static aliases = ["wiki"];
static requires = ["mashape"];
}
module.exports = WikihowCommand;

31
commands/fun/xkcd.js Normal file
View file

@ -0,0 +1,31 @@
const fetch = require("node-fetch");
const Command = require("../../classes/command.js");
class XKCDCommand extends Command {
async run() {
const url = this.args.length > 0 && this.args[0].match(/^\d+$/) ? `http://xkcd.com/${this.args[0]}/info.0.json` : "http://xkcd.com/info.0.json";
try {
const request = await fetch(url);
const json = await request.json();
const embed = {
"embed": {
"title": json.safe_title,
"url": `https://xkcd.com/${json.num}`,
"color": 16711680,
"description": json.alt,
"image": {
"url": json.img
}
}
};
return embed;
} catch {
return `${this.message.author.mention}, I couldn't get that XKCD!`;
}
}
static description = "Gets an XKCD comic";
static arguments = ["{id}"];
}
module.exports = XKCDCommand;