Added (hacky) message command support, lots of work to prepare for message content intent enforcement, improve broadcast, remove evalraw, update packages
This commit is contained in:
parent
3392c3c89e
commit
d33a7804d7
56 changed files with 443 additions and 315 deletions
|
@ -14,6 +14,7 @@ class AncientCommand extends Command {
|
|||
return data.headers.location;
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
this.success = false;
|
||||
return "I couldn't get a meme in time. Maybe try again?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class BirdCommand extends Command {
|
|||
return json[0];
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
this.success = false;
|
||||
return "I couldn't get a bird image in time. Maybe try again?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,6 +14,7 @@ class CatCommand extends Command {
|
|||
return data.headers.location;
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
this.success = false;
|
||||
return "I couldn't get a cat image in time. Maybe try again?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ class DogCommand extends Command {
|
|||
return json.message;
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
this.success = false;
|
||||
return "I couldn't get a dog image in time. Maybe try again?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,7 @@ class WikihowCommand extends Command {
|
|||
}
|
||||
} catch (e) {
|
||||
if (e.name === "AbortError") {
|
||||
this.success = false;
|
||||
return "I couldn't get a WikiHow image in time. Maybe try again?";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,11 +8,15 @@ class AvatarCommand extends Command {
|
|||
if (this.type === "classic" && this.message.mentions[0]) {
|
||||
return this.message.mentions[0].dynamicAvatarURL(null, 512);
|
||||
} else if (await this.ipc.fetchUser(member)) {
|
||||
const user = await this.ipc.fetchUser(member);
|
||||
return user.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // hacky "solution"
|
||||
let user = await this.ipc.fetchUser(member);
|
||||
if (!user) user = await this.client.getRESTUser(member);
|
||||
return user?.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // hacky "solution"
|
||||
} else if (mentionRegex.test(member)) {
|
||||
const id = member.match(mentionRegex)[1];
|
||||
if (id < 21154535154122752n) return "That's not a valid mention!";
|
||||
if (id < 21154535154122752n) {
|
||||
this.success = false;
|
||||
return "That's not a valid mention!";
|
||||
}
|
||||
try {
|
||||
const user = await this.client.getRESTUser(id);
|
||||
return user.avatar ? this.client._formatImage(`/avatars/${user.id}/${user.avatar}`, null, 512) : `https://cdn.discordapp.com/embed/avatars/${user.discriminator % 5}.png`; // repeat of hacky "solution" from above
|
||||
|
|
|
@ -12,7 +12,10 @@ class BannerCommand extends Command {
|
|||
return user.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
|
||||
} else if (mentionRegex.test(member)) {
|
||||
const id = member.match(mentionRegex)[1];
|
||||
if (id < 21154535154122752n) return "That's not a valid mention!";
|
||||
if (id < 21154535154122752n) {
|
||||
this.success = false;
|
||||
return "That's not a valid mention!";
|
||||
}
|
||||
try {
|
||||
const user = await this.client.getRESTUser(id);
|
||||
return user.dynamicBannerURL(null, 512) ?? "This user doesn't have a banner!";
|
||||
|
|
|
@ -3,11 +3,13 @@ import { clean } from "../../utils/misc.js";
|
|||
|
||||
class Base64Command extends Command {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (this.type === "classic" && this.args.length === 0) return "You need to provide whether you want to encode or decode the text!";
|
||||
const command = this.type === "classic" ? this.args[0].toLowerCase() : this.optionsArray[0].name.toLowerCase();
|
||||
if (command !== "decode" && command !== "encode") return "You need to provide whether you want to encode or decode the text!";
|
||||
const string = this.options.text ?? this.args.slice(1).join(" ");
|
||||
if (!string || !string.trim()) return `You need to provide a string to ${command}!`;
|
||||
this.success = true;
|
||||
if (command === "decode") {
|
||||
const b64Decoded = Buffer.from(string, "base64").toString("utf8");
|
||||
return `\`\`\`\n${await clean(b64Decoded)}\`\`\``;
|
||||
|
|
|
@ -5,15 +5,20 @@ class BroadcastCommand extends Command {
|
|||
run() {
|
||||
return new Promise((resolve) => {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can broadcast messages!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
resolve("Only the bot owner can broadcast messages!");
|
||||
}
|
||||
const message = this.options.message ?? this.args.join(" ");
|
||||
if (message?.trim()) {
|
||||
this.ipc.centralStore.set("broadcast", message);
|
||||
this.ipc.broadcast("playbroadcast", message);
|
||||
this.ipc.register("broadcastSuccess", () => {
|
||||
this.ipc.unregister("broadcastSuccess");
|
||||
resolve("Successfully broadcasted message.");
|
||||
});
|
||||
} else {
|
||||
this.ipc.centralStore.delete("broadcast");
|
||||
this.ipc.broadcast("broadcastend");
|
||||
this.ipc.register("broadcastEnd", () => {
|
||||
this.ipc.unregister("broadcastEnd");
|
||||
|
|
|
@ -3,6 +3,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class ChannelCommand extends Command {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
|
@ -23,6 +24,7 @@ class ChannelCommand extends Command {
|
|||
}
|
||||
|
||||
await db.disableChannel(channel);
|
||||
this.success = true;
|
||||
return `I have been disabled in this channel. To re-enable me, just run \`${guildDB.prefix}channel enable\`.`;
|
||||
} else if (this.args[0].toLowerCase() === "enable") {
|
||||
let channel;
|
||||
|
@ -36,11 +38,12 @@ class ChannelCommand extends Command {
|
|||
}
|
||||
|
||||
await db.enableChannel(channel);
|
||||
this.success = true;
|
||||
return "I have been re-enabled in this channel.";
|
||||
}
|
||||
}
|
||||
|
||||
static description = "Enables/disables me in a channel (does not work with slash commands)";
|
||||
static description = "Enables/disables classic commands in a channel (use server settings for slash commands)";
|
||||
static arguments = ["[enable/disable]", "{id}"];
|
||||
static slashAllowed = false;
|
||||
static directAllowed = false;
|
||||
|
|
|
@ -4,6 +4,7 @@ import * as collections from "../../utils/collections.js";
|
|||
|
||||
class CommandCommand extends Command {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!this.member.permissions.has("administrator") && !owners.includes(this.member.id)) return "You need to be an administrator to enable/disable me!";
|
||||
|
@ -21,16 +22,18 @@ class CommandCommand extends Command {
|
|||
if (disabled?.includes(command)) return "That command is already disabled!";
|
||||
|
||||
await db.disableCommand(this.channel.guild.id, command);
|
||||
this.success = true;
|
||||
return `The command has been disabled. To re-enable it, just run \`${guildDB.prefix}command enable ${command}\`.`;
|
||||
} else if (this.args[0].toLowerCase() === "enable") {
|
||||
if (!disabled?.includes(command)) return "That command isn't disabled!";
|
||||
|
||||
await db.enableCommand(this.channel.guild.id, command);
|
||||
this.success = true;
|
||||
return `The command \`${command}\` has been re-enabled.`;
|
||||
}
|
||||
}
|
||||
|
||||
static description = "Enables/disables a command for a server";
|
||||
static description = "Enables/disables a classic command for a server (use server settings for slash commands)";
|
||||
static aliases = ["cmd"];
|
||||
static arguments = ["[enable/disable]", "[command]"];
|
||||
static slashAllowed = false;
|
||||
|
|
|
@ -4,7 +4,10 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class CountCommand extends Command {
|
||||
async run() {
|
||||
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!";
|
||||
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) {
|
||||
this.success = false;
|
||||
return "I don't have the `Embed Links` permission!";
|
||||
}
|
||||
const counts = await database.getCounts();
|
||||
const countArray = [];
|
||||
for (const entry of Object.entries(counts)) {
|
||||
|
|
|
@ -4,8 +4,7 @@ import Command from "../../classes/command.js";
|
|||
class EmoteCommand extends Command {
|
||||
async run() {
|
||||
const emoji = this.options.emoji ?? this.content;
|
||||
if (!emoji || !emoji.trim()) return "You need to provide an emoji!";
|
||||
if (emoji.split(" ")[0].match(/^<a?:.+:\d+>$/)) {
|
||||
if (emoji && emoji.trim() && 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 = [];
|
||||
|
@ -14,6 +13,7 @@ class EmoteCommand extends Command {
|
|||
}
|
||||
return `https://twemoji.maxcdn.com/v/latest/72x72/${codePoints.join("-").replace("-fe0f", "")}.png`;
|
||||
} else {
|
||||
this.success = false;
|
||||
return "You need to provide a valid emoji to get an image!";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,10 @@ import Command from "../../classes/command.js";
|
|||
class EvalCommand extends Command {
|
||||
async run() {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can use eval!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
return "Only the bot owner can use eval!";
|
||||
}
|
||||
await this.acknowledge();
|
||||
const code = this.options.code ?? this.args.join(" ");
|
||||
try {
|
||||
|
|
|
@ -1,31 +0,0 @@
|
|||
import { clean } from "../../utils/misc.js";
|
||||
import Command from "../../classes/command.js";
|
||||
|
||||
class EvalRawCommand extends Command {
|
||||
async run() {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can use evalraw!";
|
||||
const code = this.args.join(" ");
|
||||
try {
|
||||
const evaled = eval(code);
|
||||
if (evaled.length >= 2000) {
|
||||
return {
|
||||
text: "The result was too large, so here it is as a file:",
|
||||
file: evaled,
|
||||
name: "result.txt"
|
||||
};
|
||||
} else {
|
||||
return evaled;
|
||||
}
|
||||
} catch (err) {
|
||||
return `\`ERROR\` \`\`\`xl\n${await clean(err)}\n\`\`\``;
|
||||
}
|
||||
}
|
||||
|
||||
static description = "Executes JavaScript code (with raw output)";
|
||||
static aliases = ["run"];
|
||||
static arguments = ["[code]"];
|
||||
static slashAllowed = false;
|
||||
}
|
||||
|
||||
export default EvalRawCommand;
|
|
@ -7,7 +7,10 @@ import Command from "../../classes/command.js";
|
|||
class ExecCommand extends Command {
|
||||
async run() {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can use exec!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
return "Only the bot owner can use exec!";
|
||||
}
|
||||
await this.acknowledge();
|
||||
const code = this.options.cmd ?? this.args.join(" ");
|
||||
try {
|
||||
|
|
|
@ -54,7 +54,10 @@ class HelpCommand extends Command {
|
|||
}
|
||||
return embed;
|
||||
} else {
|
||||
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) return "I don't have the `Embed Links` permission!";
|
||||
if (this.channel.guild && !this.channel.permissionsOf(this.client.user.id).has("embedLinks")) {
|
||||
this.success = false;
|
||||
return "I don't have the `Embed Links` permission!";
|
||||
}
|
||||
const pages = [];
|
||||
if (help.categories === help.categoryTemplate && !help.generated) await help.generateList();
|
||||
for (const category of Object.keys(help.categories)) {
|
||||
|
|
|
@ -7,6 +7,7 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class ImageSearchCommand extends Command {
|
||||
async run() {
|
||||
this.success = false;
|
||||
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.options.query ?? this.args.join(" ");
|
||||
if (!query || !query.trim()) return "You need to provide something to search for!";
|
||||
|
@ -34,6 +35,7 @@ class ImageSearchCommand extends Command {
|
|||
}]
|
||||
});
|
||||
}
|
||||
this.success = true;
|
||||
return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, embeds);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@ import Command from "../../classes/command.js";
|
|||
class ImageReloadCommand extends Command {
|
||||
async run() {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can reload the image servers!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
return "Only the bot owner can reload the image servers!";
|
||||
}
|
||||
const amount = await this.ipc.serviceCommand("image", { type: "reload" }, true);
|
||||
if (amount > 0) {
|
||||
return `Successfully connected to ${amount} image servers.`;
|
||||
|
|
|
@ -6,9 +6,11 @@ class LengthenCommand extends Command {
|
|||
async run() {
|
||||
await this.acknowledge();
|
||||
const input = this.options.url ?? this.args.join(" ");
|
||||
this.success = false;
|
||||
if (!input || !input.trim() || !urlCheck(input)) return "You need to provide a short URL to lengthen!";
|
||||
if (urlCheck(input)) {
|
||||
const url = await request(encodeURI(input), { method: "HEAD" });
|
||||
this.success = true;
|
||||
return url.headers.location || input;
|
||||
} else {
|
||||
return "That isn't a URL!";
|
||||
|
|
|
@ -7,7 +7,10 @@ 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.member.permissions.has("administrator") && !owners.includes(this.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)) {
|
||||
this.success = false;
|
||||
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 {
|
||||
|
|
|
@ -4,7 +4,10 @@ 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!";
|
||||
if (this.args.length === 0) {
|
||||
this.success = false;
|
||||
return "You need to provide some text to generate a QR code!";
|
||||
}
|
||||
await this.acknowledge();
|
||||
const writable = new PassThrough();
|
||||
qrcode.toFileStream(writable, this.content, { margin: 1 });
|
||||
|
|
|
@ -8,12 +8,14 @@ import imageDetect from "../../utils/imagedetect.js";
|
|||
class QrReadCommand extends Command {
|
||||
async run() {
|
||||
const image = await imageDetect(this.client, this.message, this.interaction, this.options);
|
||||
this.success = false;
|
||||
if (image === undefined) return "You need to provide an image/GIF with a QR code to read!";
|
||||
await this.acknowledge();
|
||||
const data = Buffer.from(await (await request(image.path)).body.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!";
|
||||
this.success = true;
|
||||
return `\`\`\`\n${await clean(qrBuffer.data)}\n\`\`\``;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@ class RawCommand extends Command {
|
|||
async run() {
|
||||
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!";
|
||||
if (image === undefined) {
|
||||
this.success = false;
|
||||
return "You need to provide an image/GIF to get a raw URL!";
|
||||
}
|
||||
return image.path;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,10 @@ import Command from "../../classes/command.js";
|
|||
class RestartCommand extends Command {
|
||||
async run() {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can restart me!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
return "Only the bot owner can restart me!";
|
||||
}
|
||||
await this.client.createMessage(this.channel.id, Object.assign({
|
||||
content: "esmBot is restarting."
|
||||
}, this.reference));
|
||||
|
|
|
@ -2,7 +2,10 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class ServerInfoCommand extends Command {
|
||||
async run() {
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
if (!this.channel.guild) {
|
||||
this.success = false;
|
||||
return "This command only works in servers!";
|
||||
}
|
||||
const owner = await this.channel.guild.members.get(this.channel.guild.ownerID);
|
||||
return {
|
||||
embeds: [{
|
||||
|
|
|
@ -2,8 +2,10 @@ import Command from "../../classes/command.js";
|
|||
|
||||
class SnowflakeCommand extends Command {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.args[0]) return "You need to provide a snowflake ID!";
|
||||
if (!this.args[0].match(/^<?[@#]?[&!]?\d+>?$/) && this.args[0] < 21154535154122752n) return "That's not a valid snowflake!";
|
||||
this.success = true;
|
||||
return `<t:${Math.floor(((this.args[0].replaceAll("@", "").replaceAll("#", "").replaceAll("!", "").replaceAll("&", "").replaceAll("<", "").replaceAll(">", "") / 4194304) + 1420070400000) / 1000)}:F>`;
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,10 @@ class SoundReloadCommand extends Command {
|
|||
run() {
|
||||
return new Promise((resolve) => {
|
||||
const owners = process.env.OWNER.split(",");
|
||||
if (!owners.includes(this.author.id)) return "Only the bot owner can reload Lavalink!";
|
||||
if (!owners.includes(this.author.id)) {
|
||||
this.success = false;
|
||||
return "Only the bot owner can reload Lavalink!";
|
||||
}
|
||||
this.acknowledge().then(() => {
|
||||
this.ipc.broadcast("soundreload");
|
||||
this.ipc.register("soundReloadSuccess", (msg) => {
|
||||
|
|
|
@ -4,10 +4,13 @@ import imagedetect from "../../utils/imagedetect.js";
|
|||
class StickerCommand extends Command {
|
||||
async run() {
|
||||
const result = await imagedetect(this.client, this.message, this.interaction, this.options, false, false, true);
|
||||
this.success = false;
|
||||
if (!result) return "You need to provide a sticker!";
|
||||
if (result.format_type === 1) { // PNG
|
||||
this.success = true;
|
||||
return `https://cdn.discordapp.com/stickers/${result.id}.png`;
|
||||
} else if (result.format_type === 2) { // APNG
|
||||
this.success = true;
|
||||
return {
|
||||
embeds: [{
|
||||
color: 16711680,
|
||||
|
@ -18,6 +21,7 @@ class StickerCommand extends Command {
|
|||
}]
|
||||
};
|
||||
} else if (result.format_type === 3) { // Lottie
|
||||
this.success = true;
|
||||
return `I can't display this sticker because it uses the Lottie animation format; however, I can give you the raw JSON link to it: https://cdn.discordapp.com/stickers/${result.id}.json`;
|
||||
} else {
|
||||
return "I don't recognize that sticker format!";
|
||||
|
|
|
@ -8,6 +8,7 @@ import Command from "../../classes/command.js";
|
|||
class YouTubeCommand extends Command {
|
||||
async run() {
|
||||
const query = this.options.query ?? this.args.join(" ");
|
||||
this.success = false;
|
||||
if (!query || !query.trim()) return "You need to provide something to search for!";
|
||||
await this.acknowledge();
|
||||
const messages = [];
|
||||
|
@ -16,6 +17,7 @@ class YouTubeCommand extends Command {
|
|||
for (const [i, value] of videos.results.entries()) {
|
||||
messages.push({ content: `Page ${i + 1} of ${videos.results.length}\n<:youtube:637020823005167626> **${value.title.replaceAll("*", "\\*")}**\nUploaded by **${value.author.replaceAll("*", "\\*")}**\n${value.url}` });
|
||||
}
|
||||
this.success = true;
|
||||
return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, messages);
|
||||
}
|
||||
|
||||
|
|
23
commands/message/select-image.js
Normal file
23
commands/message/select-image.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import Command from "../../classes/command.js";
|
||||
import imageDetect from "../../utils/imagedetect.js";
|
||||
import { selectedImages } from "../../utils/collections.js";
|
||||
|
||||
class SelectImageCommand extends Command {
|
||||
async run() {
|
||||
const message = this.interaction.data.resolved.messages.get(this.interaction.data.target_id);
|
||||
const image = await imageDetect(this.client, message, this.interaction, this.options, true, false, false, true);
|
||||
this.success = false;
|
||||
if (image === undefined) {
|
||||
return "I couldn't find an image in that message!";
|
||||
} else if (image.type === "large") {
|
||||
return "That image is too large (>= 25MB)! Try using a smaller image.";
|
||||
} else if (image.type === "tenorlimit") {
|
||||
return "I've been rate-limited by Tenor. Please try uploading your GIF elsewhere.";
|
||||
}
|
||||
selectedImages.set(this.author.id, image);
|
||||
this.success = true;
|
||||
return "The image has been selected for your next command.";
|
||||
}
|
||||
}
|
||||
|
||||
export default SelectImageCommand;
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class HostCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -37,9 +38,11 @@ class HostCommand extends MusicCommand {
|
|||
const object = this.connection;
|
||||
object.host = member.id;
|
||||
players.set(this.channel.guild.id, object);
|
||||
this.success = true;
|
||||
return `🔊 ${member.mention} is the new voice channel host.`;
|
||||
} else {
|
||||
const member = this.channel.guild ? this.channel.guild.members.get(players.get(this.channel.guild.id).host) : undefined;
|
||||
this.success = true;
|
||||
return `🔊 The current voice channel host is **${member?.username}#${member?.discriminator}**.`;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class LoopCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -10,6 +11,7 @@ class LoopCommand extends MusicCommand {
|
|||
const object = this.connection;
|
||||
object.loop = !object.loop;
|
||||
players.set(this.channel.guild.id, object);
|
||||
this.success = true;
|
||||
return object.loop ? "🔊 The player is now looping." : "🔊 The player is no longer looping.";
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@ import { commands, aliases, info, categories } from "../../utils/collections.js"
|
|||
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 "https://media.discordapp.net/attachments/322114245632327703/941958748874887178/robot_dance-trans.gif";
|
||||
if (cmd === "music" || this.constructor.aliases.includes(cmd)) return "https://projectlounge.pw/robotdance.gif";
|
||||
if (this.type === "classic") {
|
||||
this.origOptions.args.shift();
|
||||
} else {
|
||||
|
@ -14,8 +14,12 @@ class MusicAIOCommand extends Command {
|
|||
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();
|
||||
const inst = new command(this.client, this.cluster, this.worker, this.ipc, this.origOptions);
|
||||
const result = await inst.run();
|
||||
this.success = inst.success;
|
||||
return result;
|
||||
} else {
|
||||
this.success = false;
|
||||
return "That isn't a valid music command!";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class NowPlayingCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -10,6 +11,7 @@ class NowPlayingCommand extends MusicCommand {
|
|||
if (!player) return "I'm not playing anything!";
|
||||
const track = await player.node.rest.decode(player.track);
|
||||
const parts = Math.floor((player.position / track.length) * 10);
|
||||
this.success = true;
|
||||
return {
|
||||
embeds: [{
|
||||
color: 16711680,
|
||||
|
|
|
@ -5,9 +5,12 @@ const prefixes = ["ytsearch:", "ytmsearch:", "scsearch:", "spsearch:", "amsearch
|
|||
class PlayCommand extends MusicCommand {
|
||||
async run() {
|
||||
const input = this.options.query ?? this.args.join(" ");
|
||||
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!";
|
||||
if (!input && ((!this.message || this.message?.attachments.length <= 0))) {
|
||||
this.success = false;
|
||||
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.options.file ? this.interaction.data.resolved.attachments[this.options.file] : null);
|
||||
const attachment = this.type === "classic" ? this.message.attachments[0] : null;
|
||||
if (query.startsWith("||") && query.endsWith("||")) {
|
||||
query = query.substring(2, query.length - 2);
|
||||
}
|
||||
|
@ -24,13 +27,10 @@ class PlayCommand extends MusicCommand {
|
|||
}
|
||||
|
||||
static flags = [{
|
||||
name: "file",
|
||||
type: 11,
|
||||
description: "An audio file attachment"
|
||||
}, {
|
||||
name: "query",
|
||||
type: 3,
|
||||
description: "An audio search query or URL"
|
||||
description: "An audio search query or URL",
|
||||
required: true
|
||||
}];
|
||||
static description = "Plays a song or adds it to the queue";
|
||||
static aliases = ["p"];
|
||||
|
|
|
@ -6,6 +6,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class QueueCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -52,6 +53,7 @@ class QueueCommand extends MusicCommand {
|
|||
});
|
||||
}
|
||||
if (embeds.length === 0) return "There's nothing in the queue!";
|
||||
this.success = true;
|
||||
return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, embeds);
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class RemoveCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -13,6 +14,7 @@ class RemoveCommand extends MusicCommand {
|
|||
if (removed.length === 0) return "That's not a valid position!";
|
||||
const track = await this.connection.player.node.rest.decode(removed[0]);
|
||||
queues.set(this.channel.guild.id, this.queue);
|
||||
this.success = true;
|
||||
return `🔊 The song \`${track.title ? track.title : "(blank)"}\` has been removed from the queue.`;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class SeekCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -11,13 +12,14 @@ class SeekCommand extends MusicCommand {
|
|||
if (!track.isSeekable) return "This track isn't seekable!";
|
||||
const pos = this.options.position ?? this.args[0];
|
||||
let seconds;
|
||||
if (pos.includes(":")) {
|
||||
if (typeof pos === "string" && pos.includes(":")) {
|
||||
seconds = +(pos.split(":").reduce((acc, time) => (60 * acc) + +time));
|
||||
} else {
|
||||
seconds = parseFloat(pos);
|
||||
}
|
||||
if (isNaN(seconds) || (seconds * 1000) > track.length || (seconds * 1000) < 0) return "That's not a valid position!";
|
||||
player.seekTo(seconds * 1000);
|
||||
this.success = true;
|
||||
return `🔊 Seeked track to ${seconds} second(s).`;
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class ShuffleCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -10,6 +11,7 @@ class ShuffleCommand extends MusicCommand {
|
|||
const object = this.connection;
|
||||
object.shuffle = !object.shuffle;
|
||||
players.set(this.channel.guild.id, object);
|
||||
this.success = true;
|
||||
return object.shuffle ? "🔊 The player is now shuffling." : "🔊 The player is no longer shuffling.";
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class SkipCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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!";
|
||||
|
@ -18,13 +19,16 @@ class SkipCommand extends MusicCommand {
|
|||
if (votes.count + 1 === votes.max) {
|
||||
await player.player.stopTrack(this.channel.guild.id);
|
||||
skipVotes.set(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) });
|
||||
this.success = true;
|
||||
if (this.type === "application") return "🔊 The current song has been skipped.";
|
||||
} else {
|
||||
skipVotes.set(this.channel.guild.id, newObject);
|
||||
this.success = true;
|
||||
return `🔊 Voted to skip song (${votes.count + 1}/${votes.max} people have voted).`;
|
||||
}
|
||||
} else {
|
||||
await player.player.stopTrack();
|
||||
this.success = true;
|
||||
if (this.type === "application") return "🔊 The current song has been skipped.";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,13 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class StopCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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.getNode().leaveChannel(this.channel.guild.id);
|
||||
this.success = true;
|
||||
return "🔊 The current voice channel session has ended.";
|
||||
}
|
||||
if (this.connection.host !== this.author.id && !this.member.permissions.has("manageChannels")) return "Only the current voice session host can stop the music!";
|
||||
|
@ -15,6 +17,7 @@ class StopCommand extends MusicCommand {
|
|||
connection.node.leaveChannel(this.channel.guild.id);
|
||||
players.delete(this.channel.guild.id);
|
||||
queues.delete(this.channel.guild.id);
|
||||
this.success = true;
|
||||
return "🔊 The current voice channel session has ended.";
|
||||
}
|
||||
|
||||
|
|
|
@ -2,12 +2,14 @@ import MusicCommand from "../../classes/musicCommand.js";
|
|||
|
||||
class ToggleCommand extends MusicCommand {
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
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.member.permissions.has("manageChannels")) return "Only the current voice session host can pause/resume the music!";
|
||||
const player = this.connection.player;
|
||||
player.setPaused(!player.paused ? true : false);
|
||||
this.success = true;
|
||||
return `🔊 The player has been ${player.paused ? "paused" : "resumed"}.`;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,10 @@ import { sounds, info } from "../../utils/collections.js";
|
|||
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!";
|
||||
if (!sounds.has(soundName)) {
|
||||
this.success = false;
|
||||
return "You need to provide a sound to play!";
|
||||
}
|
||||
const name = sounds.get(soundName);
|
||||
return await play(this.client, name, { channel: this.channel, member: this.member, type: this.type, interaction: this.interaction });
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ const blacklist = ["create", "add", "edit", "remove", "delete", "list", "random"
|
|||
class TagsCommand extends Command {
|
||||
// todo: attempt to not make this file the worst thing that human eyes have ever seen
|
||||
async run() {
|
||||
this.success = false;
|
||||
if (!this.channel.guild) return "This command only works in servers!";
|
||||
const cmd = this.type === "classic" ? (this.args[0] ?? "").toLowerCase() : this.optionsArray[0].name;
|
||||
if (!cmd || !cmd.trim()) return "You need to provide the name of the tag you want to view!";
|
||||
|
@ -18,6 +19,7 @@ class TagsCommand extends Command {
|
|||
const getResult = await database.getTag(this.channel.guild.id, tagName);
|
||||
if (getResult) return "This tag already exists!";
|
||||
const result = await database.setTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.channel.guild);
|
||||
this.success = true;
|
||||
if (result) return result;
|
||||
return `The tag \`${tagName}\` has been added!`;
|
||||
} else if (cmd === "delete" || cmd === "remove") {
|
||||
|
@ -27,6 +29,7 @@ class TagsCommand extends Command {
|
|||
const owners = process.env.OWNER.split(",");
|
||||
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(tagName, this.channel.guild);
|
||||
this.success = true;
|
||||
return `The tag \`${tagName}\` has been deleted!`;
|
||||
} else if (cmd === "edit") {
|
||||
if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to edit!";
|
||||
|
@ -35,12 +38,14 @@ class TagsCommand extends Command {
|
|||
const owners = process.env.OWNER.split(",");
|
||||
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.editTag(tagName, { content: this.type === "classic" ? this.args.slice(2).join(" ") : this.optionsArray[0].options[1].value, author: this.member.id }, this.channel.guild);
|
||||
this.success = true;
|
||||
return `The tag \`${tagName}\` has been edited!`;
|
||||
} else if (cmd === "own" || cmd === "owner") {
|
||||
if (!tagName || !tagName.trim()) return "You need to provide the name of the tag you want to check the owner of!";
|
||||
const getResult = await database.getTag(this.channel.guild.id, tagName);
|
||||
if (!getResult) return "This tag doesn't exist!";
|
||||
const user = await this.ipc.fetchUser(getResult.author);
|
||||
this.success = true;
|
||||
if (!user) {
|
||||
try {
|
||||
const restUser = await this.client.getRESTUser(getResult.author);
|
||||
|
@ -77,6 +82,7 @@ class TagsCommand extends Command {
|
|||
});
|
||||
}
|
||||
if (embeds.length === 0) return "I couldn't find any tags!";
|
||||
this.success = true;
|
||||
return paginator(this.client, { type: this.type, message: this.message, interaction: this.interaction, channel: this.channel, author: this.author }, embeds);
|
||||
} else {
|
||||
let getResult;
|
||||
|
@ -87,6 +93,7 @@ class TagsCommand extends Command {
|
|||
getResult = await database.getTag(this.channel.guild.id, this.type === "classic" ? cmd : tagName);
|
||||
}
|
||||
if (!getResult) return "This tag doesn't exist!";
|
||||
this.success = true;
|
||||
if (getResult.content.length > 2000) {
|
||||
return {
|
||||
embeds: [{
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue