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 = {
printWidth: 80,
printWidth: 120,
tabWidth: 4,
useTabs: false,
semi: true,

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -14,12 +14,8 @@ export const ShopCommand = new Command({
for (const item of selection)
fields.push({
name: `**${item.title}** (${getPrefix(guild)}eco buy ${
item.usage
})`,
value: `${item.description} Costs ${$(
item.cost
).pluralise("Mon", "s")}.`,
name: `**${item.title}** (${getPrefix(guild)}eco buy ${item.usage})`,
value: `${item.description} Costs ${$(item.cost).pluralise("Mon", "s")}.`,
inline: false
});
@ -40,17 +36,10 @@ export const ShopCommand = new Command({
else {
const shopPages = $(ShopItems).split(5);
const pageAmount = shopPages.length;
const msg = await channel.send(
getShopEmbed(shopPages[0], `Shop (Page 1 of ${pageAmount})`)
);
const msg = await channel.send(getShopEmbed(shopPages[0], `Shop (Page 1 of ${pageAmount})`));
$.paginate(msg, author.id, pageAmount, (page) => {
msg.edit(
getShopEmbed(
shopPages[page],
`Shop (Page ${page + 1} of ${pageAmount})`
)
);
msg.edit(getShopEmbed(shopPages[page], `Shop (Page ${page + 1} of ${pageAmount})`));
});
}
}
@ -90,10 +79,7 @@ export const BuyCommand = new Command({
}
}
if (!found)
channel.send(
`There's no item in the shop that goes by \`${requested}\`!`
);
if (!found) 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(
sender: User,
receiver: User,
amount: number
): object {
export function getSendEmbed(sender: User, receiver: User, amount: number): object {
return {
embed: {
color: 0xffff00,
@ -48,17 +44,11 @@ export function getSendEmbed(
fields: [
{
name: `Sender: ${sender.username}#${sender.discriminator}`,
value: $(Storage.getUser(sender.id).money).pluralise(
"credit",
"s"
)
value: $(Storage.getUser(sender.id).money).pluralise("credit", "s")
},
{
name: `Receiver: ${receiver.username}#${receiver.discriminator}`,
value: $(Storage.getUser(receiver.id).money).pluralise(
"credit",
"s"
)
value: $(Storage.getUser(receiver.id).money).pluralise("credit", "s")
}
],
footer: {
@ -72,16 +62,10 @@ export function getSendEmbed(
};
}
export function isAuthorized(
guild: Guild | null,
channel: TextChannel | DMChannel | NewsChannel
): boolean {
if (guild?.id === "637512823676600330" || process.argv[2] === "dev")
return true;
export function isAuthorized(guild: Guild | null, channel: TextChannel | DMChannel | NewsChannel): boolean {
if (guild?.id === "637512823676600330" || process.argv[2] === "dev") return true;
else {
channel.send(
"Sorry, this command can only be used in Monika's emote server."
);
channel.send("Sorry, this command can only be used in Monika's emote server.");
return false;
}
}

View File

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

View File

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

View File

@ -9,8 +9,7 @@ export default new Command({
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.",
async run($: CommonLibrary): Promise<any> {
if (!$.guild)
return $.channel.send(`You must use this command on a server!`);
if (!$.guild) 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.
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.
stats[emote.id] = {
name: emote.name,
formatted: `<${emote.animated ? "a" : ""}:${emote.name}:${
emote.id
}>`,
formatted: `<${emote.animated ? "a" : ""}:${emote.name}:${emote.id}>`,
users: 0,
bots: 0
};
@ -133,10 +130,7 @@ export default new Command({
// Then halt the loop and send warnings of any inconsistencies.
continueReactionLoop = false;
if (
reaction.count !==
userReactions + botReactions
) {
if (reaction.count !== userReactions + botReactions) {
$.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.`
);
@ -161,9 +155,7 @@ export default new Command({
const finishTime = Date.now();
clearInterval(interval);
statusMessage.edit(
`Finished operation in ${moment
.duration(finishTime - startTime)
.humanize()} with ${$(warnings).pluralise(
`Finished operation in ${moment.duration(finishTime - startTime).humanize()} with ${$(warnings).pluralise(
"inconsistenc",
"ies",
"y"
@ -174,9 +166,7 @@ export default new Command({
// 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.
let sortedEmoteIDs = Object.keys(stats).sort(
(a, b) => stats[b].users - stats[a].users
);
let sortedEmoteIDs = Object.keys(stats).sort((a, b) => stats[b].users - stats[a].users);
const lines: string[] = [];
let rank = 1;

View File

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

View File

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

View File

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

View File

@ -16,9 +16,7 @@ export default new Command({
try {
target = await $.channel.messages.fetch(last);
} catch {
return $.channel.send(
`No valid message found by the ID \`${last}\`!`
);
return $.channel.send(`No valid message found by the ID \`${last}\`!`);
}
$.args.pop();
@ -28,10 +26,7 @@ export default new Command({
distance = parseInt(last);
if (distance >= 0 && distance <= 99) $.args.pop();
else
return $.channel.send(
"Your distance must be between 0 and 99!"
);
else return $.channel.send("Your distance must be between 0 and 99!");
}
}
@ -48,9 +43,7 @@ export default new Command({
let anyEmoteIsValid = false;
for (const search of $.args) {
const emoji = $.client.emojis.cache.find(
(emoji) => emoji.name === search
);
const emoji = $.client.emojis.cache.find((emoji) => emoji.name === search);
if (emoji) {
// 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.",
any: new Command({
async run($: CommonLibrary): Promise<any> {
https.get(
"https://is.gd/create.php?format=simple&url=" +
encodeURIComponent($.args[0]),
function (res) {
var body = "";
res.on("data", function (chunk) {
body += chunk;
});
res.on("end", function () {
$.channel.send(`<${body}>`);
});
}
);
https.get("https://is.gd/create.php?format=simple&url=" + encodeURIComponent($.args[0]), function (res) {
var body = "";
res.on("data", function (chunk) {
body += chunk;
});
res.on("end", function () {
$.channel.send(`<${body}>`);
});
});
}
})
});

View File

@ -58,8 +58,7 @@ export default class Command {
const baseSubcommands = Object.keys(options.subcommands);
// Loop once to set the base subcommands.
for (const name in options.subcommands)
this.subcommands.set(name, options.subcommands[name]);
for (const name in options.subcommands) 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.
// 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.
else if (this.user && /\d{17,19}/.test(param)) return TYPES.USER;
// Disallow infinity and allow for 0.
else if (
this.number &&
(Number(param) || param === "0") &&
!param.includes("Infinity")
)
return TYPES.NUMBER;
else if (this.number && (Number(param) || param === "0") && !param.includes("Infinity")) return TYPES.NUMBER;
else if (this.any) return TYPES.ANY;
else return TYPES.NONE;
}
@ -166,9 +160,7 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
writeFile(
"src/commands/test.ts",
template,
generateHandler(
'"test.ts" (testing/template command) successfully generated.'
)
generateHandler('"test.ts" (testing/template command) successfully generated.')
);
commands = new Collection();
@ -189,10 +181,7 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
while ((cmd = await subdir.read())) {
if (cmd.isDirectory()) {
if (cmd.name === "subcommands") continue;
else
$.warn(
`You can't have multiple levels of directories! From: "dist/commands/${cmd.name}"`
);
else $.warn(`You can't have multiple levels of directories! From: "dist/commands/${cmd.name}"`);
} else loadCommand(cmd.name, list, selected.name);
}
@ -207,25 +196,14 @@ export async function loadCommands(): Promise<Collection<string, Command>> {
return commands;
}
async function loadCommand(
filename: string,
list: string[],
category?: string
) {
if (!commands)
return $.error(
`Function "loadCommand" was called without first initializing commands!`
);
async function loadCommand(filename: string, list: string[], category?: string) {
if (!commands) return $.error(`Function "loadCommand" was called without first initializing commands!`);
const prefix = category ?? "";
const header = filename.substring(0, filename.indexOf(".js"));
const command = (await import(`../commands/${prefix}/${header}`))
.default as Command | undefined;
const command = (await import(`../commands/${prefix}/${header}`)).default as Command | undefined;
if (!command)
return $.warn(
`Command "${header}" has no default export which is a Command instance!`
);
if (!command) return $.warn(`Command "${header}" has no default export which is a Command instance!`);
command.originalCommandName = header;
list.push(header);
@ -238,17 +216,11 @@ async function loadCommand(
for (const alias of command.aliases) {
if (commands.has(alias))
$.warn(
`Top-level alias "${alias}" from command "${header}" already exists either as a command or alias!`
);
$.warn(`Top-level alias "${alias}" from command "${header}" already exists either as a command or alias!`);
else commands.set(alias, command);
}
$.log(
`Loading Command: ${header} (${
category ? $(category).toTitleCase() : "Miscellaneous"
})`
);
$.log(`Loading Command: ${header} (${category ? $(category).toTitleCase() : "Miscellaneous"})`);
}
// 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) {
for (const file of Storage.open("dist/events", (filename: string) =>
filename.endsWith(".js")
)) {
for (const file of Storage.open("dist/events", (filename: string) => filename.endsWith(".js"))) {
const header = file.substring(0, file.indexOf(".js"));
const event = (await import(`../events/${header}`)).default;

View File

@ -1,20 +1,5 @@
import {
GenericWrapper,
NumberWrapper,
StringWrapper,
ArrayWrapper
} from "./wrappers";
import {
Client,
Message,
TextChannel,
DMChannel,
NewsChannel,
Guild,
User,
GuildMember,
Permissions
} from "discord.js";
import {GenericWrapper, NumberWrapper, StringWrapper, ArrayWrapper} from "./wrappers";
import {Client, Message, TextChannel, DMChannel, NewsChannel, Guild, User, GuildMember, Permissions} from "discord.js";
import chalk from "chalk";
import {get} from "https";
import FileManager from "./storage";
@ -45,16 +30,8 @@ export interface CommonLibrary {
callback: (page: number) => void,
duration?: number
) => void;
prompt: (
message: Message,
senderID: string,
onConfirm: () => void,
duration?: number
) => void;
getMemberByUsername: (
guild: Guild,
username: string
) => Promise<GuildMember | undefined>;
prompt: (message: Message, senderID: string, onConfirm: () => void, duration?: number) => void;
getMemberByUsername: (guild: Guild, username: string) => Promise<GuildMember | undefined>;
callMemberByUsername: (
message: Message,
username: string,
@ -88,9 +65,7 @@ export default function $(value: any) {
$.handler = function (this: CommonLibrary, error: Error) {
if (this)
this.channel.send(
`There was an error while trying to execute that command!\`\`\`${
error.stack ?? error
}\`\`\``
`There was an error while trying to execute that command!\`\`\`${error.stack ?? error}\`\`\``
);
else
$.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.
// General Purpose Logger
$.log = (...args: any[]) => {
if (enabled)
console.log(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgWhite("INFO"),
...args
);
if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgWhite("INFO"), ...args);
const text = `[${formatUTCTimestamp()}] [INFO] ${args.join(" ")}\n`;
logs.info += text;
@ -130,12 +100,7 @@ $.log = (...args: any[]) => {
};
// "It'll still work, but you should really check up on this."
$.warn = (...args: any[]) => {
if (enabled)
console.warn(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgYellow("WARN"),
...args
);
if (enabled) console.warn(chalk.white.bgGray(formatTimestamp()), chalk.black.bgYellow("WARN"), ...args);
const text = `[${formatUTCTimestamp()}] [WARN] ${args.join(" ")}\n`;
logs.warn += text;
@ -144,12 +109,7 @@ $.warn = (...args: any[]) => {
};
// Used for anything which prevents the program from actually running.
$.error = (...args: any[]) => {
if (enabled)
console.error(
chalk.white.bgGray(formatTimestamp()),
chalk.white.bgRed("ERROR"),
...args
);
if (enabled) console.error(chalk.white.bgGray(formatTimestamp()), chalk.white.bgRed("ERROR"), ...args);
const text = `[${formatUTCTimestamp()}] [ERROR] ${args.join(" ")}\n`;
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.
$.debug = (...args: any[]) => {
if (process.argv[2] === "dev" && enabled)
console.debug(
chalk.white.bgGray(formatTimestamp()),
chalk.white.bgBlue("DEBUG"),
...args
);
console.debug(chalk.white.bgGray(formatTimestamp()), chalk.white.bgBlue("DEBUG"), ...args);
const text = `[${formatUTCTimestamp()}] [DEBUG] ${args.join(" ")}\n`;
logs.verbose += text;
};
// Used once at the start of the program when the bot loads.
$.ready = (...args: any[]) => {
if (enabled)
console.log(
chalk.white.bgGray(formatTimestamp()),
chalk.black.bgGreen("READY"),
...args
);
if (enabled) console.log(chalk.white.bgGray(formatTimestamp()), chalk.black.bgGreen("READY"), ...args);
const text = `[${formatUTCTimestamp()}] [READY] ${args.join(" ")}\n`;
logs.info += text;
@ -205,14 +156,8 @@ export function formatUTCTimestamp(now = new Date()) {
return `${year}-${month}-${day} ${hour}:${minute}:${second}`;
}
export function botHasPermission(
guild: Guild | null,
permission: number
): boolean {
return !!(
client.user &&
guild?.members.resolve(client.user)?.hasPermission(permission)
);
export function botHasPermission(guild: Guild | null, permission: number): boolean {
return !!(client.user && guild?.members.resolve(client.user)?.hasPermission(permission));
}
// Pagination function that allows for customization via a callback.
@ -253,10 +198,7 @@ $.paginate = async (
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.
// This will dynamically adjust for that, switching modes depending on whether it currently has the "Manage Messages" permission.
const canDeleteEmotes = botHasPermission(
message.guild,
Permissions.FLAGS.MANAGE_MESSAGES
);
const canDeleteEmotes = botHasPermission(message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
handle(reaction.emoji.name, user.id);
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).
$.prompt = async (
message: Message,
senderID: string,
onConfirm: () => void,
duration = 10000
) => {
$.prompt = async (message: Message, senderID: string, onConfirm: () => void, duration = 10000) => {
let isDeleted = false;
message.react("✅");
@ -312,11 +249,7 @@ $.getMemberByUsername = async (guild: Guild, username: string) => {
};
/** Convenience function to handle false cases automatically. */
$.callMemberByUsername = async (
message: Message,
username: string,
onSuccess: (member: GuildMember) => void
) => {
$.callMemberByUsername = async (message: Message, username: string, onSuccess: (member: GuildMember) => void) => {
const guild = message.guild;
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.
*/
export function parseVars(
line: string,
definitions: {[key: string]: string},
invalid: string | null = ""
): string {
export function parseVars(line: string, definitions: {[key: string]: string}, invalid: string | null = ""): string {
let result = "";
let inVariable = false;
let token = "";
@ -397,10 +326,7 @@ export function parseVars(
export function isType(value: any, type: any): boolean {
if (value === undefined && type === undefined) return true;
else if (value === null && type === null) return true;
else
return (
value !== undefined && value !== null && value.constructor === type
);
else 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.
* Warning: Type checking is based on the fallback's type. Be sure that the "type" parameter is accurate to this!
*/
export function select<T>(
value: any,
fallback: T,
type: Function,
isArray = false
): T {
export function select<T>(value: any, fallback: T, type: Function, isArray = false): T {
if (isArray && isType(value, Array)) {
for (let item of value) if (!isType(item, type)) return fallback;
return value;
@ -426,9 +347,7 @@ export function select<T>(
export function clean(text: any) {
if (typeof text === "string")
return text
.replace(/`/g, "`" + String.fromCharCode(8203))
.replace(/@/g, "@" + String.fromCharCode(8203));
return text.replace(/`/g, "`" + String.fromCharCode(8203)).replace(/@/g, "@" + String.fromCharCode(8203));
else return text;
}
@ -450,34 +369,26 @@ export function formatBytes(bytes: any) {
export function getContent(url: any) {
return new Promise((resolve, reject) => {
get(
url,
(res: {
resume?: any;
setEncoding?: any;
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}`);
}
});
get(url, (res: {resume?: any; setEncoding?: any; on?: any; statusCode?: any}) => {
const {statusCode} = res;
if (statusCode !== 200) {
res.resume();
reject(`Request failed. Status code: ${statusCode}`);
}
).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}`);
});
});
@ -510,6 +421,5 @@ export const Random = {
int: (min: number, max: number) => Math.floor(Random.num(min, max)),
chance: (decimal: number) => Math.random() < decimal,
sign: (number = 1) => number * (Random.chance(0.5) ? -1 : 1),
deviation: (base: number, deviation: number) =>
Random.num(base - deviation, base + deviation)
deviation: (base: number, deviation: number) => 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.
const length = Object.keys(PERMISSIONS).length / 2;
export function hasPermission(
member: GuildMember,
permission: PERMISSIONS
): boolean {
for (let i = length - 1; i >= permission; i--)
if (PermissionChecker[i](member)) return true;
export function hasPermission(member: GuildMember, permission: PERMISSIONS): boolean {
for (let i = length - 1; i >= permission; i--) if (PermissionChecker[i](member)) return true;
return false;
}
export function getPermissionLevel(member: GuildMember): number {
for (let i = length - 1; i >= 0; i--)
if (PermissionChecker[i](member)) return i;
for (let i = length - 1; i >= 0; i--) if (PermissionChecker[i](member)) return i;
return 0;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,18 +3,12 @@ import {Permissions} from "discord.js";
import {botHasPermission} from "../core/lib";
// A list of message ID and callback pairs. You get the emote name and ID of the user reacting.
export const eventListeners: Map<
string,
(emote: string, id: string) => void
> = new Map();
export const eventListeners: 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.
export default new Event<"messageReactionRemove">({
on(reaction, user) {
const canDeleteEmotes = botHasPermission(
reaction.message.guild,
Permissions.FLAGS.MANAGE_MESSAGES
);
const canDeleteEmotes = botHasPermission(reaction.message.guild, Permissions.FLAGS.MANAGE_MESSAGES);
if (!canDeleteEmotes) {
const callback = eventListeners.get(reaction.message.id);

View File

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

View File

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

View File

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