Changed max width to 120 columns

This commit is contained in:
WatDuhHekBro 2020-12-15 01:56:09 -06:00
parent 39f89a9f63
commit 5165c5ec4b
33 changed files with 227 additions and 712 deletions

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
printWidth: 80, printWidth: 120,
tabWidth: 4, tabWidth: 4,
useTabs: false, useTabs: false,
semi: true, semi: true,

View File

@ -29,9 +29,7 @@ export default new Command({
); );
const permLevel = getPermissionLevel($.member); const permLevel = getPermissionLevel($.member);
$.channel.send( $.channel.send(
`${$.author.toString()}, your permission level is \`${ `${$.author.toString()}, your permission level is \`${PermissionNames[permLevel]}\` (${permLevel}).`
PermissionNames[permLevel]
}\` (${permLevel}).`
); );
}, },
subcommands: { subcommands: {
@ -41,8 +39,7 @@ export default new Command({
permission: Command.PERMISSIONS.ADMIN, permission: Command.PERMISSIONS.ADMIN,
subcommands: { subcommands: {
prefix: new Command({ prefix: new Command({
description: description: "Set a custom prefix for your guild. Removes your custom prefix if none is provided.",
"Set a custom prefix for your guild. Removes your custom prefix if none is provided.",
usage: "(<prefix>)", usage: "(<prefix>)",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
Storage.getGuild($.guild?.id || "N/A").prefix = null; Storage.getGuild($.guild?.id || "N/A").prefix = null;
@ -53,28 +50,22 @@ export default new Command({
}, },
any: new Command({ any: new Command({
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
Storage.getGuild($.guild?.id || "N/A").prefix = Storage.getGuild($.guild?.id || "N/A").prefix = $.args[0];
$.args[0];
Storage.save(); Storage.save();
$.channel.send( $.channel.send(`The custom prefix for this guild is now \`${$.args[0]}\`.`);
`The custom prefix for this guild is now \`${$.args[0]}\`.`
);
} }
}) })
}) })
} }
}), }),
diag: new Command({ diag: new Command({
description: description: 'Requests a debug log with the "info" verbosity level.',
'Requests a debug log with the "info" verbosity level.',
permission: Command.PERMISSIONS.BOT_SUPPORT, permission: Command.PERMISSIONS.BOT_SUPPORT,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
$.channel.send(getLogBuffer("info")); $.channel.send(getLogBuffer("info"));
}, },
any: new Command({ any: new Command({
description: `Select a verbosity to listen to. Available levels: \`[${Object.keys( description: `Select a verbosity to listen to. Available levels: \`[${Object.keys(logs).join(", ")}]\``,
logs
).join(", ")}]\``,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const type = $.args[0]; const type = $.args[0];
@ -95,12 +86,9 @@ export default new Command({
$.channel.send("Setting status to `online`..."); $.channel.send("Setting status to `online`...");
}, },
any: new Command({ any: new Command({
description: `Select a status to set to. Available statuses: \`[${statuses.join( description: `Select a status to set to. Available statuses: \`[${statuses.join(", ")}]\`.`,
", "
)}]\`.`,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
if (!statuses.includes($.args[0])) if (!statuses.includes($.args[0])) return $.channel.send("That status doesn't exist!");
return $.channel.send("That status doesn't exist!");
else { else {
$.client.user?.setStatus($.args[0]); $.client.user?.setStatus($.args[0]);
$.channel.send(`Setting status to \`${$.args[0]}\`...`); $.channel.send(`Setting status to \`${$.args[0]}\`...`);
@ -119,17 +107,13 @@ export default new Command({
const msgs = await $.channel.messages.fetch({ const msgs = await $.channel.messages.fetch({
limit: 100 limit: 100
}); });
const travMessages = msgs.filter( const travMessages = msgs.filter((m) => m.author.id === $.client.user?.id);
(m) => m.author.id === $.client.user?.id
);
await $.message.channel await $.message.channel.send(`Found ${travMessages.size} messages to delete.`).then((m) =>
.send(`Found ${travMessages.size} messages to delete.`) m.delete({
.then((m) => timeout: 5000
m.delete({ })
timeout: 5000 );
})
);
await $.message.channel.bulkDelete(travMessages); await $.message.channel.bulkDelete(travMessages);
} }
}), }),
@ -147,9 +131,7 @@ export default new Command({
$.channel $.channel
/// @ts-ignore /// @ts-ignore
.bulkDelete(fetched) .bulkDelete(fetched)
.catch((error: any) => .catch((error: any) => $.channel.send(`Error: ${error}`));
$.channel.send(`Error: ${error}`)
);
} }
}) })
}), }),
@ -162,8 +144,7 @@ export default new Command({
const code = $.args.join(" "); const code = $.args.join(" ");
let evaled = eval(code); let evaled = eval(code);
if (typeof evaled !== "string") if (typeof evaled !== "string") evaled = require("util").inspect(evaled);
evaled = require("util").inspect(evaled);
$.channel.send(clean(evaled), {code: "x1"}); $.channel.send(clean(evaled), {code: "x1"});
} catch (err) { } catch (err) {
$.channel.send(`\`ERROR\` \`\`\`x1\n${clean(err)}\n\`\`\``); $.channel.send(`\`ERROR\` \`\`\`x1\n${clean(err)}\n\`\`\``);
@ -175,26 +156,18 @@ export default new Command({
permission: Command.PERMISSIONS.BOT_SUPPORT, permission: Command.PERMISSIONS.BOT_SUPPORT,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const nickName = $.args.join(" "); const nickName = $.args.join(" ");
const trav = $.guild?.members.cache.find( const trav = $.guild?.members.cache.find((member) => member.id === $.client.user?.id);
(member) => member.id === $.client.user?.id
);
await trav?.setNickname(nickName); await trav?.setNickname(nickName);
if ( if (botHasPermission($.guild, Permissions.FLAGS.MANAGE_MESSAGES))
botHasPermission($.guild, Permissions.FLAGS.MANAGE_MESSAGES)
)
$.message.delete({timeout: 5000}).catch($.handler.bind($)); $.message.delete({timeout: 5000}).catch($.handler.bind($));
$.channel $.channel.send(`Nickname set to \`${nickName}\``).then((m) => m.delete({timeout: 5000}));
.send(`Nickname set to \`${nickName}\``)
.then((m) => m.delete({timeout: 5000}));
} }
}), }),
guilds: new Command({ guilds: new Command({
description: "Shows a list of all guilds the bot is a member of.", description: "Shows a list of all guilds the bot is a member of.",
permission: Command.PERMISSIONS.BOT_SUPPORT, permission: Command.PERMISSIONS.BOT_SUPPORT,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const guildList = $.client.guilds.cache const guildList = $.client.guilds.cache.array().map((e) => e.name);
.array()
.map((e) => e.name);
$.channel.send(guildList); $.channel.send(guildList);
} }
}), }),
@ -209,9 +182,7 @@ export default new Command({
$.channel.send("Activity set to default."); $.channel.send("Activity set to default.");
}, },
any: new Command({ any: new Command({
description: `Select an activity type to set. Available levels: \`[${activities.join( description: `Select an activity type to set. Available levels: \`[${activities.join(", ")}]\``,
", "
)}]\``,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const type = $.args[0]; const type = $.args[0];
@ -220,9 +191,7 @@ export default new Command({
type: $.args[0].toUpperCase() type: $.args[0].toUpperCase()
}); });
$.channel.send( $.channel.send(
`Set activity to \`${$.args[0].toUpperCase()}\` \`${$.args `Set activity to \`${$.args[0].toUpperCase()}\` \`${$.args.slice(1).join(" ")}\`.`
.slice(1)
.join(" ")}\`.`
); );
} else } else
$.channel.send( $.channel.send(

View File

@ -7,8 +7,7 @@ export default new Command({
run: ":cookie: Here's a cookie!", run: ":cookie: Here's a cookie!",
any: new Command({ any: new Command({
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
if ($.args[0] == "all") if ($.args[0] == "all") return $.channel.send(`${$.author} gave everybody a cookie!`);
return $.channel.send(`${$.author} gave everybody a cookie!`);
} }
}), }),
user: new Command({ user: new Command({
@ -42,13 +41,9 @@ export default new Command({
`bakes <@${mention.id}> fresh cookies, it smells amazing.` `bakes <@${mention.id}> fresh cookies, it smells amazing.`
]; ];
if (mention.id == sender.id) if (mention.id == sender.id) return $.channel.send("You can't give yourself cookies!");
return $.channel.send("You can't give yourself cookies!");
$.channel.send( $.channel.send(`:cookie: <@${sender.id}> ` + cookies[Math.floor(Math.random() * cookies.length)]);
`:cookie: <@${sender.id}> ` +
cookies[Math.floor(Math.random() * cookies.length)]
);
} }
}) })
}); });

View File

@ -16,16 +16,13 @@ export default new Command({
shop: ShopCommand shop: ShopCommand
}, },
user: new Command({ user: new Command({
description: description: "See how much money someone else has by using their user ID or pinging them.",
"See how much money someone else has by using their user ID or pinging them.",
async run({guild, channel, args}) { async run({guild, channel, args}) {
if (isAuthorized(guild, channel)) if (isAuthorized(guild, channel)) channel.send(getMoneyEmbed(args[0]));
channel.send(getMoneyEmbed(args[0]));
} }
}), }),
any: new Command({ any: new Command({
description: description: "See how much money someone else has by using their username.",
"See how much money someone else has by using their username.",
async run({guild, channel, args, callMemberByUsername, message}) { async run({guild, channel, args, callMemberByUsername, message}) {
if (isAuthorized(guild, channel)) if (isAuthorized(guild, channel))
callMemberByUsername(message, args.join(" "), (member) => { callMemberByUsername(message, args.join(" "), (member) => {

View File

@ -11,16 +11,13 @@ export default new Command({
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
console.log(endpoints.sfw); console.log(endpoints.sfw);
$.channel.send( $.channel.send(
`Please provide an image type. Available arguments:\n\`[${Object.keys( `Please provide an image type. Available arguments:\n\`[${Object.keys(endpoints.sfw).join(", ")}]\`.`
endpoints.sfw
).join(", ")}]\`.`
); );
}, },
any: new Command({ any: new Command({
description: "Image type to send.", description: "Image type to send.",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
if (!($.args[0] in endpoints.sfw)) if (!($.args[0] in endpoints.sfw)) return $.channel.send("Couldn't find that endpoint!");
return $.channel.send("Couldn't find that endpoint!");
let baseURL = "https://nekos.life/api/v2"; let baseURL = "https://nekos.life/api/v2";
let url = new URL(`${baseURL}${endpoints.sfw[$.args[0]]}`); let url = new URL(`${baseURL}${endpoints.sfw[$.args[0]]}`);

View File

@ -62,8 +62,6 @@ export default new Command({
"large man" "large man"
]; ];
$.channel.send( $.channel.send("ok " + responses[Math.floor(Math.random() * responses.length)]);
"ok " + responses[Math.floor(Math.random() * responses.length)]
);
} }
}); });

View File

@ -5,9 +5,7 @@ import {CommonLibrary, getContent} from "../../core/lib";
export default new Command({ export default new Command({
description: "OwO-ifies the input.", description: "OwO-ifies the input.",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
let url = new URL( let url = new URL(`https://nekos.life/api/v2/owoify?text=${$.args.join(" ")}`);
`https://nekos.life/api/v2/owoify?text=${$.args.join(" ")}`
);
const content = await getContent(url.toString()); const content = await getContent(url.toString());
$.channel.send(content.owo); $.channel.send(content.owo);
} }

View File

@ -4,8 +4,7 @@ import {Storage} from "../../../core/structures";
import {isAuthorized, getMoneyEmbed, getSendEmbed} from "./eco-utils"; import {isAuthorized, getMoneyEmbed, getSendEmbed} from "./eco-utils";
export const DailyCommand = new Command({ export const DailyCommand = new Command({
description: description: "Pick up your daily Mons. The cooldown is per user and every 22 hours to allow for some leeway.",
"Pick up your daily Mons. The cooldown is per user and every 22 hours to allow for some leeway.",
async run({author, channel, guild}) { async run({author, channel, guild}) {
if (isAuthorized(guild, channel)) { if (isAuthorized(guild, channel)) {
const user = Storage.getUser(author.id); const user = Storage.getUser(author.id);
@ -81,15 +80,10 @@ export const PayCommand = new Command({
const target = args[0]; const target = args[0];
const receiver = Storage.getUser(target.id); const receiver = Storage.getUser(target.id);
if (amount <= 0) if (amount <= 0) return channel.send("You must send at least one Mon!");
return channel.send("You must send at least one Mon!");
else if (sender.money < amount) else if (sender.money < amount)
return channel.send( return channel.send("You don't have enough Mons for that.", getMoneyEmbed(author));
"You don't have enough Mons for that.", else if (target.id === author.id) return channel.send("You can't send Mons to yourself!");
getMoneyEmbed(author)
);
else if (target.id === author.id)
return channel.send("You can't send Mons to yourself!");
else if (target.bot && process.argv[2] !== "dev") else if (target.bot && process.argv[2] !== "dev")
return channel.send("You can't send Mons to a bot!"); return channel.send("You can't send Mons to a bot!");
@ -110,24 +104,16 @@ export const PayCommand = new Command({
const last = args.pop(); const last = args.pop();
if (!/\d+/g.test(last) && args.length === 0) if (!/\d+/g.test(last) && args.length === 0)
return channel.send( return channel.send("You need to enter an amount you're sending!");
"You need to enter an amount you're sending!"
);
const amount = Math.floor(last); const amount = Math.floor(last);
const sender = Storage.getUser(author.id); const sender = Storage.getUser(author.id);
if (amount <= 0) if (amount <= 0) return channel.send("You must send at least one credit!");
return channel.send("You must send at least one credit!");
else if (sender.money < amount) else if (sender.money < amount)
return channel.send( return channel.send("You don't have enough money to do that!", getMoneyEmbed(author));
"You don't have enough money to do that!",
getMoneyEmbed(author)
);
else if (!guild) else if (!guild)
return channel.send( return channel.send("You have to use this in a server if you want to send money with a username!");
"You have to use this in a server if you want to send money with a username!"
);
const username = args.join(" "); const username = args.join(" ");
const member = ( const member = (
@ -141,8 +127,7 @@ export const PayCommand = new Command({
return channel.send( return channel.send(
`Couldn't find a user by the name of \`${username}\`! If you want to send money to someone in a different server, you have to use their user ID!` `Couldn't find a user by the name of \`${username}\`! If you want to send money to someone in a different server, you have to use their user ID!`
); );
else if (member.user.id === author.id) else if (member.user.id === author.id) return channel.send("You can't send money to yourself!");
return channel.send("You can't send money to yourself!");
else if (member.user.bot && process.argv[2] !== "dev") else if (member.user.bot && process.argv[2] !== "dev")
return channel.send("You can't send money to a bot!"); return channel.send("You can't send money to a bot!");

View File

@ -16,9 +16,7 @@ export const ShopItems: ShopItem[] = [
description: "Hug Monika.", description: "Hug Monika.",
usage: "hug", usage: "hug",
run(message, cost) { run(message, cost) {
message.channel.send( message.channel.send(`Transaction of ${cost} Mon completed successfully. <@394808963356688394>`);
`Transaction of ${cost} Mon completed successfully. <@394808963356688394>`
);
} }
}, },
{ {
@ -27,9 +25,7 @@ export const ShopItems: ShopItem[] = [
description: "Hold Monika's hand.", description: "Hold Monika's hand.",
usage: "handhold", usage: "handhold",
run(message, cost) { run(message, cost) {
message.channel.send( message.channel.send(`Transaction of ${cost} Mons completed successfully. <@394808963356688394>`);
`Transaction of ${cost} Mons completed successfully. <@394808963356688394>`
);
} }
}, },
{ {

View File

@ -14,12 +14,8 @@ export const ShopCommand = new Command({
for (const item of selection) for (const item of selection)
fields.push({ fields.push({
name: `**${item.title}** (${getPrefix(guild)}eco buy ${ name: `**${item.title}** (${getPrefix(guild)}eco buy ${item.usage})`,
item.usage value: `${item.description} Costs ${$(item.cost).pluralise("Mon", "s")}.`,
})`,
value: `${item.description} Costs ${$(
item.cost
).pluralise("Mon", "s")}.`,
inline: false inline: false
}); });
@ -40,17 +36,10 @@ export const ShopCommand = new Command({
else { else {
const shopPages = $(ShopItems).split(5); const shopPages = $(ShopItems).split(5);
const pageAmount = shopPages.length; const pageAmount = shopPages.length;
const msg = await channel.send( const msg = await channel.send(getShopEmbed(shopPages[0], `Shop (Page 1 of ${pageAmount})`));
getShopEmbed(shopPages[0], `Shop (Page 1 of ${pageAmount})`)
);
$.paginate(msg, author.id, pageAmount, (page) => { $.paginate(msg, author.id, pageAmount, (page) => {
msg.edit( msg.edit(getShopEmbed(shopPages[page], `Shop (Page ${page + 1} of ${pageAmount})`));
getShopEmbed(
shopPages[page],
`Shop (Page ${page + 1} of ${pageAmount})`
)
);
}); });
} }
} }
@ -90,10 +79,7 @@ export const BuyCommand = new Command({
} }
} }
if (!found) if (!found) channel.send(`There's no item in the shop that goes by \`${requested}\`!`);
channel.send(
`There's no item in the shop that goes by \`${requested}\`!`
);
} }
} }
}); });

View File

@ -25,11 +25,7 @@ export function getMoneyEmbed(user: User): object {
}; };
} }
export function getSendEmbed( export function getSendEmbed(sender: User, receiver: User, amount: number): object {
sender: User,
receiver: User,
amount: number
): object {
return { return {
embed: { embed: {
color: 0xffff00, color: 0xffff00,
@ -48,17 +44,11 @@ export function getSendEmbed(
fields: [ fields: [
{ {
name: `Sender: ${sender.username}#${sender.discriminator}`, name: `Sender: ${sender.username}#${sender.discriminator}`,
value: $(Storage.getUser(sender.id).money).pluralise( value: $(Storage.getUser(sender.id).money).pluralise("credit", "s")
"credit",
"s"
)
}, },
{ {
name: `Receiver: ${receiver.username}#${receiver.discriminator}`, name: `Receiver: ${receiver.username}#${receiver.discriminator}`,
value: $(Storage.getUser(receiver.id).money).pluralise( value: $(Storage.getUser(receiver.id).money).pluralise("credit", "s")
"credit",
"s"
)
} }
], ],
footer: { footer: {
@ -72,16 +62,10 @@ export function getSendEmbed(
}; };
} }
export function isAuthorized( export function isAuthorized(guild: Guild | null, channel: TextChannel | DMChannel | NewsChannel): boolean {
guild: Guild | null, if (guild?.id === "637512823676600330" || process.argv[2] === "dev") return true;
channel: TextChannel | DMChannel | NewsChannel
): boolean {
if (guild?.id === "637512823676600330" || process.argv[2] === "dev")
return true;
else { else {
channel.send( channel.send("Sorry, this command can only be used in Monika's emote server.");
"Sorry, this command can only be used in Monika's emote server."
);
return false; return false;
} }
} }

View File

@ -4,8 +4,7 @@ import {loadCommands, categories} from "../core/command";
import {PermissionNames} from "../core/permissions"; import {PermissionNames} from "../core/permissions";
export default new Command({ export default new Command({
description: description: "Lists all commands. If a command is specified, their arguments are listed as well.",
"Lists all commands. If a command is specified, their arguments are listed as well.",
usage: "([command, [subcommand/type], ...])", usage: "([command, [subcommand/type], ...])",
aliases: ["h"], aliases: ["h"],
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
@ -20,9 +19,7 @@ export default new Command({
const command = commands.get(header); const command = commands.get(header);
if (!command) if (!command)
return $.warn( return $.warn(`Command "${header}" of category "${category}" unexpectedly doesn't exist!`);
`Command "${header}" of category "${category}" unexpectedly doesn't exist!`
);
output += `\n- \`${header}\`: ${command.description}`; output += `\n- \`${header}\`: ${command.description}`;
} }
@ -37,13 +34,9 @@ export default new Command({
let header = $.args.shift() as string; let header = $.args.shift() as string;
let command = commands.get(header); let command = commands.get(header);
if (!command || header === "test") if (!command || header === "test") return $.channel.send(`No command found by the name \`${header}\`!`);
return $.channel.send(
`No command found by the name \`${header}\`!`
);
if (command.originalCommandName) if (command.originalCommandName) header = command.originalCommandName;
header = command.originalCommandName;
else $.warn(`originalCommandName isn't defined for ${header}?!`); else $.warn(`originalCommandName isn't defined for ${header}?!`);
let permLevel = command.permission ?? Command.PERMISSIONS.NONE; let permLevel = command.permission ?? Command.PERMISSIONS.NONE;
@ -91,10 +84,7 @@ export default new Command({
} }
} }
if (invalid) if (invalid) return $.channel.send(`No command found by the name \`${header}\`!`);
return $.channel.send(
`No command found by the name \`${header}\`!`
);
let append = ""; let append = "";
@ -104,21 +94,15 @@ export default new Command({
command.subcommands.forEach((subcmd, subtag) => { command.subcommands.forEach((subcmd, subtag) => {
// Don't capture duplicates generated from aliases. // Don't capture duplicates generated from aliases.
if (subcmd.originalCommandName === subtag) { if (subcmd.originalCommandName === subtag) {
const customUsage = subcmd.usage const customUsage = subcmd.usage ? ` ${subcmd.usage}` : "";
? ` ${subcmd.usage}` list.push(`- \`${header} ${subtag}${customUsage}\` - ${subcmd.description}`);
: "";
list.push(
`- \`${header} ${subtag}${customUsage}\` - ${subcmd.description}`
);
} }
}); });
const addDynamicType = (cmd: Command | null, type: string) => { const addDynamicType = (cmd: Command | null, type: string) => {
if (cmd) { if (cmd) {
const customUsage = cmd.usage ? ` ${cmd.usage}` : ""; const customUsage = cmd.usage ? ` ${cmd.usage}` : "";
list.push( list.push(`- \`${header} <${type}>${customUsage}\` - ${cmd.description}`);
`- \`${header} <${type}>${customUsage}\` - ${cmd.description}`
);
} }
}; };
@ -126,9 +110,7 @@ export default new Command({
addDynamicType(command.number, "number"); addDynamicType(command.number, "number");
addDynamicType(command.any, "any"); addDynamicType(command.any, "any");
append = append = "Usages:" + (list.length > 0 ? `\n${list.join("\n")}` : " None.");
"Usages:" +
(list.length > 0 ? `\n${list.join("\n")}` : " None.");
} else append = `Usage: \`${header} ${usage}\``; } else append = `Usage: \`${header} ${usage}\``;
let aliases = "None"; let aliases = "None";

View File

@ -10,17 +10,14 @@ import moment from "moment";
import utc from "moment"; import utc from "moment";
export default new Command({ export default new Command({
description: description: "Command to provide all sorts of info about the current server, a user, etc.",
"Command to provide all sorts of info about the current server, a user, etc.",
run: "Please provide an argument.\nFor help, run `%prefix%help info`.", run: "Please provide an argument.\nFor help, run `%prefix%help info`.",
subcommands: { subcommands: {
avatar: new Command({ avatar: new Command({
description: "Shows your own, or another user's avatar.", description: "Shows your own, or another user's avatar.",
usage: "(<user>)", usage: "(<user>)",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
$.channel.send( $.channel.send($.author.displayAvatarURL({dynamic: true, size: 2048}));
$.author.displayAvatarURL({dynamic: true, size: 2048})
);
}, },
user: new Command({ user: new Command({
description: "Shows your own, or another user's avatar.", description: "Shows your own, or another user's avatar.",
@ -51,16 +48,10 @@ export default new Command({
`** Client:** ${$.client.user?.tag} (${$.client.user?.id})`, `** Client:** ${$.client.user?.tag} (${$.client.user?.id})`,
`** Servers:** ${$.client.guilds.cache.size.toLocaleString()}`, `** Servers:** ${$.client.guilds.cache.size.toLocaleString()}`,
`** Users:** ${$.client.guilds.cache `** Users:** ${$.client.guilds.cache
.reduce( .reduce((a: any, b: {memberCount: any}) => a + b.memberCount, 0)
(a: any, b: {memberCount: any}) =>
a + b.memberCount,
0
)
.toLocaleString()}`, .toLocaleString()}`,
`** Channels:** ${$.client.channels.cache.size.toLocaleString()}`, `** Channels:** ${$.client.channels.cache.size.toLocaleString()}`,
`** Creation Date:** ${utc( `** Creation Date:** ${utc($.client.user?.createdTimestamp).format("Do MMMM YYYY HH:mm:ss")}`,
$.client.user?.createdTimestamp
).format("Do MMMM YYYY HH:mm:ss")}`,
`** Node.JS:** ${process.version}`, `** Node.JS:** ${process.version}`,
`** Version:** v${version}`, `** Version:** v${version}`,
`** Discord.JS:** ${djsversion}`, `** Discord.JS:** ${djsversion}`,
@ -76,12 +67,8 @@ export default new Command({
`\u3000 • Model: ${core.model}`, `\u3000 • Model: ${core.model}`,
`\u3000 • Speed: ${core.speed}MHz`, `\u3000 • Speed: ${core.speed}MHz`,
`** Memory:**`, `** Memory:**`,
`\u3000 • Total: ${formatBytes( `\u3000 • Total: ${formatBytes(process.memoryUsage().heapTotal)}`,
process.memoryUsage().heapTotal `\u3000 • Used: ${formatBytes(process.memoryUsage().heapTotal)}`
)}`,
`\u3000 • Used: ${formatBytes(
process.memoryUsage().heapTotal
)}`
]) ])
.setTimestamp(); .setTimestamp();
$.channel.send(embed); $.channel.send(embed);
@ -99,9 +86,7 @@ export default new Command({
const emojis = $.guild.emojis.cache; const emojis = $.guild.emojis.cache;
const iconURL = $.guild.iconURL({dynamic: true}); const iconURL = $.guild.iconURL({dynamic: true});
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setDescription( .setDescription(`**Guild information for __${$.guild.name}__**`)
`**Guild information for __${$.guild.name}__**`
)
.setColor("BLUE"); .setColor("BLUE");
if (iconURL) if (iconURL)
embed embed
@ -111,97 +96,41 @@ export default new Command({
`** ID:** ${$.guild.id}`, `** ID:** ${$.guild.id}`,
`** Owner:** ${$.guild.owner?.user.tag} (${$.guild.ownerID})`, `** Owner:** ${$.guild.owner?.user.tag} (${$.guild.ownerID})`,
`** Region:** ${regions[$.guild.region]}`, `** Region:** ${regions[$.guild.region]}`,
`** Boost Tier:** ${ `** Boost Tier:** ${$.guild.premiumTier ? `Tier ${$.guild.premiumTier}` : "None"}`,
$.guild.premiumTier `** Explicit Filter:** ${filterLevels[$.guild.explicitContentFilter]}`,
? `Tier ${$.guild.premiumTier}` `** Verification Level:** ${verificationLevels[$.guild.verificationLevel]}`,
: "None" `** Time Created:** ${moment($.guild.createdTimestamp).format("LT")} ${moment(
}`,
`** Explicit Filter:** ${
filterLevels[$.guild.explicitContentFilter]
}`,
`** Verification Level:** ${
verificationLevels[
$.guild.verificationLevel
]
}`,
`** Time Created:** ${moment(
$.guild.createdTimestamp $.guild.createdTimestamp
).format("LT")} ${moment( ).format("LL")} ${moment($.guild.createdTimestamp).fromNow()})`,
$.guild.createdTimestamp
).format("LL")} ${moment(
$.guild.createdTimestamp
).fromNow()})`,
"\u200b" "\u200b"
]) ])
.addField("Statistics", [ .addField("Statistics", [
`** Role Count:** ${roles.length}`, `** Role Count:** ${roles.length}`,
`** Emoji Count:** ${emojis.size}`, `** Emoji Count:** ${emojis.size}`,
`** Regular Emoji Count:** ${ `** Regular Emoji Count:** ${emojis.filter((emoji) => !emoji.animated).size}`,
emojis.filter((emoji) => !emoji.animated) `** Animated Emoji Count:** ${emojis.filter((emoji) => emoji.animated).size}`,
.size
}`,
`** Animated Emoji Count:** ${
emojis.filter((emoji) => emoji.animated)
.size
}`,
`** Member Count:** ${$.guild.memberCount}`, `** Member Count:** ${$.guild.memberCount}`,
`** Humans:** ${ `** Humans:** ${members.filter((member) => !member.user.bot).size}`,
members.filter((member) => !member.user.bot) `** Bots:** ${members.filter((member) => member.user.bot).size}`,
.size `** Text Channels:** ${channels.filter((channel) => channel.type === "text").size}`,
}`, `** Voice Channels:** ${channels.filter((channel) => channel.type === "voice").size}`,
`** Bots:** ${ `** Boost Count:** ${$.guild.premiumSubscriptionCount || "0"}`,
members.filter((member) => member.user.bot)
.size
}`,
`** Text Channels:** ${
channels.filter(
(channel) => channel.type === "text"
).size
}`,
`** Voice Channels:** ${
channels.filter(
(channel) => channel.type === "voice"
).size
}`,
`** Boost Count:** ${
$.guild.premiumSubscriptionCount || "0"
}`,
`\u200b` `\u200b`
]) ])
.addField("Presence", [ .addField("Presence", [
`** Online:** ${ `** Online:** ${members.filter((member) => member.presence.status === "online").size}`,
members.filter( `** Idle:** ${members.filter((member) => member.presence.status === "idle").size}`,
(member) =>
member.presence.status === "online"
).size
}`,
`** Idle:** ${
members.filter(
(member) =>
member.presence.status === "idle"
).size
}`,
`** Do Not Disturb:** ${ `** Do Not Disturb:** ${
members.filter( members.filter((member) => member.presence.status === "dnd").size
(member) =>
member.presence.status === "dnd"
).size
}`, }`,
`** Offline:** ${ `** Offline:** ${
members.filter( members.filter((member) => member.presence.status === "offline").size
(member) =>
member.presence.status === "offline"
).size
}`, }`,
"\u200b" "\u200b"
]) ])
.addField( .addField(
`Roles [${roles.length - 1}]`, `Roles [${roles.length - 1}]`,
roles.length < 10 roles.length < 10 ? roles.join(", ") : roles.length > 10 ? trimArray(roles) : "None"
? roles.join(", ")
: roles.length > 10
? trimArray(roles)
: "None"
) )
.setTimestamp(); .setTimestamp();
@ -224,56 +153,35 @@ export default new Command({
); );
const roles = member.roles.cache const roles = member.roles.cache
.sort( .sort((a: {position: number}, b: {position: number}) => b.position - a.position)
(a: {position: number}, b: {position: number}) =>
b.position - a.position
)
.map((role: {toString: () => any}) => role.toString()) .map((role: {toString: () => any}) => role.toString())
.slice(0, -1); .slice(0, -1);
// @ts-ignore - Discord.js' typings seem to be outdated here. According to their v12 docs, it's User.fetchFlags() instead of User.flags. // @ts-ignore - Discord.js' typings seem to be outdated here. According to their v12 docs, it's User.fetchFlags() instead of User.flags.
const userFlags = ((await member.user.fetchFlags()) as UserFlags).toArray(); const userFlags = ((await member.user.fetchFlags()) as UserFlags).toArray();
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setThumbnail( .setThumbnail(member.user.displayAvatarURL({dynamic: true, size: 512}))
member.user.displayAvatarURL({dynamic: true, size: 512})
)
.setColor(member.displayHexColor || "BLUE") .setColor(member.displayHexColor || "BLUE")
.addField("User", [ .addField("User", [
`** Username:** ${member.user.username}`, `** Username:** ${member.user.username}`,
`** Discriminator:** ${member.user.discriminator}`, `** Discriminator:** ${member.user.discriminator}`,
`** ID:** ${member.id}`, `** ID:** ${member.id}`,
`** Flags:** ${ `** Flags:** ${userFlags.length ? userFlags.join(", ") : "None"}`,
userFlags.length ? userFlags.join(", ") : "None" `** Avatar:** [Link to avatar](${member.user.displayAvatarURL({
}`, dynamic: true
`** Avatar:** [Link to avatar](${member.user.displayAvatarURL( })})`,
{ `** Time Created:** ${moment(member.user.createdTimestamp).format("LT")} ${moment(
dynamic: true
}
)})`,
`** Time Created:** ${moment(
member.user.createdTimestamp member.user.createdTimestamp
).format("LT")} ${moment( ).format("LL")} ${moment(member.user.createdTimestamp).fromNow()}`,
member.user.createdTimestamp
).format("LL")} ${moment(
member.user.createdTimestamp
).fromNow()}`,
`** Status:** ${member.user.presence.status}`, `** Status:** ${member.user.presence.status}`,
`** Game:** ${ `** Game:** ${member.user.presence.activities || "Not playing a game."}`
member.user.presence.activities || "Not playing a game."
}`
]) ])
.addField("Member", [ .addField("Member", [
`** Highest Role:** ${ `** Highest Role:** ${
member.roles.highest.id === $.guild?.id member.roles.highest.id === $.guild?.id ? "None" : member.roles.highest.name
? "None"
: member.roles.highest.name
}`,
`** Server Join Date:** ${moment(member.joinedAt).format(
"LL LTS"
)}`,
`** Hoist Role:** ${
member.roles.hoist ? member.roles.hoist.name : "None"
}`, }`,
`** Server Join Date:** ${moment(member.joinedAt).format("LL LTS")}`,
`** Hoist Role:** ${member.roles.hoist ? member.roles.hoist.name : "None"}`,
`** Roles:** [${roles.length}]: ${ `** Roles:** [${roles.length}]: ${
roles.length < 10 roles.length < 10
? roles.join(", ") ? roles.join(", ")

View File

@ -9,8 +9,7 @@ export default new Command({
description: description:
"Scans all text channels in the current guild and returns the number of times each emoji specific to the guild has been used. Has a cooldown of 24 hours per guild.", "Scans all text channels in the current guild and returns the number of times each emoji specific to the guild has been used. Has a cooldown of 24 hours per guild.",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
if (!$.guild) if (!$.guild) return $.channel.send(`You must use this command on a server!`);
return $.channel.send(`You must use this command on a server!`);
// Test if the command is on cooldown. This isn't the strictest cooldown possible, because in the event that the bot crashes, the cooldown will be reset. But for all intends and purposes, it's a good enough cooldown. It's a per-server cooldown. // Test if the command is on cooldown. This isn't the strictest cooldown possible, because in the event that the bot crashes, the cooldown will be reset. But for all intends and purposes, it's a good enough cooldown. It's a per-server cooldown.
const startTime = Date.now(); const startTime = Date.now();
@ -53,9 +52,7 @@ export default new Command({
// If you don't include the "a" for animated emotes, it'll not only not show up, but also cause all other emotes in the same message to not show up. The emote name is self-correcting but it's better to keep the right value since it'll be used to calculate message lengths that fit. // If you don't include the "a" for animated emotes, it'll not only not show up, but also cause all other emotes in the same message to not show up. The emote name is self-correcting but it's better to keep the right value since it'll be used to calculate message lengths that fit.
stats[emote.id] = { stats[emote.id] = {
name: emote.name, name: emote.name,
formatted: `<${emote.animated ? "a" : ""}:${emote.name}:${ formatted: `<${emote.animated ? "a" : ""}:${emote.name}:${emote.id}>`,
emote.id
}>`,
users: 0, users: 0,
bots: 0 bots: 0
}; };
@ -133,10 +130,7 @@ export default new Command({
// Then halt the loop and send warnings of any inconsistencies. // Then halt the loop and send warnings of any inconsistencies.
continueReactionLoop = false; continueReactionLoop = false;
if ( if (reaction.count !== userReactions + botReactions) {
reaction.count !==
userReactions + botReactions
) {
$.warn( $.warn(
`[Channel: ${channel.id}, Message: ${msg.id}] A reaction count of ${reaction.count} was expected but was given ${userReactions} user reactions and ${botReactions} bot reactions.` `[Channel: ${channel.id}, Message: ${msg.id}] A reaction count of ${reaction.count} was expected but was given ${userReactions} user reactions and ${botReactions} bot reactions.`
); );
@ -161,9 +155,7 @@ export default new Command({
const finishTime = Date.now(); const finishTime = Date.now();
clearInterval(interval); clearInterval(interval);
statusMessage.edit( statusMessage.edit(
`Finished operation in ${moment `Finished operation in ${moment.duration(finishTime - startTime).humanize()} with ${$(warnings).pluralise(
.duration(finishTime - startTime)
.humanize()} with ${$(warnings).pluralise(
"inconsistenc", "inconsistenc",
"ies", "ies",
"y" "y"
@ -174,9 +166,7 @@ export default new Command({
// Display stats on emote usage. // Display stats on emote usage.
// This can work outside the loop now that it's synchronous, and now it's clearer what code is meant to execute at the end. // This can work outside the loop now that it's synchronous, and now it's clearer what code is meant to execute at the end.
let sortedEmoteIDs = Object.keys(stats).sort( let sortedEmoteIDs = Object.keys(stats).sort((a, b) => stats[b].users - stats[a].users);
(a, b) => stats[b].users - stats[a].users
);
const lines: string[] = []; const lines: string[] = [];
let rank = 1; let rank = 1;

View File

@ -7,24 +7,16 @@ export default new Command({
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const voiceChannel = $.message.member?.voice.channel; const voiceChannel = $.message.member?.voice.channel;
if (!voiceChannel) if (!voiceChannel) return $.channel.send("You are not in a voice channel.");
return $.channel.send("You are not in a voice channel.");
if (!$.guild?.me?.hasPermission("MANAGE_CHANNELS")) if (!$.guild?.me?.hasPermission("MANAGE_CHANNELS"))
return $.channel.send( return $.channel.send("I am lacking the required permissions to perform this action.");
"I am lacking the required permissions to perform this action."
);
if ($.args.length === 0) if ($.args.length === 0) return $.channel.send("Please provide a new voice channel name.");
return $.channel.send("Please provide a new voice channel name.");
const changeVC = $.guild.channels.resolve(voiceChannel.id); const changeVC = $.guild.channels.resolve(voiceChannel.id);
$.channel $.channel
.send( .send(`Changed channel name from "${voiceChannel}" to "${$.args.join(" ")}".`)
`Changed channel name from "${voiceChannel}" to "${$.args.join(
" "
)}".`
)
/// @ts-ignore /// @ts-ignore
.then(changeVC?.setName($.args.join(" "))); .then(changeVC?.setName($.args.join(" ")));
} }

View File

@ -10,9 +10,7 @@ export default new Command({
usage: "<emote>", usage: "<emote>",
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const search = $.args[0].toLowerCase(); const search = $.args[0].toLowerCase();
const emote = $.client.emojis.cache.find((emote) => const emote = $.client.emojis.cache.find((emote) => emote.name.toLowerCase().includes(search));
emote.name.toLowerCase().includes(search)
);
if (!emote) return $.channel.send("That's not a valid emote name!"); if (!emote) return $.channel.send("That's not a valid emote name!");
$.message.delete(); $.message.delete();
$.channel.send(`${emote}`); $.channel.send(`${emote}`);

View File

@ -7,14 +7,10 @@ export default new Command({
endpoint: true, endpoint: true,
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
const nsfw: string | string[] = []; const nsfw: string | string[] = [];
const pages = $.client.emojis.cache const pages = $.client.emojis.cache.filter((x) => !nsfw.includes(x.guild.id), this).array();
.filter((x) => !nsfw.includes(x.guild.id), this)
.array();
const pagesSplit = $(pages).split(20); const pagesSplit = $(pages).split(20);
$.log(pagesSplit); $.log(pagesSplit);
var embed = new MessageEmbed() var embed = new MessageEmbed().setTitle("**Emoji list!**").setColor("AQUA");
.setTitle("**Emoji list!**")
.setColor("AQUA");
let desc = ""; let desc = "";
for (const emote of pagesSplit[0]) { for (const emote of pagesSplit[0]) {

View File

@ -16,9 +16,7 @@ export default new Command({
try { try {
target = await $.channel.messages.fetch(last); target = await $.channel.messages.fetch(last);
} catch { } catch {
return $.channel.send( return $.channel.send(`No valid message found by the ID \`${last}\`!`);
`No valid message found by the ID \`${last}\`!`
);
} }
$.args.pop(); $.args.pop();
@ -28,10 +26,7 @@ export default new Command({
distance = parseInt(last); distance = parseInt(last);
if (distance >= 0 && distance <= 99) $.args.pop(); if (distance >= 0 && distance <= 99) $.args.pop();
else else return $.channel.send("Your distance must be between 0 and 99!");
return $.channel.send(
"Your distance must be between 0 and 99!"
);
} }
} }
@ -48,9 +43,7 @@ export default new Command({
let anyEmoteIsValid = false; let anyEmoteIsValid = false;
for (const search of $.args) { for (const search of $.args) {
const emoji = $.client.emojis.cache.find( const emoji = $.client.emojis.cache.find((emoji) => emoji.name === search);
(emoji) => emoji.name === search
);
if (emoji) { if (emoji) {
// Call the delete function only once to avoid unnecessary errors. // Call the delete function only once to avoid unnecessary errors.

View File

@ -7,19 +7,15 @@ export default new Command({
run: "Please provide a URL.", run: "Please provide a URL.",
any: new Command({ any: new Command({
async run($: CommonLibrary): Promise<any> { async run($: CommonLibrary): Promise<any> {
https.get( https.get("https://is.gd/create.php?format=simple&url=" + encodeURIComponent($.args[0]), function (res) {
"https://is.gd/create.php?format=simple&url=" + var body = "";
encodeURIComponent($.args[0]), res.on("data", function (chunk) {
function (res) { body += chunk;
var body = ""; });
res.on("data", function (chunk) { res.on("end", function () {
body += chunk; $.channel.send(`<${body}>`);
}); });
res.on("end", function () { });
$.channel.send(`<${body}>`);
});
}
);
} }
}) })
}); });

View File

@ -58,8 +58,7 @@ export default class Command {
const baseSubcommands = Object.keys(options.subcommands); const baseSubcommands = Object.keys(options.subcommands);
// Loop once to set the base subcommands. // Loop once to set the base subcommands.
for (const name in options.subcommands) for (const name in options.subcommands) this.subcommands.set(name, options.subcommands[name]);
this.subcommands.set(name, options.subcommands[name]);
// Then loop again to make aliases point to the base subcommands and warn if something's not right. // Then loop again to make aliases point to the base subcommands and warn if something's not right.
// This shouldn't be a problem because I'm hoping that JS stores these as references that point to the same object. // This shouldn't be a problem because I'm hoping that JS stores these as references that point to the same object.
@ -118,12 +117,7 @@ export default class Command {
// Any Discord ID format will automatically format to a user ID. // Any Discord ID format will automatically format to a user ID.
else if (this.user && /\d{17,19}/.test(param)) return TYPES.USER; else if (this.user && /\d{17,19}/.test(param)) return TYPES.USER;
// Disallow infinity and allow for 0. // Disallow infinity and allow for 0.
else if ( else if (this.number && (Number(param) || param === "0") && !param.includes("Infinity")) return TYPES.NUMBER;
this.number &&
(Number(param) || param === "0") &&
!param.includes("Infinity")
)
return TYPES.NUMBER;
else if (this.any) return TYPES.ANY; else if (this.any) return TYPES.ANY;
else return TYPES.NONE; else return TYPES.NONE;
} }
@ -166,9 +160,7 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
writeFile( writeFile(
"src/commands/test.ts", "src/commands/test.ts",
template, template,
generateHandler( generateHandler('"test.ts" (testing/template command) successfully generated.')
'"test.ts" (testing/template command) successfully generated.'
)
); );
commands = new Collection(); commands = new Collection();
@ -189,10 +181,7 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
while ((cmd = await subdir.read())) { while ((cmd = await subdir.read())) {
if (cmd.isDirectory()) { if (cmd.isDirectory()) {
if (cmd.name === "subcommands") continue; if (cmd.name === "subcommands") continue;
else else $.warn(`You can't have multiple levels of directories! From: "dist/commands/${cmd.name}"`);
$.warn(
`You can't have multiple levels of directories! From: "dist/commands/${cmd.name}"`
);
} else loadCommand(cmd.name, list, selected.name); } else loadCommand(cmd.name, list, selected.name);
} }
@ -207,25 +196,14 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
return commands; return commands;
} }
async function loadCommand( async function loadCommand(filename: string, list: string[], category?: string) {
filename: string, if (!commands) return $.error(`Function "loadCommand" was called without first initializing commands!`);
list: string[],
category?: string
) {
if (!commands)
return $.error(
`Function "loadCommand" was called without first initializing commands!`
);
const prefix = category ?? ""; const prefix = category ?? "";
const header = filename.substring(0, filename.indexOf(".js")); const header = filename.substring(0, filename.indexOf(".js"));
const command = (await import(`../commands/${prefix}/${header}`)) const command = (await import(`../commands/${prefix}/${header}`)).default as Command | undefined;
.default as Command | undefined;
if (!command) if (!command) return $.warn(`Command "${header}" has no default export which is a Command instance!`);
return $.warn(
`Command "${header}" has no default export which is a Command instance!`
);
command.originalCommandName = header; command.originalCommandName = header;
list.push(header); list.push(header);
@ -238,17 +216,11 @@ async function loadCommand(
for (const alias of command.aliases) { for (const alias of command.aliases) {
if (commands.has(alias)) if (commands.has(alias))
$.warn( $.warn(`Top-level alias "${alias}" from command "${header}" already exists either as a command or alias!`);
`Top-level alias "${alias}" from command "${header}" already exists either as a command or alias!`
);
else commands.set(alias, command); else commands.set(alias, command);
} }
$.log( $.log(`Loading Command: ${header} (${category ? $(category).toTitleCase() : "Miscellaneous"})`);
`Loading Command: ${header} (${
category ? $(category).toTitleCase() : "Miscellaneous"
})`
);
} }
// The template should be built with a reductionist mentality. // The template should be built with a reductionist mentality.

View File

@ -24,9 +24,7 @@ export default class Event<K extends keyof ClientEvents> {
} }
export async function loadEvents(client: Client) { export async function loadEvents(client: Client) {
for (const file of Storage.open("dist/events", (filename: string) => for (const file of Storage.open("dist/events", (filename: string) => filename.endsWith(".js"))) {
filename.endsWith(".js")
)) {
const header = file.substring(0, file.indexOf(".js")); const header = file.substring(0, file.indexOf(".js"));
const event = (await import(`../events/${header}`)).default; const event = (await import(`../events/${header}`)).default;

View File

@ -1,20 +1,5 @@
import { import {GenericWrapper, NumberWrapper, StringWrapper, ArrayWrapper} from "./wrappers";
GenericWrapper, import {Client, Message, TextChannel, DMChannel, NewsChannel, Guild, User, GuildMember, Permissions} from "discord.js";
NumberWrapper,
StringWrapper,
ArrayWrapper
} from "./wrappers";
import {
Client,
Message,
TextChannel,
DMChannel,
NewsChannel,
Guild,
User,
GuildMember,
Permissions
} from "discord.js";
import chalk from "chalk"; import chalk from "chalk";
import {get} from "https"; import {get} from "https";
import FileManager from "./storage"; import FileManager from "./storage";
@ -45,16 +30,8 @@ export interface CommonLibrary {
callback: (page: number) => void, callback: (page: number) => void,
duration?: number duration?: number
) => void; ) => void;
prompt: ( prompt: (message: Message, senderID: string, onConfirm: () => void, duration?: number) => void;
message: Message, getMemberByUsername: (guild: Guild, username: string) => Promise<GuildMember | undefined>;
senderID: string,
onConfirm: () => void,
duration?: number
) => void;
getMemberByUsername: (
guild: Guild,
username: string
) => Promise<GuildMember | undefined>;
callMemberByUsername: ( callMemberByUsername: (
message: Message, message: Message,
username: string, username: string,
@ -88,9 +65,7 @@ export default function $(value: any) {
$.handler = function (this: CommonLibrary, error: Error) { $.handler = function (this: CommonLibrary, error: Error) {
if (this) if (this)
this.channel.send( this.channel.send(
`There was an error while trying to execute that command!\`\`\`${ `There was an error while trying to execute that command!\`\`\`${error.stack ?? error}\`\`\``
error.stack ?? error
}\`\`\``
); );
else else
$.warn( $.warn(
@ -117,12 +92,7 @@ export function setConsoleActivated(activated: boolean) {
// The custom console. In order of verbosity, error, warn, log, and debug. Ready is a variation of log. // The custom console. In order of verbosity, error, warn, log, and debug. Ready is a variation of log.
// General Purpose Logger // General Purpose Logger
$.log = (...args: any[]) => { $.log = (...args: any[]) => {
if (enabled) if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgWhite("INFO"), ...args);
console.log(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgWhite("INFO"),
...args
);
const text = `[${formatUTCTimestamp()}] [INFO] ${args.join(" ")}\n`; const text = `[${formatUTCTimestamp()}] [INFO] ${args.join(" ")}\n`;
logs.info += text; logs.info += text;
@ -130,12 +100,7 @@ $.log = (...args: any[]) => {
}; };
// "It'll still work, but you should really check up on this." // "It'll still work, but you should really check up on this."
$.warn = (...args: any[]) => { $.warn = (...args: any[]) => {
if (enabled) if (enabled) console.warn(chalk.white.bgGray(formatTimestamp()), chalk.black.bgYellow("WARN"), ...args);
console.warn(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgYellow("WARN"),
...args
);
const text = `[${formatUTCTimestamp()}] [WARN] ${args.join(" ")}\n`; const text = `[${formatUTCTimestamp()}] [WARN] ${args.join(" ")}\n`;
logs.warn += text; logs.warn += text;
@ -144,12 +109,7 @@ $.warn = (...args: any[]) => {
}; };
// Used for anything which prevents the program from actually running. // Used for anything which prevents the program from actually running.
$.error = (...args: any[]) => { $.error = (...args: any[]) => {
if (enabled) if (enabled) console.error(chalk.white.bgGray(formatTimestamp()), chalk.white.bgRed("ERROR"), ...args);
console.error(
chalk.white.bgGray(formatTimestamp()),
chalk.white.bgRed("ERROR"),
...args
);
const text = `[${formatUTCTimestamp()}] [ERROR] ${args.join(" ")}\n`; const text = `[${formatUTCTimestamp()}] [ERROR] ${args.join(" ")}\n`;
logs.error += text; logs.error += text;
@ -162,23 +122,14 @@ $.error = (...args: any[]) => {
// Would probably be more suited for debugging program logic rather than function logic, which can be checked using unit tests. // Would probably be more suited for debugging program logic rather than function logic, which can be checked using unit tests.
$.debug = (...args: any[]) => { $.debug = (...args: any[]) => {
if (process.argv[2] === "dev" && enabled) if (process.argv[2] === "dev" && enabled)
console.debug( console.debug(chalk.white.bgGray(formatTimestamp()), chalk.white.bgBlue("DEBUG"), ...args);
chalk.white.bgGray(formatTimestamp()),
chalk.white.bgBlue("DEBUG"),
...args
);
const text = `[${formatUTCTimestamp()}] [DEBUG] ${args.join(" ")}\n`; const text = `[${formatUTCTimestamp()}] [DEBUG] ${args.join(" ")}\n`;
logs.verbose += text; logs.verbose += text;
}; };
// Used once at the start of the program when the bot loads. // Used once at the start of the program when the bot loads.
$.ready = (...args: any[]) => { $.ready = (...args: any[]) => {
if (enabled) if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgGreen("READY"), ...args);
console.log(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgGreen("READY"),
...args
);
const text = `[${formatUTCTimestamp()}] [READY] ${args.join(" ")}\n`; const text = `[${formatUTCTimestamp()}] [READY] ${args.join(" ")}\n`;
logs.info += text; logs.info += text;
@ -205,14 +156,8 @@ export function formatUTCTimestamp(now = new Date()) {
return `${year}-${month}-${day} ${hour}:${minute}:${second}`; return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
} }
export function botHasPermission( export function botHasPermission(guild: Guild | null, permission: number): boolean {
guild: Guild | null, return !!(client.user && guild?.members.resolve(client.user)?.hasPermission(permission));
permission: number
): boolean {
return !!(
client.user &&
guild?.members.resolve(client.user)?.hasPermission(permission)
);
} }
// Pagination function that allows for customization via a callback. // Pagination function that allows for customization via a callback.
@ -253,10 +198,7 @@ $.paginate = async (
if (user.id === senderID) { if (user.id === senderID) {
// The reason this is inside the call is because it's possible to switch a user's permissions halfway and suddenly throw an error. // The reason this is inside the call is because it's possible to switch a user's permissions halfway and suddenly throw an error.
// This will dynamically adjust for that, switching modes depending on whether it currently has the "Manage Messages" permission. // This will dynamically adjust for that, switching modes depending on whether it currently has the "Manage Messages" permission.
const canDeleteEmotes = botHasPermission( const canDeleteEmotes = botHasPermission(message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
message.guild,
Permissions.FLAGS.MANAGE_MESSAGES
);
handle(reaction.emoji.name, user.id); handle(reaction.emoji.name, user.id);
if (canDeleteEmotes) reaction.users.remove(user); if (canDeleteEmotes) reaction.users.remove(user);
@ -273,12 +215,7 @@ $.paginate = async (
}; };
// Waits for the sender to either confirm an action or let it pass (and delete the message). // Waits for the sender to either confirm an action or let it pass (and delete the message).
$.prompt = async ( $.prompt = async (message: Message, senderID: string, onConfirm: () => void, duration = 10000) => {
message: Message,
senderID: string,
onConfirm: () => void,
duration = 10000
) => {
let isDeleted = false; let isDeleted = false;
message.react("✅"); message.react("✅");
@ -312,11 +249,7 @@ $.getMemberByUsername = async (guild: Guild, username: string) => {
}; };
/** Convenience function to handle false cases automatically. */ /** Convenience function to handle false cases automatically. */
$.callMemberByUsername = async ( $.callMemberByUsername = async (message: Message, username: string, onSuccess: (member: GuildMember) => void) => {
message: Message,
username: string,
onSuccess: (member: GuildMember) => void
) => {
const guild = message.guild; const guild = message.guild;
const send = message.channel.send; const send = message.channel.send;
@ -364,11 +297,7 @@ export function parseArgs(line: string): string[] {
* - `%%` = `%` * - `%%` = `%`
* - If the invalid token is null/undefined, nothing is changed. * - If the invalid token is null/undefined, nothing is changed.
*/ */
export function parseVars( export function parseVars(line: string, definitions: {[key: string]: string}, invalid: string | null = ""): string {
line: string,
definitions: {[key: string]: string},
invalid: string | null = ""
): string {
let result = ""; let result = "";
let inVariable = false; let inVariable = false;
let token = ""; let token = "";
@ -397,10 +326,7 @@ export function parseVars(
export function isType(value: any, type: any): boolean { export function isType(value: any, type: any): boolean {
if (value === undefined && type === undefined) return true; if (value === undefined && type === undefined) return true;
else if (value === null && type === null) return true; else if (value === null && type === null) return true;
else else return value !== undefined && value !== null && value.constructor === type;
return (
value !== undefined && value !== null && value.constructor === type
);
} }
/** /**
@ -409,12 +335,7 @@ export function isType(value: any, type: any): boolean {
* If at any point the value doesn't match the data structure provided, the fallback is returned. * If at any point the value doesn't match the data structure provided, the fallback is returned.
* Warning: Type checking is based on the fallback's type. Be sure that the "type" parameter is accurate to this! * Warning: Type checking is based on the fallback's type. Be sure that the "type" parameter is accurate to this!
*/ */
export function select<T>( export function select<T>(value: any, fallback: T, type: Function, isArray = false): T {
value: any,
fallback: T,
type: Function,
isArray = false
): T {
if (isArray && isType(value, Array)) { if (isArray && isType(value, Array)) {
for (let item of value) if (!isType(item, type)) return fallback; for (let item of value) if (!isType(item, type)) return fallback;
return value; return value;
@ -426,9 +347,7 @@ export function select<T>(
export function clean(text: any) { export function clean(text: any) {
if (typeof text === "string") if (typeof text === "string")
return text return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
.replace(/`/g, "`" + String.fromCharCode(8203))
.replace(/@/g, "@" + String.fromCharCode(8203));
else return text; else return text;
} }
@ -450,34 +369,26 @@ export function formatBytes(bytes: any) {
export function getContent(url: any) { export function getContent(url: any) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
get( get(url, (res: {resume?: any; setEncoding?: any; on?: any; statusCode?: any}) => {
url, const {statusCode} = res;
(res: { if (statusCode !== 200) {
resume?: any; res.resume();
setEncoding?: any; reject(`Request failed. Status code: ${statusCode}`);
on?: any;
statusCode?: any;
}) => {
const {statusCode} = res;
if (statusCode !== 200) {
res.resume();
reject(`Request failed. Status code: ${statusCode}`);
}
res.setEncoding("utf8");
let rawData = "";
res.on("data", (chunk: string) => {
rawData += chunk;
});
res.on("end", () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
} catch (e) {
reject(`Error: ${e.message}`);
}
});
} }
).on("error", (err: {message: any}) => { res.setEncoding("utf8");
let rawData = "";
res.on("data", (chunk: string) => {
rawData += chunk;
});
res.on("end", () => {
try {
const parsedData = JSON.parse(rawData);
resolve(parsedData);
} catch (e) {
reject(`Error: ${e.message}`);
}
});
}).on("error", (err: {message: any}) => {
reject(`Error: ${err.message}`); reject(`Error: ${err.message}`);
}); });
}); });
@ -510,6 +421,5 @@ export const Random = {
int: (min: number, max: number) => Math.floor(Random.num(min, max)), int: (min: number, max: number) => Math.floor(Random.num(min, max)),
chance: (decimal: number) => Math.random() < decimal, chance: (decimal: number) => Math.random() < decimal,
sign: (number = 1) => number * (Random.chance(0.5) ? -1 : 1), sign: (number = 1) => number * (Random.chance(0.5) ? -1 : 1),
deviation: (base: number, deviation: number) => deviation: (base: number, deviation: number) => Random.num(base - deviation, base + deviation)
Random.num(base - deviation, base + deviation)
}; };

View File

@ -53,18 +53,13 @@ const PermissionChecker: ((member: GuildMember) => boolean)[] = [
// After checking the lengths of these three objects, use this as the length for consistency. // After checking the lengths of these three objects, use this as the length for consistency.
const length = Object.keys(PERMISSIONS).length / 2; const length = Object.keys(PERMISSIONS).length / 2;
export function hasPermission( export function hasPermission(member: GuildMember, permission: PERMISSIONS): boolean {
member: GuildMember, for (let i = length - 1; i >= permission; i--) if (PermissionChecker[i](member)) return true;
permission: PERMISSIONS
): boolean {
for (let i = length - 1; i >= permission; i--)
if (PermissionChecker[i](member)) return true;
return false; return false;
} }
export function getPermissionLevel(member: GuildMember): number { export function getPermissionLevel(member: GuildMember): number {
for (let i = length - 1; i >= 0; i--) for (let i = length - 1; i >= 0; i--) if (PermissionChecker[i](member)) return i;
if (PermissionChecker[i](member)) return i;
return 0; return 0;
} }

View File

@ -14,16 +14,11 @@ const Storage = {
data = JSON.parse(file); data = JSON.parse(file);
} catch (error) { } catch (error) {
if (process.argv[2] !== "dev") { if (process.argv[2] !== "dev") {
$.warn( $.warn(`Malformed JSON data (header: ${header}), backing it up.`, file);
`Malformed JSON data (header: ${header}), backing it up.`,
file
);
fs.writeFile( fs.writeFile(
`${path}.backup`, `${path}.backup`,
file, file,
generateHandler( generateHandler(`Backup file of "${header}" successfully written as ${file}.`)
`Backup file of "${header}" successfully written as ${file}.`
)
); );
} }
} }
@ -39,30 +34,16 @@ const Storage = {
const result = JSON.stringify(data, null, "\t"); const result = JSON.stringify(data, null, "\t");
if (asynchronous) if (asynchronous)
fs.writeFile( fs.writeFile(path, result, generateHandler(`"${header}" sucessfully spaced and written.`));
path,
result,
generateHandler(
`"${header}" sucessfully spaced and written.`
)
);
else fs.writeFileSync(path, result); else fs.writeFileSync(path, result);
} else { } else {
const result = JSON.stringify(data); const result = JSON.stringify(data);
if (asynchronous) if (asynchronous) fs.writeFile(path, result, generateHandler(`"${header}" sucessfully written.`));
fs.writeFile(
path,
result,
generateHandler(`"${header}" sucessfully written.`)
);
else fs.writeFileSync(path, result); else fs.writeFileSync(path, result);
} }
}, },
open( open(path: string, filter?: (value: string, index: number, array: string[]) => unknown): string[] {
path: string,
filter?: (value: string, index: number, array: string[]) => unknown
): string[] {
if (!fs.existsSync(path)) fs.mkdirSync(path); if (!fs.existsSync(path)) fs.mkdirSync(path);
let directory = fs.readdirSync(path); let directory = fs.readdirSync(path);

View File

@ -47,21 +47,15 @@ class StorageStructure extends GenericStructure {
this.users = {}; this.users = {};
this.guilds = {}; this.guilds = {};
for (let id in data.users) for (let id in data.users) if (/\d{17,19}/g.test(id)) this.users[id] = new User(data.users[id]);
if (/\d{17,19}/g.test(id))
this.users[id] = new User(data.users[id]);
for (let id in data.guilds) for (let id in data.guilds) if (/\d{17,19}/g.test(id)) this.guilds[id] = new Guild(data.guilds[id]);
if (/\d{17,19}/g.test(id))
this.guilds[id] = new Guild(data.guilds[id]);
} }
/** Gets a user's profile if they exist and generate one if not. */ /** Gets a user's profile if they exist and generate one if not. */
public getUser(id: string): User { public getUser(id: string): User {
if (!/\d{17,19}/g.test(id)) if (!/\d{17,19}/g.test(id))
$.warn( $.warn(`"${id}" is not a valid user ID! It will be erased when the data loads again.`);
`"${id}" is not a valid user ID! It will be erased when the data loads again.`
);
if (id in this.users) return this.users[id]; if (id in this.users) return this.users[id];
else { else {
@ -74,9 +68,7 @@ class StorageStructure extends GenericStructure {
/** Gets a guild's settings if they exist and generate one if not. */ /** Gets a guild's settings if they exist and generate one if not. */
public getGuild(id: string): Guild { public getGuild(id: string): Guild {
if (!/\d{17,19}/g.test(id)) if (!/\d{17,19}/g.test(id))
$.warn( $.warn(`"${id}" is not a valid guild ID! It will be erased when the data loads again.`);
`"${id}" is not a valid guild ID! It will be erased when the data loads again.`
);
if (id in this.guilds) return this.guilds[id]; if (id in this.guilds) return this.guilds[id];
else { else {

View File

@ -13,12 +13,7 @@ export class NumberWrapper extends GenericWrapper<number> {
* - pluralise("part", "ies", "y") = party/parties * - pluralise("part", "ies", "y") = party/parties
* - pluralise("sheep") = sheep * - pluralise("sheep") = sheep
*/ */
public pluralise( public pluralise(word: string, plural = "", singular = "", excludeNumber = false): string {
word: string,
plural = "",
singular = "",
excludeNumber = false
): string {
let result = excludeNumber ? "" : `${this.value} `; let result = excludeNumber ? "" : `${this.value} `;
if (this.value === 1) result += word + singular; if (this.value === 1) result += word + singular;
@ -33,19 +28,9 @@ export class NumberWrapper extends GenericWrapper<number> {
* - (0).pluraliseSigned() = '+0 credits' * - (0).pluraliseSigned() = '+0 credits'
* - (1).pluraliseSigned() = '+1 credit' * - (1).pluraliseSigned() = '+1 credit'
*/ */
public pluraliseSigned( public pluraliseSigned(word: string, plural = "", singular = "", excludeNumber = false): string {
word: string,
plural = "",
singular = "",
excludeNumber = false
): string {
const sign = this.value >= 0 ? "+" : ""; const sign = this.value >= 0 ? "+" : "";
return `${sign}${this.pluralise( return `${sign}${this.pluralise(word, plural, singular, excludeNumber)}`;
word,
plural,
singular,
excludeNumber
)}`;
} }
} }
@ -53,8 +38,7 @@ export class StringWrapper extends GenericWrapper<string> {
public replaceAll(before: string, after: string): string { public replaceAll(before: string, after: string): string {
let result = this.value; let result = this.value;
while (result.indexOf(before) !== -1) while (result.indexOf(before) !== -1) result = result.replace(before, after);
result = result.replace(before, after);
return result; return result;
} }
@ -78,16 +62,11 @@ export class ArrayWrapper<T> extends GenericWrapper<T[]> {
* `$([1,2,3,4,5,6,7,8,9,10]).split(3)` = `[[1,2,3],[4,5,6],[7,8,9],[10]]` * `$([1,2,3,4,5,6,7,8,9,10]).split(3)` = `[[1,2,3],[4,5,6],[7,8,9],[10]]`
*/ */
public split(lengthOfEachSection: number): T[][] { public split(lengthOfEachSection: number): T[][] {
const amountOfSections = Math.ceil( const amountOfSections = Math.ceil(this.value.length / lengthOfEachSection);
this.value.length / lengthOfEachSection
);
const sections: T[][] = new Array(amountOfSections); const sections: T[][] = new Array(amountOfSections);
for (let index = 0; index < amountOfSections; index++) for (let index = 0; index < amountOfSections; index++)
sections[index] = this.value.slice( sections[index] = this.value.slice(index * lengthOfEachSection, (index + 1) * lengthOfEachSection);
index * lengthOfEachSection,
(index + 1) * lengthOfEachSection
);
return sections; return sections;
} }

View File

@ -8,9 +8,7 @@ export default new Event<"channelCreate">({
const botGuilds = client.guilds; const botGuilds = client.guilds;
if (channel instanceof discord.GuildChannel) { if (channel instanceof discord.GuildChannel) {
const createdGuild = await botGuilds.fetch(channel.guild.id); const createdGuild = await botGuilds.fetch(channel.guild.id);
$.log( $.log(`Channel created in '${createdGuild.name}' called '#${channel.name}'`);
`Channel created in '${createdGuild.name}' called '#${channel.name}'`
);
} }
} }
}); });

View File

@ -8,9 +8,7 @@ export default new Event<"channelDelete">({
const botGuilds = client.guilds; const botGuilds = client.guilds;
if (channel instanceof discord.GuildChannel) { if (channel instanceof discord.GuildChannel) {
const createdGuild = await botGuilds.fetch(channel.guild.id); const createdGuild = await botGuilds.fetch(channel.guild.id);
$.log( $.log(`Channel deleted in '${createdGuild.name}' called '#${channel.name}'`);
`Channel deleted in '${createdGuild.name}' called '#${channel.name}'`
);
} }
} }
}); });

View File

@ -1,10 +1,6 @@
import Event from "../core/event"; import Event from "../core/event";
import Command, {loadCommands} from "../core/command"; import Command, {loadCommands} from "../core/command";
import { import {hasPermission, getPermissionLevel, PermissionNames} from "../core/permissions";
hasPermission,
getPermissionLevel,
PermissionNames
} from "../core/permissions";
import {Permissions, Collection} from "discord.js"; import {Permissions, Collection} from "discord.js";
import {getPrefix} from "../core/structures"; import {getPrefix} from "../core/structures";
import $ from "../core/lib"; import $ from "../core/lib";
@ -23,27 +19,18 @@ export default new Event<"message">({
const prefix = getPrefix(message.guild); const prefix = getPrefix(message.guild);
if (!message.content.startsWith(prefix)) { if (!message.content.startsWith(prefix)) {
if ( if (message.client.user && message.mentions.has(message.client.user))
message.client.user && message.channel.send(`${message.author.toString()}, my prefix on this guild is \`${prefix}\`.`);
message.mentions.has(message.client.user)
)
message.channel.send(
`${message.author.toString()}, my prefix on this guild is \`${prefix}\`.`
);
return; return;
} }
const [header, ...args] = message.content const [header, ...args] = message.content.substring(prefix.length).split(/ +/);
.substring(prefix.length)
.split(/ +/);
if (!commands.has(header)) return; if (!commands.has(header)) return;
if ( if (
message.channel.type === "text" && message.channel.type === "text" &&
!message.channel !message.channel.permissionsFor(message.client.user || "")?.has(Permissions.FLAGS.SEND_MESSAGES)
.permissionsFor(message.client.user || "")
?.has(Permissions.FLAGS.SEND_MESSAGES)
) { ) {
let status; let status;
@ -65,25 +52,15 @@ export default new Event<"message">({
// Subcommand Recursion // // Subcommand Recursion //
let command = commands.get(header); let command = commands.get(header);
if (!command) if (!command) return $.warn(`Command "${header}" was called but for some reason it's still undefined!`);
return $.warn(
`Command "${header}" was called but for some reason it's still undefined!`
);
const params: any[] = []; const params: any[] = [];
let isEndpoint = false; let isEndpoint = false;
let permLevel = command.permission ?? Command.PERMISSIONS.NONE; let permLevel = command.permission ?? Command.PERMISSIONS.NONE;
for (let param of args) { for (let param of args) {
if (command.endpoint) { if (command.endpoint) {
if ( if (command.subcommands.size > 0 || command.user || command.number || command.any)
command.subcommands.size > 0 || $.warn(`An endpoint cannot have subcommands! Check ${prefix}${header} again.`);
command.user ||
command.number ||
command.any
)
$.warn(
`An endpoint cannot have subcommands! Check ${prefix}${header} again.`
);
isEndpoint = true; isEndpoint = true;
break; break;
} }
@ -97,19 +74,14 @@ export default new Event<"message">({
try { try {
params.push(await message.client.users.fetch(id)); params.push(await message.client.users.fetch(id));
} catch (error) { } catch (error) {
return message.channel.send( return message.channel.send(`No user found by the ID \`${id}\`!`);
`No user found by the ID \`${id}\`!`
);
} }
} else if (type === Command.TYPES.NUMBER) } else if (type === Command.TYPES.NUMBER) params.push(Number(param));
params.push(Number(param));
else if (type !== Command.TYPES.SUBCOMMAND) params.push(param); else if (type !== Command.TYPES.SUBCOMMAND) params.push(param);
} }
if (!message.member) if (!message.member)
return $.warn( return $.warn("This command was likely called from a DM channel meaning the member object is null.");
"This command was likely called from a DM channel meaning the member object is null."
);
if (!hasPermission(message.member, permLevel)) { if (!hasPermission(message.member, permLevel)) {
const userPermLevel = getPermissionLevel(message.member); const userPermLevel = getPermissionLevel(message.member);

View File

@ -3,18 +3,12 @@ import {Permissions} from "discord.js";
import {botHasPermission} from "../core/lib"; import {botHasPermission} from "../core/lib";
// A list of message ID and callback pairs. You get the emote name and ID of the user reacting. // A list of message ID and callback pairs. You get the emote name and ID of the user reacting.
export const eventListeners: Map< export const eventListeners: Map<string, (emote: string, id: string) => void> = new Map();
string,
(emote: string, id: string) => void
> = new Map();
// Attached to the client, there can be one event listener attached to a message ID which is executed if present. // Attached to the client, there can be one event listener attached to a message ID which is executed if present.
export default new Event<"messageReactionRemove">({ export default new Event<"messageReactionRemove">({
on(reaction, user) { on(reaction, user) {
const canDeleteEmotes = botHasPermission( const canDeleteEmotes = botHasPermission(reaction.message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
reaction.message.guild,
Permissions.FLAGS.MANAGE_MESSAGES
);
if (!canDeleteEmotes) { if (!canDeleteEmotes) {
const callback = eventListeners.get(reaction.message.id); const callback = eventListeners.get(reaction.message.id);

View File

@ -6,9 +6,7 @@ import {Config} from "../core/structures";
export default new Event<"ready">({ export default new Event<"ready">({
once() { once() {
if (client.user) { if (client.user) {
$.ready( $.ready(`Logged in as ${client.user.username}#${client.user.discriminator}.`);
`Logged in as ${client.user.username}#${client.user.discriminator}.`
);
client.user.setActivity({ client.user.setActivity({
type: "LISTENING", type: "LISTENING",
name: `${Config.prefix}help` name: `${Config.prefix}help`

View File

@ -27,14 +27,12 @@ const prompts = [
{ {
type: "input", type: "input",
name: "admins", name: "admins",
message: message: "Enter a list of bot admins (by their IDs) separated by spaces."
"Enter a list of bot admins (by their IDs) separated by spaces."
}, },
{ {
type: "input", type: "input",
name: "support", name: "support",
message: message: "Enter a list of bot troubleshooters (by their IDs) separated by spaces."
"Enter a list of bot troubleshooters (by their IDs) separated by spaces."
} }
]; ];

View File

@ -6,68 +6,41 @@ describe("Wrappers", () => {
describe("NumberWrapper", () => { describe("NumberWrapper", () => {
describe("#pluralise()", () => { describe("#pluralise()", () => {
it('should return "5 credits"', () => { it('should return "5 credits"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(5).pluralise("credit", "s"), "5 credits");
new NumberWrapper(5).pluralise("credit", "s"),
"5 credits"
);
}); });
it('should return "1 credit"', () => { it('should return "1 credit"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(1).pluralise("credit", "s"), "1 credit");
new NumberWrapper(1).pluralise("credit", "s"),
"1 credit"
);
}); });
it('should return "-1 credits"', () => { it('should return "-1 credits"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(-1).pluralise("credit", "s"), "-1 credits");
new NumberWrapper(-1).pluralise("credit", "s"),
"-1 credits"
);
}); });
it("should be able to work with a plural suffix", () => { it("should be able to work with a plural suffix", () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(2).pluralise("part", "ies", "y"), "2 parties");
new NumberWrapper(2).pluralise("part", "ies", "y"),
"2 parties"
);
}); });
it("should be able to work with a singular suffix", () => { it("should be able to work with a singular suffix", () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(1).pluralise("part", "ies", "y"), "1 party");
new NumberWrapper(1).pluralise("part", "ies", "y"),
"1 party"
);
}); });
it("should be able to exclude the number", () => { it("should be able to exclude the number", () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(1).pluralise("credit", "s", "", true), "credit");
new NumberWrapper(1).pluralise("credit", "s", "", true),
"credit"
);
}); });
}); });
describe("#pluraliseSigned()", () => { describe("#pluraliseSigned()", () => {
it('should return "-1 credits"', () => { it('should return "-1 credits"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(-1).pluraliseSigned("credit", "s"), "-1 credits");
new NumberWrapper(-1).pluraliseSigned("credit", "s"),
"-1 credits"
);
}); });
it('should return "+0 credits"', () => { it('should return "+0 credits"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(0).pluraliseSigned("credit", "s"), "+0 credits");
new NumberWrapper(0).pluraliseSigned("credit", "s"),
"+0 credits"
);
}); });
it('should return "+1 credit"', () => { it('should return "+1 credit"', () => {
assert.strictEqual( assert.strictEqual(new NumberWrapper(1).pluraliseSigned("credit", "s"), "+1 credit");
new NumberWrapper(1).pluraliseSigned("credit", "s"),
"+1 credit"
);
}); });
}); });
}); });
@ -75,19 +48,14 @@ describe("Wrappers", () => {
describe("StringWrapper", () => { describe("StringWrapper", () => {
describe("#replaceAll()", () => { describe("#replaceAll()", () => {
it('should convert "test" to "zesz"', () => { it('should convert "test" to "zesz"', () => {
assert.strictEqual( assert.strictEqual(new StringWrapper("test").replaceAll("t", "z"), "zesz");
new StringWrapper("test").replaceAll("t", "z"),
"zesz"
);
}); });
}); });
describe("#toTitleCase()", () => { describe("#toTitleCase()", () => {
it("should capitalize the first letter of each word", () => { it("should capitalize the first letter of each word", () => {
assert.strictEqual( assert.strictEqual(
new StringWrapper( new StringWrapper("yeetus deletus find salvation from jesus").toTitleCase(),
"yeetus deletus find salvation from jesus"
).toTitleCase(),
"Yeetus Deletus Find Salvation From Jesus" "Yeetus Deletus Find Salvation From Jesus"
); );
}); });
@ -97,10 +65,12 @@ describe("Wrappers", () => {
describe("ArrayWrapper", () => { describe("ArrayWrapper", () => {
describe("#split()", () => { describe("#split()", () => {
it("should split [1,2,3,4,5,6,7,8,9,10] into [[1,2,3],[4,5,6],[7,8,9],[10]]", () => { it("should split [1,2,3,4,5,6,7,8,9,10] into [[1,2,3],[4,5,6],[7,8,9],[10]]", () => {
assert.deepStrictEqual( assert.deepStrictEqual(new ArrayWrapper([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).split(3), [
new ArrayWrapper([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]).split(3), [1, 2, 3],
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]] [4, 5, 6],
); [7, 8, 9],
[10]
]);
}); });
}); });
}); });