Reduced clunkiness of rest type and applied changes to commands

This commit is contained in:
WatDuhHekBro 2021-04-10 12:07:55 -05:00
parent 26e0bb5824
commit 15012c7d17
19 changed files with 217 additions and 204 deletions

View File

@ -1,4 +1,4 @@
import {Command, NamedCommand, getMemberByName} from "../../core"; import {Command, NamedCommand, getMemberByName, RestCommand} from "../../core";
import {isAuthorized, getMoneyEmbed} from "./modules/eco-utils"; import {isAuthorized, getMoneyEmbed} from "./modules/eco-utils";
import {DailyCommand, PayCommand, GuildCommand, LeaderboardCommand} from "./modules/eco-core"; import {DailyCommand, PayCommand, GuildCommand, LeaderboardCommand} from "./modules/eco-core";
import {BuyCommand, ShopCommand} from "./modules/eco-shop"; import {BuyCommand, ShopCommand} from "./modules/eco-shop";
@ -33,11 +33,11 @@ export default new NamedCommand({
if (isAuthorized(guild, channel)) send(getMoneyEmbed(args[0])); if (isAuthorized(guild, channel)) send(getMoneyEmbed(args[0]));
} }
}), }),
any: new Command({ any: new RestCommand({
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({send, guild, channel, args, message}) { async run({send, guild, channel, args, message, combined}) {
if (isAuthorized(guild, channel)) { if (isAuthorized(guild, channel)) {
const member = await getMemberByName(guild!, args.join(" ")); const member = await getMemberByName(guild!, combined);
if (member instanceof GuildMember) send(getMoneyEmbed(member.user)); if (member instanceof GuildMember) send(getMoneyEmbed(member.user));
else send(member); else send(member);
} }

View File

@ -1,17 +1,19 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import figlet from "figlet"; import figlet from "figlet";
export default new NamedCommand({ export default new NamedCommand({
description: "Generates a figlet of your input.", description: "Generates a figlet of your input.",
async run({send, message, channel, guild, author, member, client, args}) { run: "You have to provide input for me to create a figlet!",
const input = args.join(" "); any: new RestCommand({
if (!args[0]) return send("You have to provide input for me to create a figlet!"); async run({send, message, channel, guild, author, member, client, args, combined}) {
return send( return send(
"```" + figlet.textSync(combined, {
figlet.textSync(`${input}`, {
horizontalLayout: "full" horizontalLayout: "full"
}) + }),
"```" {
); code: true
} }
);
}
})
}); });

View File

@ -1,4 +1,5 @@
import {Command, NamedCommand, prompt} from "../../../core"; import {GuildMember} from "discord.js";
import {Command, getMemberByName, NamedCommand, prompt, RestCommand} from "../../../core";
import {pluralise} from "../../../lib"; import {pluralise} from "../../../lib";
import {Storage} from "../../../structures"; import {Storage} from "../../../structures";
import {isAuthorized, getMoneyEmbed, getSendEmbed, ECO_EMBED_COLOR} from "./eco-utils"; import {isAuthorized, getMoneyEmbed, getSendEmbed, ECO_EMBED_COLOR} from "./eco-utils";
@ -140,8 +141,8 @@ export const PayCommand = new NamedCommand({
number: new Command({ number: new Command({
run: "You must use the format `eco pay <user> <amount>`!" run: "You must use the format `eco pay <user> <amount>`!"
}), }),
any: new Command({ any: new RestCommand({
async run({send, args, author, channel, guild}) { async run({send, args, author, channel, guild, combined}) {
if (isAuthorized(guild, channel)) { if (isAuthorized(guild, channel)) {
const last = args.pop(); const last = args.pop();
@ -156,18 +157,8 @@ export const PayCommand = new NamedCommand({
else if (!guild) else if (!guild)
return send("You have to use this in a server if you want to send Mons with a username!"); return send("You have to use this in a server if you want to send Mons with a username!");
const username = args.join(" "); const member = await getMemberByName(guild, combined);
const member = ( if (!(member instanceof GuildMember)) return send(member);
await guild.members.fetch({
query: username,
limit: 1
})
).first();
if (!member)
return send(
`Couldn't find a user by the name of \`${username}\`! If you want to send Mons to someone in a different server, you have to use their user ID!`
);
else if (member.user.id === author.id) return send("You can't send Mons to yourself!"); else if (member.user.id === author.id) return send("You can't send Mons to yourself!");
else if (member.user.bot && process.argv[2] !== "dev") return send("You can't send Mons to a bot!"); else if (member.user.bot && process.argv[2] !== "dev") return send("You can't send Mons to a bot!");

View File

@ -1,4 +1,4 @@
import {Command, NamedCommand, paginate} from "../../../core"; import {Command, NamedCommand, paginate, RestCommand} from "../../../core";
import {pluralise, split} from "../../../lib"; import {pluralise, split} from "../../../lib";
import {Storage, getPrefix} from "../../../structures"; import {Storage, getPrefix} from "../../../structures";
import {isAuthorized, ECO_EMBED_COLOR} from "./eco-utils"; import {isAuthorized, ECO_EMBED_COLOR} from "./eco-utils";
@ -47,37 +47,37 @@ export const ShopCommand = new NamedCommand({
export const BuyCommand = new NamedCommand({ export const BuyCommand = new NamedCommand({
description: "Buys an item from the shop.", description: "Buys an item from the shop.",
usage: "<item>", usage: "<item>",
async run({send, guild, channel, args, message, author}) { run: "You need to specify an item to buy.",
if (isAuthorized(guild, channel)) { any: new RestCommand({
let found = false; async run({send, guild, channel, args, message, author, combined}) {
if (isAuthorized(guild, channel)) {
let found = false;
let amount = 1; // The amount the user is buying.
let amount = 1; // The amount the user is buying. // For now, no shop items support being bought multiple times. Uncomment these 2 lines when it's supported/needed.
//if (/\d+/g.test(args[args.length - 1]))
//amount = parseInt(args.pop());
// For now, no shop items support being bought multiple times. Uncomment these 2 lines when it's supported/needed. for (let item of ShopItems) {
//if (/\d+/g.test(args[args.length - 1])) if (item.usage === combined) {
//amount = parseInt(args.pop()); const user = Storage.getUser(author.id);
const cost = item.cost * amount;
let requested = args.join(" "); // The item the user is buying. if (cost > user.money) {
send("Not enough Mons!");
} else {
user.money -= cost;
Storage.save();
item.run(message, cost, amount);
}
for (let item of ShopItems) { found = true;
if (item.usage === requested) { break;
const user = Storage.getUser(author.id);
const cost = item.cost * amount;
if (cost > user.money) {
send("Not enough Mons!");
} else {
user.money -= cost;
Storage.save();
item.run(message, cost, amount);
} }
found = true;
break;
} }
}
if (!found) send(`There's no item in the shop that goes by \`${requested}\`!`); if (!found) send(`There's no item in the shop that goes by \`${combined}\`!`);
}
} }
} })
}); });

View File

@ -1,12 +1,15 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import {getContent} from "../../lib"; import {getContent} from "../../lib";
import {URL} from "url"; import {URL} from "url";
export default new NamedCommand({ export default new NamedCommand({
description: "OwO-ifies the input.", description: "OwO-ifies the input.",
async run({send, message, channel, guild, author, member, client, args}) { run: "You need to specify some text to owoify.",
let url = new URL(`https://nekos.life/api/v2/owoify?text=${args.join(" ")}`); any: new RestCommand({
const content = (await getContent(url.toString())) as any; // Apparently, the object in question is {owo: string}. async run({send, message, channel, guild, author, member, client, args, combined}) {
send(content.owo); let url = new URL(`https://nekos.life/api/v2/owoify?text=${combined}`);
} const content = (await getContent(url.toString())) as any; // Apparently, the object in question is {owo: string}.
send(content.owo);
}
})
}); });

View File

@ -1,13 +1,13 @@
import {MessageEmbed} from "discord.js"; import {MessageEmbed} from "discord.js";
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
export default new NamedCommand({ export default new NamedCommand({
description: "Create a poll.", description: "Create a poll.",
usage: "<question>", usage: "<question>",
run: "Please provide a question.", run: "Please provide a question.",
any: new Command({ any: new RestCommand({
description: "Question for the poll.", description: "Question for the poll.",
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setAuthor( .setAuthor(
`Poll created by ${message.author.username}`, `Poll created by ${message.author.username}`,
@ -15,7 +15,7 @@ export default new NamedCommand({
) )
.setColor(0xffffff) .setColor(0xffffff)
.setFooter("React to vote.") .setFooter("React to vote.")
.setDescription(args.join(" ")); .setDescription(combined);
const msg = await send(embed); const msg = await send(embed);
await msg.react("✅"); await msg.react("✅");
await msg.react("⛔"); await msg.react("⛔");

View File

@ -1,14 +1,14 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import {MessageEmbed} from "discord.js"; import {MessageEmbed} from "discord.js";
import urban from "relevant-urban"; import urban from "relevant-urban";
export default new NamedCommand({ export default new NamedCommand({
description: "Gives you a definition of the inputted word.", description: "Gives you a definition of the inputted word.",
run: "Please input a word.", run: "Please input a word.",
any: new Command({ any: new RestCommand({
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
// [Bug Fix]: Use encodeURIComponent() when emojis are used: "TypeError [ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters" // [Bug Fix]: Use encodeURIComponent() when emojis are used: "TypeError [ERR_UNESCAPED_CHARACTERS]: Request path contains unescaped characters"
urban(encodeURIComponent(args.join(" "))) urban(encodeURIComponent(combined))
.then((res) => { .then((res) => {
const embed = new MessageEmbed() const embed = new MessageEmbed()
.setColor(0x1d2439) .setColor(0x1d2439)

View File

@ -1,4 +1,4 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
const vaporwave = (() => { const vaporwave = (() => {
const map = new Map<string, string>(); const map = new Map<string, string>();
@ -24,9 +24,9 @@ function getVaporwaveText(text: string): string {
export default new NamedCommand({ export default new NamedCommand({
description: "Transforms your text into .", description: "Transforms your text into .",
run: "You need to enter some text!", run: "You need to enter some text!",
any: new Command({ any: new RestCommand({
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
const text = getVaporwaveText(args.join(" ")); const text = getVaporwaveText(combined);
if (text !== "") send(text); if (text !== "") send(text);
else send("Make sure to enter at least one valid character."); else send("Make sure to enter at least one valid character.");
} }

View File

@ -1,15 +1,15 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import {MessageEmbed} from "discord.js"; import {MessageEmbed} from "discord.js";
import {find} from "weather-js"; import {find} from "weather-js";
export default new NamedCommand({ export default new NamedCommand({
description: "Shows weather info of specified location.", description: "Shows weather info of specified location.",
run: "You need to provide a city.", run: "You need to provide a city.",
any: new Command({ any: new RestCommand({
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
find( find(
{ {
search: args.join(" "), search: combined,
degreeType: "C" degreeType: "C"
}, },
function (error, result) { function (error, result) {

View File

@ -1,5 +1,5 @@
import {User, GuildMember} from "discord.js"; import {User, GuildMember} from "discord.js";
import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE} from "../../core"; import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE, RestCommand} from "../../core";
// Quotes must be used here or the numbers will change // Quotes must be used here or the numbers will change
const registry: {[id: string]: string} = { const registry: {[id: string]: string} = {
@ -65,11 +65,10 @@ export default new NamedCommand({
} }
} }
}), }),
any: new Command({ any: new RestCommand({
channelType: CHANNEL_TYPE.GUILD, channelType: CHANNEL_TYPE.GUILD,
async run({send, message, channel, guild, author, client, args}) { async run({send, message, channel, guild, author, client, args, combined}) {
const query = args.join(" ") as string; const member = await getMemberByName(guild!, combined);
const member = await getMemberByName(guild!, query);
if (member instanceof GuildMember) { if (member instanceof GuildMember) {
if (member.id in registry) { if (member.id in registry) {

View File

@ -1,4 +1,12 @@
import {Command, NamedCommand, botHasPermission, getPermissionLevel, getPermissionName, CHANNEL_TYPE} from "../../core"; import {
Command,
NamedCommand,
botHasPermission,
getPermissionLevel,
getPermissionName,
CHANNEL_TYPE,
RestCommand
} from "../../core";
import {clean} from "../../lib"; import {clean} from "../../lib";
import {Config, Storage} from "../../structures"; import {Config, Storage} from "../../structures";
import {Permissions, TextChannel, User} from "discord.js"; import {Permissions, TextChannel, User} from "discord.js";
@ -119,12 +127,11 @@ export default new NamedCommand({
Storage.save(); Storage.save();
send("Reset your server's welcome message to the default."); send("Reset your server's welcome message to the default.");
}, },
any: new Command({ any: new RestCommand({
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
const newMessage = args.join(" "); Storage.getGuild(guild!.id).welcomeMessage = combined;
Storage.getGuild(guild!.id).welcomeMessage = newMessage;
Storage.save(); Storage.save();
send(`Set your server's welcome message to \`${newMessage}\`.`); send(`Set your server's welcome message to \`${combined}\`.`);
} }
}) })
}) })
@ -241,29 +248,32 @@ export default new NamedCommand({
description: "Evaluate code.", description: "Evaluate code.",
usage: "<code>", usage: "<code>",
permission: PERMISSIONS.BOT_OWNER, permission: PERMISSIONS.BOT_OWNER,
// You have to bring everything into scope to use them. AFAIK, there isn't a more maintainable way to do this, but at least TS will let you know if anything gets removed. run: "You have to enter some code to execute first.",
async run({send, message, channel, guild, author, member, client, args}) { any: new RestCommand({
try { // You have to bring everything into scope to use them. AFAIK, there isn't a more maintainable way to do this, but at least TS will let you know if anything gets removed.
const code = args.join(" "); async run({send, message, channel, guild, author, member, client, args, combined}) {
let evaled = eval(code); try {
let evaled = eval(combined);
if (typeof evaled !== "string") evaled = require("util").inspect(evaled); if (typeof evaled !== "string") evaled = require("util").inspect(evaled);
send(clean(evaled), {code: "js", split: true}); send(clean(evaled), {code: "js", split: true});
} catch (err) { } catch (err) {
send(clean(err), {code: "js", split: true}); send(clean(err), {code: "js", split: true});
}
} }
} })
}), }),
nick: new NamedCommand({ nick: new NamedCommand({
description: "Change the bot's nickname.", description: "Change the bot's nickname.",
permission: PERMISSIONS.BOT_SUPPORT, permission: PERMISSIONS.BOT_SUPPORT,
channelType: CHANNEL_TYPE.GUILD, channelType: CHANNEL_TYPE.GUILD,
async run({send, message, channel, guild, author, member, client, args}) { run: "You have to specify a nickname to set for the bot",
const nickName = args.join(" "); any: new RestCommand({
await guild!.me?.setNickname(nickName); async run({send, message, channel, guild, author, member, client, args, combined}) {
if (botHasPermission(guild, Permissions.FLAGS.MANAGE_MESSAGES)) message.delete({timeout: 5000}); await guild!.me?.setNickname(combined);
send(`Nickname set to \`${nickName}\``).then((m) => m.delete({timeout: 5000})); if (botHasPermission(guild, Permissions.FLAGS.MANAGE_MESSAGES)) message.delete({timeout: 5000});
} send(`Nickname set to \`${combined}\``).then((m) => m.delete({timeout: 5000}));
}
})
}), }),
guilds: new NamedCommand({ guilds: new NamedCommand({
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.",

View File

@ -53,7 +53,6 @@ export default new NamedCommand({
list.push(` \`${header} ${type}${customUsage}\` - ${subcommand.description}`); list.push(` \`${header} ${type}${customUsage}\` - ${subcommand.description}`);
} }
if (result.hasRestCommand) list.push(` \`${header} <...>\``);
append = list.length > 0 ? list.join("\n") : "None"; append = list.length > 0 ? list.join("\n") : "None";
} else { } else {
append = `\`${header} ${command.usage}\``; append = `\`${header} ${command.usage}\``;

View File

@ -1,22 +1,24 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import * as math from "mathjs"; import * as math from "mathjs";
import {MessageEmbed} from "discord.js"; import {MessageEmbed} from "discord.js";
export default new NamedCommand({ export default new NamedCommand({
description: "Calculates a specified math expression.", description: "Calculates a specified math expression.",
async run({send, message, channel, guild, author, member, client, args}) { run: "Please provide a calculation.",
if (!args[0]) return send("Please provide a calculation."); any: new RestCommand({
let resp; async run({send, message, channel, guild, author, member, client, args, combined}) {
try { let resp;
resp = math.evaluate(args.join(" ")); try {
} catch (e) { resp = math.evaluate(combined);
return send("Please provide a *valid* calculation."); } catch (e) {
return send("Please provide a *valid* calculation.");
}
const embed = new MessageEmbed()
.setColor(0xffffff)
.setTitle("Math Calculation")
.addField("Input", `\`\`\`js\n${combined}\`\`\``)
.addField("Output", `\`\`\`js\n${resp}\`\`\``);
return send(embed);
} }
const embed = new MessageEmbed() })
.setColor(0xffffff)
.setTitle("Math Calculation")
.addField("Input", `\`\`\`js\n${args.join("")}\`\`\``)
.addField("Output", `\`\`\`js\n${resp}\`\`\``);
return send(embed);
}
}); });

View File

@ -1,19 +1,21 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
export default new NamedCommand({ export default new NamedCommand({
description: "Renames current voice channel.", description: "Renames current voice channel.",
usage: "<name>", usage: "<name>",
async run({send, message, channel, guild, author, member, client, args}) { run: "Please provide a new voice channel name.",
const voiceChannel = message.member?.voice.channel; any: new RestCommand({
async run({send, message, channel, guild, author, member, client, args, combined}) {
const voiceChannel = message.member?.voice.channel;
if (!voiceChannel) return send("You are not in a voice channel."); if (!voiceChannel) return send("You are not in a voice channel.");
if (!voiceChannel.guild.me?.hasPermission("MANAGE_CHANNELS")) if (!voiceChannel.guild.me?.hasPermission("MANAGE_CHANNELS"))
return send("I am lacking the required permissions to perform this action."); return send("I am lacking the required permissions to perform this action.");
if (args.length === 0) return send("Please provide a new voice channel name.");
const prevName = voiceChannel.name; const prevName = voiceChannel.name;
const newName = args.join(" "); const newName = combined;
await voiceChannel.setName(newName); await voiceChannel.setName(newName);
return await send(`Changed channel name from "${prevName}" to "${newName}".`); return await send(`Changed channel name from "${prevName}" to "${newName}".`);
} }
})
}); });

View File

@ -1,7 +1,7 @@
import {MessageEmbed, version as djsversion, Guild, User, GuildMember} from "discord.js"; import {MessageEmbed, version as djsversion, Guild, User, GuildMember} from "discord.js";
import ms from "ms"; import ms from "ms";
import os from "os"; import os from "os";
import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE, getGuildByName} from "../../core"; import {Command, NamedCommand, getMemberByName, CHANNEL_TYPE, getGuildByName, RestCommand} from "../../core";
import {formatBytes, trimArray} from "../../lib"; import {formatBytes, trimArray} from "../../lib";
import {verificationLevels, filterLevels, regions} from "../../defs/info"; import {verificationLevels, filterLevels, regions} from "../../defs/info";
import moment, {utc} from "moment"; import moment, {utc} from "moment";
@ -30,12 +30,11 @@ export default new NamedCommand({
); );
} }
}), }),
any: new Command({ any: new RestCommand({
description: "Shows another user's avatar by searching their name", description: "Shows another user's avatar by searching their name",
channelType: CHANNEL_TYPE.GUILD, channelType: CHANNEL_TYPE.GUILD,
async run({send, message, channel, guild, author, client, args}) { async run({send, message, channel, guild, author, client, args, combined}) {
const name = args.join(" "); const member = await getMemberByName(guild!, combined);
const member = await getMemberByName(guild!, name);
if (member instanceof GuildMember) { if (member instanceof GuildMember) {
send( send(
@ -106,10 +105,10 @@ export default new NamedCommand({
send(await getGuildInfo(targetGuild, guild)); send(await getGuildInfo(targetGuild, guild));
} }
}), }),
any: new Command({ any: new RestCommand({
description: "Display info about a guild by finding its name.", description: "Display info about a guild by finding its name.",
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
const targetGuild = getGuildByName(args.join(" ")); const targetGuild = getGuildByName(combined);
if (targetGuild instanceof Guild) { if (targetGuild instanceof Guild) {
send(await getGuildInfo(targetGuild, guild)); send(await getGuildInfo(targetGuild, guild));

View File

@ -1,13 +1,13 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
export default new NamedCommand({ export default new NamedCommand({
description: "Repeats your message.", description: "Repeats your message.",
usage: "<message>", usage: "<message>",
run: "Please provide a message for me to say!", run: "Please provide a message for me to say!",
any: new Command({ any: new RestCommand({
description: "Message to repeat.", description: "Message to repeat.",
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args, combined}) {
send(`*${author} says:*\n${args.join(" ")}`); send(`*${author} says:*\n${combined}`);
} }
}) })
}); });

View File

@ -1,4 +1,13 @@
import {Command, NamedCommand, ask, askYesOrNo, askMultipleChoice, prompt, getMemberByName} from "../../core"; import {
Command,
NamedCommand,
ask,
askYesOrNo,
askMultipleChoice,
prompt,
getMemberByName,
RestCommand
} from "../../core";
import {Storage} from "../../structures"; import {Storage} from "../../structures";
import {User, GuildMember} from "discord.js"; import {User, GuildMember} from "discord.js";
import moment from "moment"; import moment from "moment";
@ -381,10 +390,10 @@ export default new NamedCommand({
send(getTimeEmbed(args[0])); send(getTimeEmbed(args[0]));
} }
}), }),
any: new Command({ any: new RestCommand({
description: "See what time it is for someone else (by their username).", description: "See what time it is for someone else (by their username).",
async run({send, channel, args, guild}) { async run({send, channel, args, guild, combined}) {
const member = await getMemberByName(guild!, args.join(" ")); const member = await getMemberByName(guild!, combined);
if (member instanceof GuildMember) send(getTimeEmbed(member.user)); if (member instanceof GuildMember) send(getTimeEmbed(member.user));
else send(member); else send(member);
} }

View File

@ -1,4 +1,4 @@
import {Command, NamedCommand} from "../../core"; import {Command, NamedCommand, RestCommand} from "../../core";
import moment from "moment"; import moment from "moment";
import {Storage} from "../../structures"; import {Storage} from "../../structures";
import {MessageEmbed} from "discord.js"; import {MessageEmbed} from "discord.js";
@ -21,34 +21,38 @@ export default new NamedCommand({
}, },
subcommands: { subcommands: {
add: new NamedCommand({ add: new NamedCommand({
async run({send, message, channel, guild, author, member, client, args}) { run: "You need to specify a note to add.",
const user = Storage.getUser(author.id); any: new RestCommand({
const note = args.join(" "); async run({send, message, channel, guild, author, member, client, args, combined}) {
user.todoList[Date.now().toString()] = note; const user = Storage.getUser(author.id);
console.debug(user.todoList); user.todoList[Date.now().toString()] = combined;
Storage.save(); console.debug(user.todoList);
send(`Successfully added \`${note}\` to your todo list.`); Storage.save();
} send(`Successfully added \`${combined}\` to your todo list.`);
}
})
}), }),
remove: new NamedCommand({ remove: new NamedCommand({
async run({send, message, channel, guild, author, member, client, args}) { run: "You need to specify a note to remove.",
const user = Storage.getUser(author.id); any: new RestCommand({
const note = args.join(" "); async run({send, message, channel, guild, author, member, client, args, combined}) {
let isFound = false; const user = Storage.getUser(author.id);
let isFound = false;
for (const timestamp in user.todoList) { for (const timestamp in user.todoList) {
const selectedNote = user.todoList[timestamp]; const selectedNote = user.todoList[timestamp];
if (selectedNote === note) { if (selectedNote === combined) {
delete user.todoList[timestamp]; delete user.todoList[timestamp];
Storage.save(); Storage.save();
isFound = true; isFound = true;
send(`Removed \`${note}\` from your todo list.`); send(`Removed \`${combined}\` from your todo list.`);
}
} }
}
if (!isFound) send("That item couldn't be found."); if (!isFound) send("That item couldn't be found.");
} }
})
}), }),
clear: new NamedCommand({ clear: new NamedCommand({
async run({send, message, channel, guild, author, member, client, args}) { async run({send, message, channel, guild, author, member, client, args}) {

View File

@ -82,7 +82,6 @@ interface CommandOptionsBase {
interface CommandOptionsEndpoint { interface CommandOptionsEndpoint {
readonly endpoint: true; readonly endpoint: true;
readonly rest?: RestCommand;
readonly run?: (($: CommandMenu) => Promise<any>) | string; readonly run?: (($: CommandMenu) => Promise<any>) | string;
} }
@ -91,6 +90,7 @@ interface CommandOptionsEndpoint {
// Role pings, maybe not, but it's not a big deal. // Role pings, maybe not, but it's not a big deal.
interface CommandOptionsNonEndpoint { interface CommandOptionsNonEndpoint {
readonly endpoint?: false; readonly endpoint?: false;
readonly run?: (($: CommandMenu) => Promise<any>) | string;
readonly subcommands?: {[key: string]: NamedCommand}; readonly subcommands?: {[key: string]: NamedCommand};
readonly channel?: Command; readonly channel?: Command;
readonly role?: Command; readonly role?: Command;
@ -100,9 +100,7 @@ interface CommandOptionsNonEndpoint {
readonly guild?: Command; // Only available if an ID is set to reroute to it. readonly guild?: Command; // Only available if an ID is set to reroute to it.
readonly id?: ID; readonly id?: ID;
readonly number?: Command; readonly number?: Command;
readonly any?: Command; readonly any?: Command | RestCommand;
readonly rest?: undefined; // Redeclare it here as undefined to prevent its use otherwise.
readonly run?: (($: CommandMenu) => Promise<any>) | string;
} }
type CommandOptions = CommandOptionsBase & (CommandOptionsEndpoint | CommandOptionsNonEndpoint); type CommandOptions = CommandOptionsBase & (CommandOptionsEndpoint | CommandOptionsNonEndpoint);
@ -123,9 +121,8 @@ interface ExecuteCommandMetadata {
export interface CommandInfo { export interface CommandInfo {
readonly type: "info"; readonly type: "info";
readonly command: BaseCommand; readonly command: BaseCommand;
readonly subcommandInfo: Collection<string, Command>; readonly subcommandInfo: Collection<string, BaseCommand>;
readonly keyedSubcommandInfo: Collection<string, NamedCommand>; readonly keyedSubcommandInfo: Collection<string, BaseCommand>;
readonly hasRestCommand: boolean;
readonly permission: number; readonly permission: number;
readonly nsfw: boolean; readonly nsfw: boolean;
readonly channelType: CHANNEL_TYPE; readonly channelType: CHANNEL_TYPE;
@ -181,8 +178,7 @@ export class Command extends BaseCommand {
private id: Command | null; private id: Command | null;
private idType: ID | null; private idType: ID | null;
private number: Command | null; private number: Command | null;
private any: Command | null; private any: Command | RestCommand | null;
private rest: RestCommand | null;
constructor(options?: CommandOptions) { constructor(options?: CommandOptions) {
super(options); super(options);
@ -199,7 +195,6 @@ export class Command extends BaseCommand {
this.idType = null; this.idType = null;
this.number = null; this.number = null;
this.any = null; this.any = null;
this.rest = null;
if (options && !options.endpoint) { if (options && !options.endpoint) {
if (options.channel) this.channel = options.channel; if (options.channel) this.channel = options.channel;
@ -263,8 +258,6 @@ export class Command extends BaseCommand {
} }
} }
} }
} else if (options && options.endpoint) {
if (options.rest) this.rest = options.rest;
} }
} }
@ -327,14 +320,7 @@ export class Command extends BaseCommand {
} }
// If the current command is an endpoint but there are still some arguments left, don't continue unless there's a RestCommand. // If the current command is an endpoint but there are still some arguments left, don't continue unless there's a RestCommand.
if (this.endpoint) { if (this.endpoint) return {content: "Too many arguments!"};
if (this.rest) {
args.unshift(param);
return this.rest.execute(args.join(" "), menu, metadata);
} else {
return {content: "Too many arguments!"};
}
}
// Resolve the value of the current command's argument (adding it to the resolved args), // Resolve the value of the current command's argument (adding it to the resolved args),
// then pass the thread of execution to whichever subcommand is valid (if any). // then pass the thread of execution to whichever subcommand is valid (if any).
@ -513,10 +499,14 @@ export class Command extends BaseCommand {
metadata.symbolicArgs.push("<number>"); metadata.symbolicArgs.push("<number>");
menu.args.push(Number(param)); menu.args.push(Number(param));
return this.number.execute(args, menu, metadata); return this.number.execute(args, menu, metadata);
} else if (this.any) { } else if (this.any instanceof Command) {
metadata.symbolicArgs.push("<any>"); metadata.symbolicArgs.push("<any>");
menu.args.push(param); menu.args.push(param);
return this.any.execute(args, menu, metadata); return this.any.execute(args, menu, metadata);
} else if (this.any instanceof RestCommand) {
metadata.symbolicArgs.push("<...>");
args.unshift(param);
return this.any.execute(args.join(" "), menu, metadata);
} else { } else {
// Continue adding on the rest of the arguments if there's no valid subcommand. // Continue adding on the rest of the arguments if there's no valid subcommand.
menu.args.push(param); menu.args.push(param);
@ -553,8 +543,8 @@ export class Command extends BaseCommand {
// If there are no arguments left, return the data or an error message. // If there are no arguments left, return the data or an error message.
if (param === undefined) { if (param === undefined) {
const keyedSubcommandInfo = new Collection<string, NamedCommand>(); const keyedSubcommandInfo = new Collection<string, BaseCommand>();
const subcommandInfo = new Collection<string, Command>(); const subcommandInfo = new Collection<string, BaseCommand>();
// Get all the subcommands of the current command but without aliases. // Get all the subcommands of the current command but without aliases.
for (const [tag, command] of this.subcommands.entries()) { for (const [tag, command] of this.subcommands.entries()) {
@ -572,14 +562,18 @@ export class Command extends BaseCommand {
if (this.user) subcommandInfo.set("<user>", this.user); if (this.user) subcommandInfo.set("<user>", this.user);
if (this.id) subcommandInfo.set(`<id = <${this.idType}>>`, this.id); if (this.id) subcommandInfo.set(`<id = <${this.idType}>>`, this.id);
if (this.number) subcommandInfo.set("<number>", this.number); if (this.number) subcommandInfo.set("<number>", this.number);
if (this.any) subcommandInfo.set("<any>", this.any);
// The special case for a possible rest command.
if (this.any) {
if (this.any instanceof Command) subcommandInfo.set("<any>", this.any);
else subcommandInfo.set("<...>", this.any);
}
return { return {
type: "info", type: "info",
command: this, command: this,
keyedSubcommandInfo, keyedSubcommandInfo,
subcommandInfo, subcommandInfo,
hasRestCommand: !!this.rest,
...metadata ...metadata
}; };
} }
@ -640,16 +634,16 @@ export class Command extends BaseCommand {
return invalidSubcommandGenerator(); return invalidSubcommandGenerator();
} }
} else if (param === "<any>") { } else if (param === "<any>") {
if (this.any) { if (this.any instanceof Command) {
metadata.args.push("<any>"); metadata.args.push("<any>");
return this.any.resolveInfoInternal(args, metadata); return this.any.resolveInfoInternal(args, metadata);
} else { } else {
return invalidSubcommandGenerator(); return invalidSubcommandGenerator();
} }
} else if (param === "<...>") { } else if (param === "<...>") {
if (this.rest) { if (this.any instanceof RestCommand) {
metadata.args.push("<...>"); metadata.args.push("<...>");
return this.rest.resolveInfoFinale(metadata); return this.any.resolveInfoFinale(metadata);
} else { } else {
return invalidSubcommandGenerator(); return invalidSubcommandGenerator();
} }
@ -755,9 +749,8 @@ export class RestCommand extends BaseCommand {
return { return {
type: "info", type: "info",
command: this, command: this,
keyedSubcommandInfo: new Collection<string, NamedCommand>(), keyedSubcommandInfo: new Collection<string, BaseCommand>(),
subcommandInfo: new Collection<string, Command>(), subcommandInfo: new Collection<string, BaseCommand>(),
hasRestCommand: false,
...metadata ...metadata
}; };
} }