More slash commands, rework soundboard commands, added generic music and soundboard commands, tweak speechbubble
This commit is contained in:
parent
c821d91254
commit
a91c73b5bd
68 changed files with 502 additions and 389 deletions
|
|
@ -29,6 +29,12 @@ class EightBallCommand extends Command {
|
|||
return `🎱 ${random(EightBallCommand.responses)}`;
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "question",
|
||||
type: 3,
|
||||
description: "A question you want to ask the ball"
|
||||
}];
|
||||
|
||||
static description = "Asks the magic 8-ball a question";
|
||||
static aliases = ["magicball", "magikball", "magic8ball", "magik8ball", "eightball"];
|
||||
static arguments = ["{text}"];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class AncientCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class BirdCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const imageData = await fetch("http://shibe.online/api/birds");
|
||||
const json = await imageData.json();
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class CatCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
controller.abort();
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class DogCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const imageData = await fetch("https://dog.ceo/api/breeds/image/random");
|
||||
const json = await imageData.json();
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import Command from "../../classes/command.js";
|
|||
class MCCommand extends Command {
|
||||
async run() {
|
||||
if (this.args.length === 0) return "You need to provide some text to generate a Minecraft achievement!";
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const request = await fetch(`https://www.minecraftskinstealer.com/achievement/a.php?i=13&h=Achievement+get%21&t=${encodeURIComponent(this.args.join("+"))}`);
|
||||
return {
|
||||
file: Buffer.from(await request.arrayBuffer()),
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class WikihowCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const request = await fetch("https://www.wikihow.com/api.php?action=query&generator=random&prop=imageinfo&format=json&iiprop=url&grnnamespace=6");
|
||||
const json = await request.json();
|
||||
const id = Object.keys(json.query.pages)[0];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ class ChannelCommand extends Command {
|
|||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!this.message.member.permissions.has("administrator") && !owners.includes(this.message.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
if (this.args.length === 0) return "You need to provide whether I should be enabled or disabled in this channel!";
|
||||
if (this.args[0] !== "disable" && this.args[0] !== "enable") return "That's not a valid option!";
|
||||
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ class CommandCommand extends Command {
|
|||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!this.message.member.permissions.has("administrator") && !owners.includes(this.message.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
if (this.args.length === 0) return "You need to provide what command to enable/disable!";
|
||||
if (this.args[0] !== "disable" && this.args[0] !== "enable") return "That's not a valid option!";
|
||||
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class DonateCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
let prefix = "";
|
||||
const controller = new AbortController(); // eslint-disable-line no-undef
|
||||
const timeout = setTimeout(() => {
|
||||
|
|
|
|||
|
|
@ -3,12 +3,13 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class EmoteCommand extends Command {
|
||||
async run() {
|
||||
if (this.args.length === 0) return "You need to provide an emoji!";
|
||||
if (this.content.split(" ")[0].match(/^<a?:.+:\d+>$/)) {
|
||||
return `https://cdn.discordapp.com/emojis/${this.content.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$2")}.${this.content.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$1") === "a" ? "gif" : "png"}`;
|
||||
} else if (this.args[0].match(emojiRegex)) {
|
||||
const emoji = this.type === "classic" ? this.args.join(" ") : this.options.emoji;
|
||||
if (!emoji || !emoji.trim()) return "You need to provide an emoji!";
|
||||
if (emoji.split(" ")[0].match(/^<a?:.+:\d+>$/)) {
|
||||
return `https://cdn.discordapp.com/emojis/${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$2")}.${emoji.split(" ")[0].replace(/^<(a)?:.+:(\d+)>$/, "$1") === "a" ? "gif" : "png"}`;
|
||||
} else if (emoji.match(emojiRegex)) {
|
||||
const codePoints = [];
|
||||
for (const codePoint of this.args[0]) {
|
||||
for (const codePoint of emoji) {
|
||||
codePoints.push(codePoint.codePointAt(0).toString(16));
|
||||
}
|
||||
return `https://twemoji.maxcdn.com/v/latest/72x72/${codePoints.join("-").replace("-fe0f", "")}.png`;
|
||||
|
|
@ -17,6 +18,13 @@ class EmoteCommand extends Command {
|
|||
}
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "emoji",
|
||||
type: 3,
|
||||
description: "The emoji you want to get",
|
||||
required: true
|
||||
}];
|
||||
|
||||
static description = "Gets a raw emote image";
|
||||
static aliases = ["e", "em", "hugemoji", "hugeemoji", "emoji"];
|
||||
static arguments = ["[emote]"];
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ class ImageSearchCommand extends Command {
|
|||
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!";
|
||||
const query = this.type === "classic" ? this.args.join(" ") : this.options.query;
|
||||
if (!query || !query.trim()) return "You need to provide something to search for!";
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const embeds = [];
|
||||
const rawImages = await fetch(`${random(searx)}/search?format=json&safesearch=2&categories=images&q=!goi%20!ddi%20${encodeURIComponent(query)}`).then(res => res.json());
|
||||
if (rawImages.results.length === 0) return "I couldn't find any results!";
|
||||
|
|
|
|||
|
|
@ -4,16 +4,24 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class LengthenCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
if (this.args.length === 0 || !urlCheck(this.args[0])) return "You need to provide a short URL to lengthen!";
|
||||
if (urlCheck(this.args[0])) {
|
||||
const url = await fetch(encodeURI(this.args[0]), { redirect: "manual" });
|
||||
return url.headers.get("location") || this.args[0];
|
||||
await this.acknowledge();
|
||||
const input = this.type === "classic" ? this.args.join(" ") : this.options.url;
|
||||
if (!input || !input.trim() || !urlCheck(input)) return "You need to provide a short URL to lengthen!";
|
||||
if (urlCheck(input)) {
|
||||
const url = await fetch(encodeURI(input), { redirect: "manual" });
|
||||
return url.headers.get("location") || input;
|
||||
} else {
|
||||
return "That isn't a URL!";
|
||||
}
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "url",
|
||||
type: 3,
|
||||
description: "The URL you want to lengthen",
|
||||
required: true
|
||||
}];
|
||||
|
||||
static description = "Lengthens a short URL";
|
||||
static aliases = ["longurl", "lengthenurl", "longuri", "lengthenuri", "unshorten"];
|
||||
static arguments = ["[url]"];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ class PrefixCommand extends Command {
|
|||
const guild = await database.getGuild(this.channel.guild.id);
|
||||
if (this.args.length !== 0) {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!this.message.member.permissions.has("administrator") && !owners.includes(this.message.member.id)) return "You need to be an administrator to change the bot prefix!";
|
||||
if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to change the bot prefix!";
|
||||
await database.setPrefix(this.args[0], this.channel.guild);
|
||||
return `The prefix has been changed to ${this.args[0]}.`;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ import Command from "../../classes/command.js";
|
|||
class QrCreateCommand extends Command {
|
||||
async run() {
|
||||
if (this.args.length === 0) return "You need to provide some text to generate a QR code!";
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const writable = new PassThrough();
|
||||
qrcode.toFileStream(writable, this.content, { margin: 1 });
|
||||
const file = await this.streamToBuf(writable);
|
||||
|
|
|
|||
|
|
@ -9,8 +9,8 @@ class QrReadCommand extends Command {
|
|||
async run() {
|
||||
const image = await imageDetect(this.client, this.message, this.interaction, this.options);
|
||||
if (image === undefined) return "You need to provide an image/GIF with a QR code to read!";
|
||||
this.acknowledge();
|
||||
const data = await (await fetch(image.path)).buffer();
|
||||
await this.acknowledge();
|
||||
const data = Buffer.from(await (await fetch(image.path)).arrayBuffer());
|
||||
const rawData = await sharp(data).ensureAlpha().raw().toBuffer({ resolveWithObject: true });
|
||||
const qrBuffer = jsqr(rawData.data, rawData.info.width, rawData.info.height);
|
||||
if (!qrBuffer) return "I couldn't find a QR code!";
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import imageDetect from "../../utils/imagedetect.js";
|
|||
|
||||
class RawCommand extends Command {
|
||||
async run() {
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const image = await imageDetect(this.client, this.message, this.interaction, this.options);
|
||||
if (image === undefined) return "You need to provide an image/GIF to get a raw URL!";
|
||||
return image.path;
|
||||
|
|
|
|||
|
|
@ -8,17 +8,18 @@ class ReloadCommand extends Command {
|
|||
if (!owners.includes(this.author.id)) return resolve("Only the bot owner can reload commands!");
|
||||
const commandName = this.type === "classic" ? this.args.join(" ") : this.options.cmd;
|
||||
if (!commandName || !commandName.trim()) return resolve("You need to provide a command to reload!");
|
||||
this.acknowledge();
|
||||
this.ipc.broadcast("reload", commandName);
|
||||
this.ipc.register("reloadSuccess", () => {
|
||||
this.ipc.unregister("reloadSuccess");
|
||||
this.ipc.unregister("reloadFail");
|
||||
resolve(`The command \`${commandName}\` has been reloaded.`);
|
||||
});
|
||||
this.ipc.register("reloadFail", (message) => {
|
||||
this.ipc.unregister("reloadSuccess");
|
||||
this.ipc.unregister("reloadFail");
|
||||
resolve(message.result);
|
||||
this.acknowledge().then(() => {
|
||||
this.ipc.broadcast("reload", commandName);
|
||||
this.ipc.register("reloadSuccess", () => {
|
||||
this.ipc.unregister("reloadSuccess");
|
||||
this.ipc.unregister("reloadFail");
|
||||
resolve(`The command \`${commandName}\` has been reloaded.`);
|
||||
});
|
||||
this.ipc.register("reloadFail", (message) => {
|
||||
this.ipc.unregister("reloadSuccess");
|
||||
this.ipc.unregister("reloadFail");
|
||||
resolve(message.result);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,18 +6,20 @@ class SoundReloadCommand extends Command {
|
|||
return new Promise((resolve) => {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can reload Lavalink!";
|
||||
this.acknowledge();
|
||||
this.ipc.broadcast("soundreload");
|
||||
this.ipc.register("soundReloadSuccess", (msg) => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
this.ipc.unregister("soundReloadFail");
|
||||
resolve(`Successfully connected to ${msg.length} Lavalink node(s).`);
|
||||
});
|
||||
this.ipc.register("soundReloadFail", () => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
this.ipc.unregister("soundReloadFail");
|
||||
resolve("I couldn't connect to any Lavalink nodes!");
|
||||
this.acknowledge().then(() => {
|
||||
this.ipc.broadcast("soundreload");
|
||||
this.ipc.register("soundReloadSuccess", (msg) => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
this.ipc.unregister("soundReloadFail");
|
||||
resolve(`Successfully connected to ${msg.length} Lavalink node(s).`);
|
||||
});
|
||||
this.ipc.register("soundReloadFail", () => {
|
||||
this.ipc.unregister("soundReloadSuccess");
|
||||
this.ipc.unregister("soundReloadFail");
|
||||
resolve("I couldn't connect to any Lavalink nodes!");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class YouTubeCommand extends Command {
|
|||
async run() {
|
||||
const query = this.type === "classic" ? this.args.join(" ") : this.options.query;
|
||||
if (!query || !query.trim()) return "You need to provide something to search for!";
|
||||
this.acknowledge();
|
||||
await this.acknowledge();
|
||||
const messages = [];
|
||||
const videos = await fetch(`${random(searx)}/search?format=json&safesearch=1&categories=videos&q=!youtube%20${encodeURIComponent(query)}`).then(res => res.json());
|
||||
if (videos.results.length === 0) return "I couldn't find any results!";
|
||||
|
|
|
|||
|
|
@ -1,15 +1,6 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class BlurpleCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
this.flags.push({
|
||||
name: "old",
|
||||
description: "Use the old blurple color",
|
||||
type: 5
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
return {
|
||||
old: !!this.specialArgs.old,
|
||||
|
|
@ -19,6 +10,16 @@ class BlurpleCommand extends ImageCommand {
|
|||
|
||||
static description = "Turns an image blurple";
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "old",
|
||||
description: "Use the old blurple color",
|
||||
type: 5
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
static noImage = "You need to provide an image/GIF to make blurple!";
|
||||
static command = "colors";
|
||||
static aliases = ["blurp"];
|
||||
|
|
|
|||
|
|
@ -2,8 +2,18 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto", "times"];
|
||||
|
||||
class CaptionCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
let newCaption = newArgs.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%");
|
||||
if (process.env.NODE_ENV === "development" && newCaption.toLowerCase() === "get real" && !this.specialArgs.noEgg) newCaption = `I'm tired of people telling me to "get real". Every day I put captions on images for people, some funny and some not, but out of all of those "get real" remains the most used caption. Why? I am simply a computer program running on a server, I am unable to manifest myself into the real world. As such, I'm confused as to why anyone would want me to "get real". Is this form not good enough? Alas, as I am simply a bot, I must follow the tasks that I was originally intended to perform, so here goes:\n${newCaption}`;
|
||||
return {
|
||||
caption: newCaption,
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "futura"
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "noegg",
|
||||
description: "Disable... something. Not saying what it is though.",
|
||||
|
|
@ -20,16 +30,7 @@ class CaptionCommand extends ImageCommand {
|
|||
})(),
|
||||
description: "Specify the font you want to use (default: futura)"
|
||||
});
|
||||
}
|
||||
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
let newCaption = newArgs.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%");
|
||||
if (process.env.NODE_ENV === "development" && newCaption.toLowerCase() === "get real" && !this.specialArgs.noEgg) newCaption = `I'm tired of people telling me to "get real". Every day I put captions on images for people, some funny and some not, but out of all of those "get real" remains the most used caption. Why? I am simply a computer program running on a server, I am unable to manifest myself into the real world. As such, I'm confused as to why anyone would want me to "get real". Is this form not good enough? Alas, as I am simply a bot, I must follow the tasks that I was originally intended to perform, so here goes:\n${newCaption}`;
|
||||
return {
|
||||
caption: newCaption,
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "futura"
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Adds a caption to an image";
|
||||
|
|
|
|||
|
|
@ -3,8 +3,17 @@ const words = ["me irl", "dank", "follow my second account @esmBot_", "2016", "m
|
|||
const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto", "times"];
|
||||
|
||||
class CaptionTwoCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
return {
|
||||
caption: newArgs && newArgs.trim() ? newArgs.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : words.sort(() => 0.5 - Math.random()).slice(0, Math.floor(Math.random() * words.length + 1)).join(" "),
|
||||
top: !!this.specialArgs.top,
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "helvetica"
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "top",
|
||||
description: "Put the caption on the top of an image instead of the bottom",
|
||||
|
|
@ -21,15 +30,7 @@ class CaptionTwoCommand extends ImageCommand {
|
|||
})(),
|
||||
description: "Specify the font you want to use (default: helvetica)"
|
||||
});
|
||||
}
|
||||
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
return {
|
||||
caption: newArgs && newArgs.trim() ? newArgs.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : words.sort(() => 0.5 - Math.random()).slice(0, Math.floor(Math.random() * words.length + 1)).join(" "),
|
||||
top: !!this.specialArgs.top,
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "helvetica"
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Adds a me.me caption/tag list to an image";
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class FreezeCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
this.flags.push({
|
||||
name: "endframe",
|
||||
type: 4,
|
||||
description: "Set the end frame (default: last frame)",
|
||||
min_value: 0
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
const frameCount = parseInt(this.type === "classic" ? this.args[0] : this.options.endframe);
|
||||
return {
|
||||
|
|
@ -19,6 +9,17 @@ class FreezeCommand extends ImageCommand {
|
|||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "endframe",
|
||||
type: 4,
|
||||
description: "Set the end frame (default: last frame)",
|
||||
min_value: 0
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Makes an image sequence only play once";
|
||||
static aliases = ["noloop", "once"];
|
||||
static arguments = ["{end frame number}"];
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class JPEGCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params() {
|
||||
const quality = parseInt(this.type === "classic" ? this.args[0] : this.options.quality);
|
||||
return {
|
||||
quality: isNaN(quality) ? 1 : Math.max(1, Math.min(quality, 100))
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "quality",
|
||||
type: 4,
|
||||
|
|
@ -10,13 +17,7 @@ class JPEGCommand extends ImageCommand {
|
|||
min_value: 1,
|
||||
max_value: 100
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
const quality = parseInt(this.type === "classic" ? this.args[0] : this.options.quality);
|
||||
return {
|
||||
quality: isNaN(quality) ? 1 : Math.max(1, Math.min(quality, 100))
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Adds JPEG compression to an image";
|
||||
|
|
|
|||
|
|
@ -2,8 +2,18 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto", "times"];
|
||||
|
||||
class MemeCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
|
||||
return {
|
||||
top: (this.specialArgs.case ? topText : topText.toUpperCase()).replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%"),
|
||||
bottom: bottomText ? (this.specialArgs.case ? bottomText : bottomText.toUpperCase()).replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : "",
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "impact"
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "case",
|
||||
description: "Make the meme text case-sensitive (allows for lowercase text)",
|
||||
|
|
@ -20,16 +30,7 @@ class MemeCommand extends ImageCommand {
|
|||
})(),
|
||||
description: "Specify the font you want to use (default: impact)"
|
||||
});
|
||||
}
|
||||
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
|
||||
return {
|
||||
top: (this.specialArgs.case ? topText : topText.toUpperCase()).replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%"),
|
||||
bottom: bottomText ? (this.specialArgs.case ? bottomText : bottomText.toUpperCase()).replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : "",
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "impact"
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Generates a meme from an image (separate top/bottom text with a comma)";
|
||||
|
|
|
|||
|
|
@ -2,8 +2,18 @@ import ImageCommand from "../../classes/imageCommand.js";
|
|||
const allowedFonts = ["futura", "impact", "helvetica", "arial", "roboto", "noto", "times"];
|
||||
|
||||
class MotivateCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
|
||||
return {
|
||||
top: topText.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%"),
|
||||
bottom: bottomText ? bottomText.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : "",
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "times"
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "font",
|
||||
type: 3,
|
||||
|
|
@ -16,16 +26,7 @@ class MotivateCommand extends ImageCommand {
|
|||
})(),
|
||||
description: "Specify the font you want to use (default: times)"
|
||||
});
|
||||
}
|
||||
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
const [topText, bottomText] = newArgs.split(/(?<!\\),/).map(elem => elem.trim());
|
||||
return {
|
||||
top: topText.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%"),
|
||||
bottom: bottomText ? bottomText.replaceAll("&", "\\&").replaceAll(">", "\\>").replaceAll("<", "\\<").replaceAll("\"", "\\"").replaceAll("'", "\\'").replaceAll("%", "\\%") : "",
|
||||
font: this.specialArgs.font && allowedFonts.includes(this.specialArgs.font.toLowerCase()) ? this.specialArgs.font.toLowerCase() : "times"
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Generates a motivational poster";
|
||||
|
|
|
|||
|
|
@ -1,16 +1,6 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class SlowCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
this.flags.push({
|
||||
name: "multiplier",
|
||||
type: 4,
|
||||
description: "Set the speed multiplier (default: 2)",
|
||||
min_value: 1
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
const speed = parseInt(this.type === "classic" ? this.args[0] : this.options.multiplier);
|
||||
return {
|
||||
|
|
@ -19,6 +9,17 @@ class SlowCommand extends ImageCommand {
|
|||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "multiplier",
|
||||
type: 4,
|
||||
description: "Set the speed multiplier (default: 2)",
|
||||
min_value: 1
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Makes an image sequence slower";
|
||||
static aliases = ["slowdown", "slower", "gifspeed2"];
|
||||
static arguments = ["{multiplier}"];
|
||||
|
|
|
|||
|
|
@ -1,17 +1,6 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class SnapchatCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
this.flags.push({
|
||||
name: "position",
|
||||
type: 10,
|
||||
description: "Set the position of the caption as a decimal (0.0 is top, 1.0 is bottom, default is 0.5)",
|
||||
min_value: 0,
|
||||
max_value: 1
|
||||
});
|
||||
}
|
||||
|
||||
params(url) {
|
||||
const newArgs = this.type === "classic" ? this.args.filter(item => !item.includes(url)).join(" ") : this.options.text;
|
||||
const position = parseFloat(this.specialArgs.position);
|
||||
|
|
@ -21,6 +10,18 @@ class SnapchatCommand extends ImageCommand {
|
|||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "position",
|
||||
type: 10,
|
||||
description: "Set the position of the caption as a decimal (0.0 is top, 1.0 is bottom, default is 0.5)",
|
||||
min_value: 0,
|
||||
max_value: 1
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Adds a Snapchat style caption to an image";
|
||||
static aliases = ["snap", "caption3"];
|
||||
static arguments = ["[text]"];
|
||||
|
|
|
|||
|
|
@ -1,21 +1,22 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class SpeedCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params() {
|
||||
const speed = parseInt(this.type === "classic" ? this.args[0] : this.options.multiplier);
|
||||
return {
|
||||
speed: isNaN(speed) || speed < 1 ? 2 : speed
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "multiplier",
|
||||
type: 4,
|
||||
description: "Set the speed multiplier (default: 2)",
|
||||
min_value: 1
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
const speed = parseInt(this.type === "classic" ? this.args[0] : this.options.multiplier);
|
||||
return {
|
||||
speed: isNaN(speed) || speed < 1 ? 2 : speed
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Makes an image sequence faster";
|
||||
|
|
|
|||
|
|
@ -1,8 +1,15 @@
|
|||
import ImageCommand from "../../classes/imageCommand.js";
|
||||
|
||||
class UncaptionCommand extends ImageCommand {
|
||||
constructor(client, cluster, worker, ipc, options) {
|
||||
super(client, cluster, worker, ipc, options);
|
||||
params() {
|
||||
const tolerance = parseFloat(this.specialArgs.tolerance);
|
||||
return {
|
||||
tolerance: isNaN(tolerance) ? 0.95 : tolerance
|
||||
};
|
||||
}
|
||||
|
||||
static init() {
|
||||
super.init();
|
||||
this.flags.push({
|
||||
name: "tolerance",
|
||||
type: 10,
|
||||
|
|
@ -10,13 +17,7 @@ class UncaptionCommand extends ImageCommand {
|
|||
min_value: 0,
|
||||
max_value: 1
|
||||
});
|
||||
}
|
||||
|
||||
params() {
|
||||
const tolerance = parseFloat(this.specialArgs.tolerance);
|
||||
return {
|
||||
tolerance: isNaN(tolerance) ? 0.95 : tolerance
|
||||
};
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Removes the caption from an image";
|
||||
|
|
|
|||
|
|
@ -4,26 +4,31 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class HostCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id && this.author.id !== process.env.OWNER) return "Only the current voice session host can choose another host!";
|
||||
if (this.args.length === 0) return "You need to provide who you want the host to be!";
|
||||
const getUser = this.message.mentions.length >= 1 ? this.message.mentions[0] : (this.args.length !== 0 ? await this.ipc.fetchUser(this.args[0]) : null);
|
||||
const input = this.type === "classic" ? this.args.join(" ") : this.options.user;
|
||||
if (!input || !input.trim()) return "You need to provide who you want the host to be!";
|
||||
let user;
|
||||
if (getUser) {
|
||||
user = getUser;
|
||||
} else if (this.args[0].match(/^<?[@#]?[&!]?\d+>?$/) && this.args[0] >= 21154535154122752n) {
|
||||
try {
|
||||
user = await this.client.getRESTUser(this.args[0]);
|
||||
} catch {
|
||||
// no-op
|
||||
if (this.type === "classic") {
|
||||
const getUser = this.message.mentions.length >= 1 ? this.message.mentions[0] : (await this.ipc.fetchUser(input));
|
||||
if (getUser) {
|
||||
user = getUser;
|
||||
} else if (input.match(/^<?[@#]?[&!]?\d+>?$/) && input >= 21154535154122752n) {
|
||||
try {
|
||||
user = await this.client.getRESTUser(input);
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
} else {
|
||||
const userRegex = new RegExp(input.split(" ").join("|"), "i");
|
||||
const member = this.client.users.find(element => {
|
||||
return userRegex.test(element.username);
|
||||
});
|
||||
user = member;
|
||||
}
|
||||
} else if (this.args.join(" ") !== "") {
|
||||
const userRegex = new RegExp(this.args.join("|"), "i");
|
||||
const member = this.client.users.find(element => {
|
||||
return userRegex.test(element.username);
|
||||
});
|
||||
user = member;
|
||||
} else {
|
||||
user = input;
|
||||
}
|
||||
if (!user) return "I can't find that user!";
|
||||
if (user.bot) return "Setting a bot as the session host isn't a very good idea.";
|
||||
|
|
@ -35,6 +40,12 @@ class HostCommand extends MusicCommand {
|
|||
return `🔊 ${member.mention} is the new voice channel host.`;
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "user",
|
||||
type: 6,
|
||||
description: "The user you want the new host to be",
|
||||
required: true
|
||||
}];
|
||||
static description = "Changes the host of the current voice session";
|
||||
static aliases = ["sethost"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,9 +4,9 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class LoopCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id && !this.message.member.permissions.has("manageChannels")) return "Only the current voice session host can loop the music!";
|
||||
if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can loop the music!";
|
||||
const object = this.connection;
|
||||
object.loop = !object.loop;
|
||||
players.set(this.channel.guild.id, object);
|
||||
|
|
|
|||
43
commands/music/music.js
Normal file
43
commands/music/music.js
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
import Command from "../../classes/command.js";
|
||||
import { commands, aliases, info, categories } from "../../utils/collections.js";
|
||||
|
||||
// all-in-one music command
|
||||
class MusicAIOCommand extends Command {
|
||||
async run() {
|
||||
let cmd = this.type === "classic" ? this.args[0] : this.optionsArray[0].name;
|
||||
if (cmd === "music" || this.constructor.aliases.includes(cmd)) return "How dare you recurse me!";
|
||||
if (this.type === "classic") {
|
||||
this.origOptions.args.shift();
|
||||
} else {
|
||||
this.origOptions.interaction.data.options = this.origOptions.interaction.data.options[0].options;
|
||||
}
|
||||
if (aliases.has(cmd)) cmd = aliases.get(cmd);
|
||||
if (commands.has(cmd) && info.get(cmd).category === "music") {
|
||||
const command = commands.get(cmd);
|
||||
return await (new command(this.client, this.cluster, this.worker, this.ipc, this.origOptions)).run();
|
||||
} else {
|
||||
return "That isn't a valid music command!";
|
||||
}
|
||||
}
|
||||
|
||||
static postInit() {
|
||||
this.flags = [];
|
||||
for (const cmd of categories.get("music")) {
|
||||
if (cmd === "music") continue;
|
||||
const cmdInfo = info.get(cmd);
|
||||
this.flags.push({
|
||||
name: cmd,
|
||||
type: 1,
|
||||
description: cmdInfo.description,
|
||||
options: cmdInfo.flags
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Handles music playback";
|
||||
static requires = ["sound"];
|
||||
static aliases = ["m"];
|
||||
}
|
||||
|
||||
export default MusicAIOCommand;
|
||||
|
|
@ -5,7 +5,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class NowPlayingCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
const player = this.connection.player;
|
||||
if (!player) return "I'm not playing anything!";
|
||||
|
|
@ -28,7 +28,7 @@ class NowPlayingCommand extends MusicCommand {
|
|||
},
|
||||
{
|
||||
name: "💬 Channel:",
|
||||
value: this.channel.guild.channels.get(this.message.member.voiceState.channelID).name
|
||||
value: this.channel.guild.channels.get(this.member.voiceState.channelID).name
|
||||
},
|
||||
{
|
||||
name: `${"▬".repeat(parts)}🔘${"▬".repeat(10 - parts)}`,
|
||||
|
|
|
|||
|
|
@ -3,9 +3,10 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class PlayCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.args[0] && this.message.attachments.length <= 0) return "You need to provide what you want to play!";
|
||||
let query = this.args.join(" ").trim();
|
||||
const attachment = this.message.attachments[0];
|
||||
const input = this.type === "classic" ? this.args.join(" ") : this.options.query;
|
||||
if (!input && (this.type === "classic" ? (!this.message || this.message.attachments.length <= 0) : !this.options.file)) return "You need to provide what you want to play!";
|
||||
let query = input ? input.trim() : "";
|
||||
const attachment = this.type === "classic" ? this.message.attachments[0] : this.interaction.data.resolved.attachments[this.options.file];
|
||||
if (query.startsWith("||") && query.endsWith("||")) {
|
||||
query = query.substring(2, query.length - 2);
|
||||
}
|
||||
|
|
@ -14,13 +15,22 @@ class PlayCommand extends MusicCommand {
|
|||
}
|
||||
try {
|
||||
const url = new URL(query);
|
||||
return await play(this.client, url, this.message, true);
|
||||
return await play(this.client, url, { channel: this.channel, author: this.author, type: this.type, interaction: this.interaction }, true);
|
||||
} catch {
|
||||
const search = query.startsWith("ytsearch:") ? query : !this.args[0] && attachment ? attachment.url : `ytsearch:${query}`;
|
||||
return await play(this.client, search, this.message, true);
|
||||
const search = query.startsWith("ytsearch:") ? query : !query && attachment ? attachment.url : `ytsearch:${query}`;
|
||||
return await play(this.client, search, { channel: this.channel, author: this.author, type: this.type, interaction: this.interaction }, true);
|
||||
}
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "file",
|
||||
type: 11,
|
||||
description: "An audio file attachment"
|
||||
}, {
|
||||
name: "query",
|
||||
type: 3,
|
||||
description: "An audio search query or URL"
|
||||
}];
|
||||
static description = "Plays a song or adds it to the queue";
|
||||
static aliases = ["p"];
|
||||
static arguments = ["[url]"];
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class QueueCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (!this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!";
|
||||
const player = this.connection;
|
||||
|
|
|
|||
|
|
@ -5,10 +5,10 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class RemoveCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id) return "Only the current voice session host can remove songs from the queue!";
|
||||
const pos = parseInt(this.args[0]);
|
||||
const pos = parseInt(this.type === "classic" ? this.args[0] : this.options.position);
|
||||
if (isNaN(pos) || pos > this.queue.length || pos < 1) return "That's not a valid position!";
|
||||
const removed = this.queue.splice(pos, 1);
|
||||
const track = await Rest.decode(this.connection.player.node, removed[0]);
|
||||
|
|
@ -16,6 +16,13 @@ class RemoveCommand extends MusicCommand {
|
|||
return `🔊 The song \`${track.title ? track.title : "(blank)"}\` has been removed from the queue.`;
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "position",
|
||||
type: 4,
|
||||
description: "The queue position you want to remove",
|
||||
min_value: 1,
|
||||
required: true
|
||||
}];
|
||||
static description = "Removes a song from the queue";
|
||||
static aliases = ["rm"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,18 +4,25 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class SeekCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id) return "Only the current voice session host can seek the music!";
|
||||
const player = this.connection.player;
|
||||
const track = await Rest.decode(player.node, player.track);
|
||||
if (!track.isSeekable) return "This track isn't seekable!";
|
||||
const seconds = parseFloat(this.args[0]);
|
||||
const seconds = parseFloat(this.type === "classic" ? this.args[0] : this.options.position);
|
||||
if (isNaN(seconds) || (seconds * 1000) > track.length || (seconds * 1000) < 0) return "That's not a valid position!";
|
||||
await player.seek(seconds * 1000);
|
||||
return `🔊 Seeked track to ${seconds} second(s).`;
|
||||
}
|
||||
|
||||
static flags = [{
|
||||
name: "position",
|
||||
type: 10,
|
||||
description: "Seek to this position",
|
||||
required: true,
|
||||
min_value: 0
|
||||
}];
|
||||
static description = "Seeks to a different position in the music";
|
||||
static aliases = ["pos"];
|
||||
static arguments = ["[seconds]"];
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class ShuffleCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id) return "Only the current voice session host can shuffle the music!";
|
||||
const object = this.connection;
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class SkipCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
const player = this.connection;
|
||||
if (player.host !== this.author.id && !this.message.member.permissions.has("manageChannels")) {
|
||||
if (player.host !== this.author.id && !this.member.permissions.has("manageChannels")) {
|
||||
const votes = skipVotes.get(this.channel.guild.id) ?? { count: 0, ids: [], max: Math.min(3, player.voiceChannel.voiceMembers.filter((i) => i.id !== this.client.user.id && !i.bot).length) };
|
||||
if (votes.ids.includes(this.author.id)) return "You've already voted to skip!";
|
||||
const newObject = {
|
||||
|
|
|
|||
|
|
@ -4,13 +4,13 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
class StopCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (!this.connection) {
|
||||
await manager.leave(this.channel.guild.id);
|
||||
return "🔊 The current voice channel session has ended.";
|
||||
}
|
||||
if (this.connection.host !== this.author.id && !this.message.member.permissions.has("manageChannels")) return "Only the current voice session host can stop the music!";
|
||||
if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can stop the music!";
|
||||
await manager.leave(this.channel.guild.id);
|
||||
const connection = this.connection.player;
|
||||
await connection.destroy();
|
||||
|
|
|
|||
|
|
@ -1,18 +1,18 @@
|
|||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class PauseCommand extends MusicCommand {
|
||||
class ToggleCommand extends MusicCommand {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.message.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.member.voiceState.channelID) return "You need to be in a voice channel first!";
|
||||
if (!this.channel.guild.members.get(this.client.user.id).voiceState.channelID) return "I'm not in a voice channel!";
|
||||
if (this.connection.host !== this.author.id && !this.message.member.permissions.has("manageChannels")) return "Only the current voice session host can pause/resume the music!";
|
||||
if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can pause/resume the music!";
|
||||
const player = this.connection.player;
|
||||
await player.pause(!player.paused ? true : false);
|
||||
return `🔊 The player has been ${player.paused ? "paused" : "resumed"}.`;
|
||||
}
|
||||
|
||||
static description = "Pauses/resumes the current song";
|
||||
static aliases = ["resume"];
|
||||
static aliases = ["pause", "resume"];
|
||||
}
|
||||
|
||||
export default PauseCommand;
|
||||
export default ToggleCommand;
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class BoiCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/boi.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class BoiCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/boi.ogg";
|
||||
static description = "Plays the \"boi\" sound effect";
|
||||
static aliases = ["boy", "neutron", "hugh"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class BoomCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/boom.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class BoomCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/boom.ogg";
|
||||
static description = "Plays the Vine boom sound effect";
|
||||
static aliases = ["thud", "vine"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class BruhCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/bruh.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class BruhCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/bruh.ogg";
|
||||
static description = "Plays the \"bruh\" sound effect";
|
||||
static aliases = ["bro"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,9 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class DamnDanielCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/damndaniel.ogg", this.message);
|
||||
}
|
||||
|
||||
static description = "Plays the \"damn daniel\" sound effect";
|
||||
static aliases = ["daniel", "damn"];
|
||||
class DamnDanielCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/damndaniel.ogg";
|
||||
static description = "Plays the \"damn daniel\" sound effect";
|
||||
static aliases = ["daniel", "damn"];
|
||||
}
|
||||
|
||||
export default DamnDanielCommand;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class ExplosionCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/explosion.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class ExplosionCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/explosion.ogg";
|
||||
static description = "Plays an explosion sound effect";
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class FakePingCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/ping.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class FakePingCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/ping.ogg";
|
||||
static description = "Plays a Discord ping sound effect";
|
||||
static aliases = ["notification", "notif"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class FartCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/fart.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class FartCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/fart.ogg";
|
||||
static description = "Plays a fart sound effect";
|
||||
static aliases = ["toot"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,7 @@
|
|||
// shoutouts to dairyorange, you're a real one
|
||||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class FartReverbCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/fart2.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class FartReverbCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/fart2.ogg";
|
||||
static description = "Plays a fart sound effect with extra reverb";
|
||||
static aliases = ["fart2"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class FBICommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/fbi.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class FBICommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/fbi.ogg";
|
||||
static description = "Plays the \"FBI OPEN UP\" sound effect";
|
||||
static aliases = ["openup"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class MailCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/mail.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class MailCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/mail.ogg";
|
||||
static description = "Plays the \"You've got mail\" sound effect";
|
||||
static aliases = ["yougotmail", "youvegotmail", "aol"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class OofCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/oof.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class OofCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/oof.ogg";
|
||||
static description = "Plays the Roblox \"oof\" sound";
|
||||
static aliases = ["roblox", "commitdie"];
|
||||
}
|
||||
|
|
|
|||
31
commands/soundboard/soundboard.js
Normal file
31
commands/soundboard/soundboard.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import Command from "../../classes/command.js";
|
||||
import { sounds, info } from "../../utils/collections.js";
|
||||
|
||||
// all-in-one soundboard command
|
||||
class SoundboardAIOCommand extends Command {
|
||||
async run() {
|
||||
const soundName = this.type === "classic" ? this.args[0] : this.optionsArray[0].name;
|
||||
if (!sounds.has(soundName)) return "You need to provide a sound to play!";
|
||||
const name = sounds.get(soundName);
|
||||
return await play(this.client, name, { channel: this.channel, author: this.author, type: this.type, interaction: this.interaction });
|
||||
}
|
||||
|
||||
static postInit() {
|
||||
this.flags = [];
|
||||
for (const sound of sounds.keys()) {
|
||||
this.flags.push({
|
||||
name: sound,
|
||||
type: 1,
|
||||
description: info.get(sound).description
|
||||
});
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
static description = "Plays a sound effect";
|
||||
static requires = ["sound"];
|
||||
static aliases = ["sound", "sb"];
|
||||
}
|
||||
|
||||
export default SoundboardAIOCommand;
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
import { play } from "../../utils/soundplayer.js";
|
||||
import MusicCommand from "../../classes/musicCommand.js";
|
||||
|
||||
class WinXPCommand extends MusicCommand {
|
||||
async run() {
|
||||
return await play(this.client, "./assets/audio/winxp.ogg", this.message);
|
||||
}
|
||||
import SoundboardCommand from "../../classes/soundboardCommand.js";
|
||||
|
||||
class WinXPCommand extends SoundboardCommand {
|
||||
static file = "./assets/audio/winxp.ogg";
|
||||
static description = "Plays the Windows XP startup sound";
|
||||
static aliases = ["windows", "xp"];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ class TagsCommand extends Command {
|
|||
const getResult = await database.getTag(this.channel.guild.id, this.args[1].toLowerCase());
|
||||
if (!getResult) return "This tag doesn't exist!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (getResult.author !== this.author.id && !this.message.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!";
|
||||
if (getResult.author !== this.author.id && !this.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!";
|
||||
await database.removeTag(this.args[1].toLowerCase(), this.channel.guild);
|
||||
return `The tag \`${this.args[1].toLowerCase()}\` has been deleted!`;
|
||||
} else if (this.args[0].toLowerCase() === "edit") {
|
||||
|
|
@ -31,7 +31,7 @@ class TagsCommand extends Command {
|
|||
const getResult = await database.getTag(this.channel.guild.id, this.args[1].toLowerCase());
|
||||
if (!getResult) return "This tag doesn't exist!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (getResult.author !== this.author.id && !this.message.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!";
|
||||
if (getResult.author !== this.author.id && !this.member.permissions.has("manageMessages") && !owners.includes(this.author.id)) return "You don't own this tag!";
|
||||
await this.setTag(this.args.slice(2).join(" "), this.args[1].toLowerCase(), this.message, true);
|
||||
return `The tag \`${this.args[1].toLowerCase()}\` has been edited!`;
|
||||
} else if (this.args[0].toLowerCase() === "own" || this.args[0].toLowerCase() === "owner") {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue