Fix and improve broken and bad code.

Improve command handler, fixed message logging, fixes potential prefix problem, other small changes
This commit is contained in:
Isaac 2021-04-01 19:33:53 +01:00
parent 3def7e290d
commit 2e9217f30d
10 changed files with 78 additions and 76 deletions

View File

@ -17,7 +17,8 @@ module.exports = class NewCommand extends Command {
{ {
name: i18n('commands.new.args.topic.name'), name: i18n('commands.new.args.topic.name'),
description: i18n('commands.new.args.topic.description'), description: i18n('commands.new.args.topic.description'),
required: false, example: i18n('commands.new.args.topic.example'),
required: true,
} }
] ]
}); });

View File

@ -199,7 +199,7 @@ module.exports = async (log) => {
type: DataTypes.BOOLEAN, type: DataTypes.BOOLEAN,
defaultValue: false, defaultValue: false,
}, },
updates: { data: {
type: DataTypes.JSON type: DataTypes.JSON
}, },
}, { }, {

View File

@ -4,29 +4,30 @@ module.exports = {
let settings = await message.guild?.settings; let settings = await message.guild?.settings;
// message collection for ticket archiving // message collection for t_row archiving
if (settings?.log_messages) { if (settings?.log_messages) {
if (message.system) return; if (message.system) return;
let ticket = await client.db.models.Ticket.findOne({ let t_row = await client.db.models.Ticket.findOne({
where: { where: {
id: message.channel.id id: message.channel.id
} }
}); });
if (ticket) { if (t_row) {
let embeds = [];
for (let embed in message.embeds) embeds.push({ ...message.embeds[embed] });
await client.db.models.Message.create({ await client.db.models.Message.create({
id: message.id, id: message.id,
ticket: ticket.id, ticket: t_row.id,
author: message.author.id, author: message.author.id,
updates: [{ data: {
content: message.content, content: message.content,
time: message.createdTimestamp, // time: message.createdTimestamp,
embeds: message.embeds.map(embed => { embeds,
return { ...message.embeds[embed] }; attachments: [...message.attachments.values()]
}), }
attachments: [ ...message.attachments.values() ]
}]
}); });
} }
} }

View File

@ -9,7 +9,7 @@ module.exports = {
let msg = await client.db.models.Message.findOne({ let msg = await client.db.models.Message.findOne({
where: { where: {
id: message.channel.id id: message.id
} }
}); });

View File

@ -1,5 +1,5 @@
module.exports = { module.exports = {
event: 'msgUpdate', event: 'messageUpdate',
execute: async (client, oldm, newm) => { execute: async (client, oldm, newm) => {
if (newm.partial) { if (newm.partial) {
@ -12,34 +12,31 @@ module.exports = {
let settings = await newm.guild?.settings; let settings = await newm.guild?.settings;
if (settings?.messages) { if (settings?.log_messages) {
if (newm.system) return; if (newm.system) return;
let msg = await client.db.models.msg.findOne({ let m_row = await client.db.models.Message.findOne({
where: { where: {
id: newm.channel.id id: newm.id
} }
}); });
if (msg) { if (m_row) {
let embeds = msg.embeds.map(embed => { let embeds = [];
return { ...msg.embeds[embed] }; for (let embed in newm.embeds) embeds.push({ ...newm.embeds[embed] });
});
if (msg.editedTimestamp) { // message has been edited m_row.data = {
msg.updates.unshift({ content: newm.content,
content: msg.content, // time: newm.editedTimestamp,
time: msg.editedTimestamp, embeds: newm.embeds.map(embed => {
embeds, return { ...newm.embeds[embed] };
attachments: [ ...msg.attachments.values() ] }),
}); attachments: [...newm.attachments.values()]
msg.edited = true; };
}
else { // probably just a link embed loading
msg.updates[0] = Object.assign(msg.updates[0], embeds);
}
await msg.save(); // save changes to msg row if (newm.editedTimestamp) m_row.edited = true;
await m_row.save(); // save changes
} }
} }
} }

View File

@ -3,12 +3,13 @@
"version": "[Discord Tickets](%s) v%s by [eartharoid](%s)" "version": "[Discord Tickets](%s) v%s by [eartharoid](%s)"
}, },
"cmd_usage": { "cmd_usage": {
"title": "`%s` command usage", "args": {
"description": "**Usage:** %s" "description": "**Description:**",
"example": "**Example:**"
}, },
"cmd_usage_named_args": { "description": "**Usage:**\n`%s`\n\n**Example:**\n`%s`\n\nRequired arguments are prefixed with `❗`.",
"title": "`%s` command usage", "named_args_description": "This command uses named arguments.\n\n",
"description": "This command uses named arguments:\n`%s argName: value anotherArg: \"A string value\";`\n\n**Required arguments are prefixed with `❗`.**" "title": "`%s` command usage"
}, },
"commands": { "commands": {
"new": { "new": {
@ -23,7 +24,8 @@
}, },
"topic": { "topic": {
"name": "topic", "name": "topic",
"description": "The topic of the ticket" "description": "The topic of the ticket",
"example": "Problem with billing"
} }
}, },
"description": "Create a new ticket", "description": "Create a new ticket",

View File

@ -5,7 +5,7 @@ module.exports = new Logger({
name: 'Discord Tickets by eartharoid', name: 'Discord Tickets by eartharoid',
debug: config.debug, debug: config.debug,
logToFile: config.logs.enabled, logToFile: config.logs.enabled,
splitFile: true, splitFile: config.logs.split,
directory: path('./logs/'), directory: path('./logs/'),
keepFor: config.logs.keep_for, keepFor: config.logs.keep_for,
timestamp: 'YYYY-MM-DD HH:mm:ss', timestamp: 'YYYY-MM-DD HH:mm:ss',

View File

@ -71,11 +71,16 @@ module.exports = class Command {
*/ */
this.args = data.args; this.args = data.args;
for (let arg in this.args) {
if (!this.args[arg].example)
throw new Error(`The "${this.name}" command's "${this.args[arg].name}" argument does not have an example!`);
}
/** /**
* True if command is internal, false if it is from a plugin * True if command is internal, false if it is from a plugin
* @type {boolean} * @type {boolean}
*/ */
this.internal = data.internal; this.internal = data.internal === true ? true : false;
if (!this.internal) { if (!this.internal) {
/** /**
@ -98,7 +103,7 @@ module.exports = class Command {
* The code to be executed when a command is invoked * The code to be executed when a command is invoked
* @abstract * @abstract
* @param {Message} message - The message that invoked this command * @param {Message} message - The message that invoked this command
* @param {(object|string)?} args - Named command arguments, or the message content with the prefix and command removed * @param {(object|string)} [args] - Named command arguments, or the message content with the prefix and command removed
*/ */
async execute(message, args) { } // eslint-disable-line no-unused-vars async execute(message, args) { } // eslint-disable-line no-unused-vars

View File

@ -72,31 +72,35 @@ module.exports = class CommandManager {
const prefix = settings.command_prefix; const prefix = settings.command_prefix;
const i18n = this.client.i18n.get(settings.locale); const i18n = this.client.i18n.get(settings.locale);
let cmd_name = message.content.match(new RegExp(`^${prefix}(\\S+)`, 'mi')); let cmd_name = message.content.match(new RegExp(`^${prefix.replace(/(?=\W)/g, '\\')}(\\S+)`, 'mi'));
if (!cmd_name) return; if (!cmd_name) return;
let raw_args = message.content.replace(cmd_name[0], '').trim(); let raw_args = message.content.replace(cmd_name[0], '').trim(); // remove the prefix and command
cmd_name = cmd_name[1]; cmd_name = cmd_name[1]; // set cmd_name to the actual string
const cmd = this.commands.find(cmd => cmd.aliases.includes(cmd_name)); const cmd = this.commands.find(cmd => cmd.aliases.includes(cmd_name));
if (!cmd); if (!cmd) return;
let args = raw_args; let args = raw_args;
const addArgs = (embed, arg) => {
let required = arg.required ? '`❗` ' : '';
embed.addField(required + arg.name, `» ${i18n('cmd_usage.args.description')} ${arg.description}\n» ${i18n('cmd_usage.args.example')} \`${arg.example}\``);
};
if (cmd.process_args) { if (cmd.process_args) {
args = {}; args = {};
let data = [ ...raw_args.matchAll(/(\w+)\??\s?:\s?(["`'](.*)["`'];|[\w<>@!#]+)/gmi) ]; let data = [...raw_args.matchAll(/(?<key>\w+)\??\s?:\s?(?<value>([^;]|;{2})*);/gmi)];
data.forEach(arg => args[arg[1]] = arg[3] || arg[2]); data.forEach(arg => args[arg.groups.key] = arg.groups.value.replace(/;{2}/gm, ';'));
for (let arg of cmd.args) { for (let arg of cmd.args) {
if (!args[arg]) { if (arg.required && !args[arg]) {
let usage = `${prefix + cmd_name} ${cmd.args.map(arg => arg.required ? `<${arg.name};>` : `[${arg.name};]`).join(' ')}`;
let example = `${prefix + cmd_name} ${cmd.args.map(arg => `${arg.name}: ${arg.example};`).join(' ')}`;
let embed = new MessageEmbed() let embed = new MessageEmbed()
.setColor(settings.error_colour) .setColor(settings.error_colour)
.setTitle(i18n('cmd_usage_named_args.title', cmd_name)) .setTitle(i18n('cmd_usage.title', cmd_name))
.setDescription(i18n('cmd_usage_named_args.description', settings.command_prefix + cmd_name)); .setDescription(i18n('cmd_usage.named_args_description') + i18n('cmd_usage.description', usage, example));
cmd.args.forEach(a => { cmd.args.forEach(a => addArgs(embed, a));
let required = a.required ? '`❗` ' : '';
embed.addField(required + a.name, a.description);
});
return message.channel.send(embed); return message.channel.send(embed);
} }
} }
@ -104,15 +108,13 @@ module.exports = class CommandManager {
const args_num = raw_args.split(' ').filter(arg => arg.length !== 0).length; const args_num = raw_args.split(' ').filter(arg => arg.length !== 0).length;
const required_args = cmd.args.reduce((acc, arg) => arg.required ? acc + 1 : acc, 0); const required_args = cmd.args.reduce((acc, arg) => arg.required ? acc + 1 : acc, 0);
if (args_num < required_args) { if (args_num < required_args) {
let usage = cmd.args.map(arg => arg.required ? `<${arg.name}>` : `[${arg.name}]`).join(' '); let usage = `${prefix + cmd_name} ${cmd.args.map(arg => arg.required ? `<${arg.name}>` : `[${arg.name}]`).join(' ')}`;
let example = `${prefix + cmd_name} ${cmd.args.map(arg => `${arg.example}`).join(' ')}`;
let embed = new MessageEmbed() let embed = new MessageEmbed()
.setColor(settings.error_colour) .setColor(settings.error_colour)
.setTitle(i18n('cmd_usage.title', cmd_name)) .setTitle(i18n('cmd_usage.title', cmd_name))
.setDescription(i18n('cmd_usage.description', `\`${settings.command_prefix + cmd_name} ${usage}\``)); .setDescription(i18n('cmd_usage.description', usage, example));
cmd.args.forEach(a => { cmd.args.forEach(a => addArgs(embed, a));
let required = a.required ? '`❗` ' : '';
embed.addField(required + a.name, a.description);
});
return message.channel.send(embed); return message.channel.send(embed);
} }
} }
@ -152,7 +154,7 @@ module.exports = class CommandManager {
try { try {
this.client.log.commands(`Executing "${cmd.name}" command (invoked by ${message.author.tag})`); this.client.log.commands(`Executing "${cmd.name}" command (invoked by ${message.author.tag})`);
await cmd.execute(message, args, raw_args); // execute the command await cmd.execute(message, args); // execute the command
} catch (e) { } catch (e) {
this.client.log.warn(`An error occurred whilst executing the ${cmd.name} command`); this.client.log.warn(`An error occurred whilst executing the ${cmd.name} command`);
this.client.log.error(e); this.client.log.error(e);

View File

@ -7,17 +7,11 @@
* |____/ |_| |___/ \___| \___/ |_| \__,_| |_| |_| \___| |_|\_\ \___| \__| |___/ * |____/ |_| |___/ \___| \___/ |_| \__,_| |_| |_| \___| |_|\_\ \___| \__| |___/
* *
* --------------------- * ---------------------
* Quick Start
* ---------------------
*
* > For detailed instructions, visit the documentation: https://discordtickets.app
*
* ---------------------
* Support * Support
* --------------------- * ---------------------
* *
* > Discord support server: https://go.eartharoid.me/discord
* > Documentation: https://discordtickets.app * > Documentation: https://discordtickets.app
* > Discord support server: https://go.eartharoid.me/discord
* *
* ############################################################################################### * ###############################################################################################
*/ */
@ -29,13 +23,13 @@ module.exports = {
command_prefix: 'tickets/', command_prefix: 'tickets/',
log_messages: true, // transcripts/archives will be empty if false log_messages: true, // transcripts/archives will be empty if false
name_format: 'ticket-{number}', name_format: 'ticket-{number}',
prefix: '-', ticket_welcome: 'Hello {name}, thank you for creating a ticket. A member of staff will soon be available to assist you.\n\n__All messages in this channel are stored for future reference.__',
ticket_welcome: 'Hello {{name}}, thank you for creating a ticket. A member of staff will soon be available to assist you.\n\n__All messages in this channel are stored for future reference.__',
}, },
locale: 'en-GB', // used for globals (such as commands) and the default guild locale locale: 'en-GB', // used for globals (such as commands) and the default guild locale
logs: { logs: {
enabled: true, enabled: true,
keep_for: 30 keep_for: 30,
split: true,
}, },
max_listeners: 10, max_listeners: 10,
plugins: [], plugins: [],