mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2024-11-09 14:23:08 +02:00
Remove slash commands
Not fully tested but working so far
This commit is contained in:
parent
82c3175f37
commit
245bba0c10
@ -1,5 +1,4 @@
|
|||||||
const { MessageEmbed } = require('discord.js');
|
const { MessageEmbed } = require('discord.js');
|
||||||
const { OptionTypes } = require('../modules/commands/helpers');
|
|
||||||
const Command = require('../modules/commands/command');
|
const Command = require('../modules/commands/command');
|
||||||
|
|
||||||
module.exports = class NewCommand extends Command {
|
module.exports = class NewCommand extends Command {
|
||||||
@ -9,37 +8,41 @@ module.exports = class NewCommand extends Command {
|
|||||||
internal: true,
|
internal: true,
|
||||||
name: i18n('commands.new.name'),
|
name: i18n('commands.new.name'),
|
||||||
description: i18n('commands.new.description'),
|
description: i18n('commands.new.description'),
|
||||||
// slash: false,
|
aliases: [
|
||||||
options: [
|
i18n('commands.new.aliases.open'),
|
||||||
|
i18n('commands.new.aliases.create'),
|
||||||
|
],
|
||||||
|
args: [
|
||||||
{
|
{
|
||||||
name: i18n('commands.new.options.category.name'),
|
name: i18n('commands.new.args.category.name'),
|
||||||
type: OptionTypes.STRING,
|
description: i18n('commands.new.args.topic.description'),
|
||||||
description: i18n('commands.new.options.topic.description'),
|
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: i18n('commands.new.options.topic.name'),
|
name: i18n('commands.new.args.topic.name'),
|
||||||
type: OptionTypes.STRING,
|
description: i18n('commands.new.args.topic.description'),
|
||||||
description: i18n('commands.new.options.topic.description'),
|
|
||||||
required: false,
|
required: false,
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute({ guild, member, channel, args }, interaction) {
|
async execute(message, args, raw_args) {
|
||||||
|
|
||||||
let settings = await guild.settings;
|
let settings = await message.guild.settings;
|
||||||
const i18n = this.client.i18n.get(settings.locale);
|
const i18n = this.client.i18n.get(settings.locale);
|
||||||
|
|
||||||
await channel.send(
|
await message.channel.send(
|
||||||
new MessageEmbed()
|
new MessageEmbed()
|
||||||
.setColor(settings.colour)
|
.setColor(settings.colour)
|
||||||
.setTitle(i18n('bot.version', require('../../package.json').version))
|
.setTitle(i18n('bot.version', require('../../package.json').version))
|
||||||
.setDescription(args.topic)
|
.setDescription(args.topic)
|
||||||
);
|
);
|
||||||
|
|
||||||
// this.client.tickets.create(guild.id, member.id, args.category, args.topic);
|
// console.log(this.aliases)
|
||||||
this.client.tickets.create(guild.id, member.id, '825861413687787560');
|
// console.log(args.category)
|
||||||
|
// console.log(args.topic)
|
||||||
|
|
||||||
|
// this.client.tickets.create(message.guild.id, message.member.id, '825861413687787560', args.topic);
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -7,16 +7,15 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
const i18n = client.i18n.get(client.config.locale);
|
const i18n = client.i18n.get(client.config.locale);
|
||||||
super(client, {
|
super(client, {
|
||||||
internal: true,
|
internal: true,
|
||||||
slash: false,
|
|
||||||
name: i18n('commands.settings.name'),
|
name: i18n('commands.settings.name'),
|
||||||
description: i18n('commands.settings.description'),
|
description: i18n('commands.settings.description'),
|
||||||
permissions: ['MANAGE_GUILD']
|
permissions: ['MANAGE_GUILD']
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute({ guild, channel, member }, message) {
|
async execute(message) {
|
||||||
|
|
||||||
let settings = await guild.settings;
|
let settings = await message.guild.settings;
|
||||||
const i18n = this.client.i18n.get(settings.locale);
|
const i18n = this.client.i18n.get(settings.locale);
|
||||||
|
|
||||||
let attachments = [ ...message.attachments.values() ];
|
let attachments = [ ...message.attachments.values() ];
|
||||||
@ -24,9 +23,10 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
if (attachments.length >= 1) {
|
if (attachments.length >= 1) {
|
||||||
|
|
||||||
// load settings from json
|
// load settings from json
|
||||||
this.client.log.info(`Downloading settings for "${guild.name}"`);
|
this.client.log.info(`Downloading settings for "${message.guild.name}"`);
|
||||||
let data = await (await fetch(attachments[0].url)).json();
|
let data = await (await fetch(attachments[0].url)).json();
|
||||||
settings.colour = data.colour;
|
settings.colour = data.colour;
|
||||||
|
settings.command_prefix = data.command_prefix;
|
||||||
settings.error_colour = data.error_colour;
|
settings.error_colour = data.error_colour;
|
||||||
settings.locale = data.locale;
|
settings.locale = data.locale;
|
||||||
settings.log_messages = data.log_messages;
|
settings.log_messages = data.log_messages;
|
||||||
@ -51,7 +51,7 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
let cat_channel = await this.client.channels.fetch(c.id);
|
let cat_channel = await this.client.channels.fetch(c.id);
|
||||||
|
|
||||||
if (cat_channel.name !== c.name)
|
if (cat_channel.name !== c.name)
|
||||||
await cat_channel.setName(c.name, `Tickets category updated by ${member.user.tag}`);
|
await cat_channel.setName(c.name, `Tickets category updated by ${message.member.user.tag}`);
|
||||||
|
|
||||||
for (let r of c.roles) {
|
for (let r of c.roles) {
|
||||||
await cat_channel.updateOverwrite(r, {
|
await cat_channel.updateOverwrite(r, {
|
||||||
@ -59,21 +59,21 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
READ_MESSAGE_HISTORY: true,
|
READ_MESSAGE_HISTORY: true,
|
||||||
SEND_MESSAGES: true,
|
SEND_MESSAGES: true,
|
||||||
ATTACH_FILES: true
|
ATTACH_FILES: true
|
||||||
}, `Tickets category updated by ${member.user.tag}`);
|
}, `Tickets category updated by ${message.member.user.tag}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// create a new category
|
// create a new category
|
||||||
const allowed_permissions = ['VIEW_CHANNEL', 'READ_MESSAGE_HISTORY', 'SEND_MESSAGES', 'EMBED_LINKS', 'ATTACH_FILES'];
|
const allowed_permissions = ['VIEW_CHANNEL', 'READ_MESSAGE_HISTORY', 'SEND_MESSAGES', 'EMBED_LINKS', 'ATTACH_FILES'];
|
||||||
let cat_channel = await guild.channels.create(c.name, {
|
let cat_channel = await message.guild.channels.create(c.name, {
|
||||||
type: 'category',
|
type: 'category',
|
||||||
reason: `Tickets category created by ${member.user.tag}`,
|
reason: `Tickets category created by ${message.member.user.tag}`,
|
||||||
position: 0,
|
position: 0,
|
||||||
permissionOverwrites: [
|
permissionOverwrites: [
|
||||||
...[
|
...[
|
||||||
{
|
{
|
||||||
id: guild.roles.everyone,
|
id: message.guild.roles.everyone,
|
||||||
deny: ['VIEW_CHANNEL']
|
deny: ['VIEW_CHANNEL']
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -94,14 +94,14 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
max_per_member: c.max_per_member,
|
max_per_member: c.max_per_member,
|
||||||
name: c.name,
|
name: c.name,
|
||||||
name_format: c.name_format,
|
name_format: c.name_format,
|
||||||
guild: guild.id,
|
guild: message.guild.id,
|
||||||
roles: c.roles,
|
roles: c.roles,
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.client.log.success(`Updated guild settings for "${guild.name}"`);
|
this.client.log.success(`Updated guild settings for "${message.guild.name}"`);
|
||||||
channel.send(i18n('commands.settings.response.updated'));
|
message.channel.send(i18n('commands.settings.response.updated'));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
@ -109,6 +109,7 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
let data = {
|
let data = {
|
||||||
categories: [],
|
categories: [],
|
||||||
colour: settings.colour,
|
colour: settings.colour,
|
||||||
|
command_prefix: settings.command_prefix,
|
||||||
error_colour: settings.error_colour,
|
error_colour: settings.error_colour,
|
||||||
locale: settings.locale,
|
locale: settings.locale,
|
||||||
log_messages: settings.log_messages,
|
log_messages: settings.log_messages,
|
||||||
@ -117,7 +118,7 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
|
|
||||||
let categories = await this.client.db.models.Category.findAll({
|
let categories = await this.client.db.models.Category.findAll({
|
||||||
where: {
|
where: {
|
||||||
guild: guild.id
|
guild: message.guild.id
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -133,10 +134,10 @@ module.exports = class SettingsCommand extends Command {
|
|||||||
|
|
||||||
let attachment = new MessageAttachment(
|
let attachment = new MessageAttachment(
|
||||||
Buffer.from(JSON.stringify(data, null, 2)),
|
Buffer.from(JSON.stringify(data, null, 2)),
|
||||||
`Settings for ${guild.name}.json`
|
`Settings for ${message.guild.name}.json`
|
||||||
);
|
);
|
||||||
|
|
||||||
channel.send({
|
message.channel.send({
|
||||||
files: [attachment]
|
files: [attachment]
|
||||||
});
|
});
|
||||||
|
|
@ -72,6 +72,10 @@ module.exports = async (log) => {
|
|||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
defaultValue: config.locale
|
defaultValue: config.locale
|
||||||
},
|
},
|
||||||
|
command_prefix: {
|
||||||
|
type: DataTypes.STRING,
|
||||||
|
defaultValue: config.defaults.command_prefix
|
||||||
|
},
|
||||||
colour: {
|
colour: {
|
||||||
type: DataTypes.STRING,
|
type: DataTypes.STRING,
|
||||||
defaultValue: config.defaults.colour
|
defaultValue: config.defaults.colour
|
||||||
|
@ -1,21 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
event: 'INTERACTION_CREATE',
|
|
||||||
raw: true,
|
|
||||||
execute: async (client, interaction) => {
|
|
||||||
|
|
||||||
switch (interaction.type) {
|
|
||||||
case 1:
|
|
||||||
client.log.info('Received interaction ping, responding with pong');
|
|
||||||
await client.api.interactions(interaction.id, interaction.token).callback.post({
|
|
||||||
data: {
|
|
||||||
type: 1, // PONG
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
client.commands.handle(interaction, true);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
};
|
|
@ -31,8 +31,6 @@ module.exports = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// non-slash commands
|
client.commands.handle(message);
|
||||||
if (message.content.match(/^tickets\/(\S+)/mi))
|
|
||||||
client.commands.handle(message, false);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
@ -4,9 +4,11 @@
|
|||||||
},
|
},
|
||||||
"commands": {
|
"commands": {
|
||||||
"new": {
|
"new": {
|
||||||
"name": "new",
|
"aliases": {
|
||||||
"description": "Create a new support ticket",
|
"create": "create",
|
||||||
"options": {
|
"open": "open"
|
||||||
|
},
|
||||||
|
"args": {
|
||||||
"category": {
|
"category": {
|
||||||
"name": "category",
|
"name": "category",
|
||||||
"description": "The category you would like to create a new ticket for"
|
"description": "The category you would like to create a new ticket for"
|
||||||
@ -15,11 +17,13 @@
|
|||||||
"name": "topic",
|
"name": "topic",
|
||||||
"description": "The topic of the ticket"
|
"description": "The topic of the ticket"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"description": "Create a new support ticket",
|
||||||
|
"name": "new"
|
||||||
},
|
},
|
||||||
"settings": {
|
"settings": {
|
||||||
"name": "settings",
|
|
||||||
"description": "Configure Discord Tickets",
|
"description": "Configure Discord Tickets",
|
||||||
|
"name": "settings",
|
||||||
"response": {
|
"response": {
|
||||||
"updated": "✅ Settings have been updated."
|
"updated": "✅ Settings have been updated."
|
||||||
}
|
}
|
||||||
|
@ -1,39 +1,7 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
|
||||||
const {
|
|
||||||
Client,
|
|
||||||
GuildMember,
|
|
||||||
Guild,
|
|
||||||
Channel,
|
|
||||||
Message
|
|
||||||
} = require('discord.js');
|
|
||||||
|
|
||||||
const {
|
|
||||||
createMessage,
|
|
||||||
flags
|
|
||||||
} = require('../../utils/discord');
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A command
|
* A command
|
||||||
*/
|
*/
|
||||||
module.exports = class Command {
|
module.exports = class Command {
|
||||||
/**
|
|
||||||
* A command option choice
|
|
||||||
* @typedef CommandOptionChoice
|
|
||||||
* @property {string} name - Choice name (1-100)
|
|
||||||
* @property {(string|number)} value - choice value
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A command option
|
|
||||||
* @typedef CommandOption
|
|
||||||
* @property {number} type - [ApplicationCommandOptionType](https://discord.com/developers/docs/interactions/slash-commands#applicationcommandoptiontype)
|
|
||||||
* @property {string} name - Option name (1-32)
|
|
||||||
* @property {string} description - Option description (1-100)
|
|
||||||
* @property {boolean} [required] - Required?
|
|
||||||
* @property {CommandOptionChoice[]} [choices] - Array of choices
|
|
||||||
* @property {CommandOption[]} [options] - Array of options if this option is a subcommand/subcommand group
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new Command
|
* Create a new Command
|
||||||
* @param {Client} client - The Discord Client
|
* @param {Client} client - The Discord Client
|
||||||
@ -43,8 +11,7 @@ module.exports = class Command {
|
|||||||
* @param {boolean} [data.slash] - Register as a slash command? **Defaults to `true`**
|
* @param {boolean} [data.slash] - Register as a slash command? **Defaults to `true`**
|
||||||
* @param {boolean} [data.staff_only] - Only allow staff to use this command?
|
* @param {boolean} [data.staff_only] - Only allow staff to use this command?
|
||||||
* @param {string[]} [data.permissions] - Array of permissions needed for a user to use this command
|
* @param {string[]} [data.permissions] - Array of permissions needed for a user to use this command
|
||||||
* @param {boolean} [data.global] - Create a global command?
|
* @param {CommandArgument[]} [data.args] - The command's arguments
|
||||||
* @param {CommandOption[]} [data.options] - The command options (parameters), max of 10
|
|
||||||
*/
|
*/
|
||||||
constructor(client, data) {
|
constructor(client, data) {
|
||||||
|
|
||||||
@ -55,7 +22,7 @@ module.exports = class Command {
|
|||||||
this.manager = this.client.commands;
|
this.manager = this.client.commands;
|
||||||
|
|
||||||
if (typeof data !== 'object') {
|
if (typeof data !== 'object') {
|
||||||
throw new TypeError(`Expected type of data to be an object, got ${typeof data}`);
|
throw new TypeError(`Expected type of command "data" to be an object, got "${typeof data}"`);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -64,18 +31,20 @@ module.exports = class Command {
|
|||||||
*/
|
*/
|
||||||
this.name = data.name;
|
this.name = data.name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The command's aliases
|
||||||
|
* @type {string[]}
|
||||||
|
*/
|
||||||
|
this.aliases = data.aliases || [];
|
||||||
|
|
||||||
|
if (!this.aliases.includes(this.name)) this.aliases.unshift(this.name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command description
|
* The command description
|
||||||
* @type {string}
|
* @type {string}
|
||||||
*/
|
*/
|
||||||
this.description = data.description;
|
this.description = data.description;
|
||||||
|
|
||||||
/**
|
|
||||||
* Register as a slash command?
|
|
||||||
* @type {boolean}
|
|
||||||
*/
|
|
||||||
this.slash = data.slash === false ? false : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Only allow staff to use this command?
|
* Only allow staff to use this command?
|
||||||
* @type {boolean}
|
* @type {boolean}
|
||||||
@ -88,18 +57,11 @@ module.exports = class Command {
|
|||||||
*/
|
*/
|
||||||
this.permissions = data.permissions;
|
this.permissions = data.permissions;
|
||||||
|
|
||||||
/**
|
|
||||||
* Is this a global command?
|
|
||||||
* @type {boolean}
|
|
||||||
* @default true
|
|
||||||
*/
|
|
||||||
this.global = data.global === false ? false : true;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The command options
|
* The command options
|
||||||
* @type {CommandOption[]}
|
* @type {CommandArgument[]}
|
||||||
*/
|
*/
|
||||||
this.options = data.options;
|
this.args = data.args;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* True if command is internal, false if it is from a plugin
|
* True if command is internal, false if it is from a plugin
|
||||||
@ -115,98 +77,21 @@ module.exports = class Command {
|
|||||||
this.plugin = this.client.plugins.plugins.find(p => p.commands?.includes(this.name));
|
this.plugin = this.client.plugins.plugins.find(p => p.commands?.includes(this.name));
|
||||||
}
|
}
|
||||||
|
|
||||||
this.manager.check(data); // validate
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
this.manager.register(this); // register the command
|
this.manager.register(this); // register the command
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return this.client.log.error(e);
|
return this.client.log.error(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.slash && this.global)
|
|
||||||
this.client.api.applications(this.client.user.id).commands.post({ data }); // post command to Discord
|
|
||||||
|
|
||||||
let internal = this.internal ? 'internal ' : '';
|
|
||||||
this.client.log.commands(`Loaded ${internal}"${this.name}" command`);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* [ApplicationCommandInteractionDataOption](https://discord.com/developers/docs/interactions/slash-commands#interaction-applicationcommandinteractiondataoption)
|
|
||||||
* @typedef {Object} ApplicationCommandInteractionDataOption
|
|
||||||
* @property {string} name - Name of the parameter
|
|
||||||
* @property {*} value - The value
|
|
||||||
* @property {(undefined|ApplicationCommandInteractionDataOption[])} options - Present if the option is a subcommand/subcommand group
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* [Interaction](https://discord.com/developers/docs/interactions/slash-commands#interaction) object
|
|
||||||
* @typedef {Object} Interaction
|
|
||||||
* @property {string} interaction.id - ID of the interaction
|
|
||||||
* @property {number} interaction.type - Type of interaction
|
|
||||||
* @property {ApplicationCommandInteractionData} interaction.data - Interaction data
|
|
||||||
* @property {Object} interaction.guild- The guild object
|
|
||||||
* @property {Object} interaction.channel- The channel object
|
|
||||||
* @property {Object} interaction.member - The member object
|
|
||||||
* @property {string} interaction.token - The token used to respond to the interaction
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The code to be executed when a command is invoked
|
* The code to be executed when a command is invoked
|
||||||
* @abstract
|
* @abstract
|
||||||
* @param {Object} data - Object containing data about the command invocation
|
* @param {Message} message - The message that invoked this command
|
||||||
* @param {Object} data.args - Command arguments
|
* @param {object?} args - Command arguments
|
||||||
* @param {Channel} data.channel- The channel object
|
|
||||||
* @param {Guild} data.guild- The guild object
|
|
||||||
* @param {GuildMember} data.member - The member object
|
|
||||||
* @param {(Interaction|Message)} interaction_or_message - Interaction object
|
|
||||||
*/
|
*/
|
||||||
async execute(data, interaction_or_message) { }
|
async execute(message, args) { }
|
||||||
|
|
||||||
/**
|
|
||||||
* Defer the response to respond later
|
|
||||||
* @param {Interaction} interaction - Interaction object
|
|
||||||
* @param {boolean} secret - Ephemeral?
|
|
||||||
*/
|
|
||||||
async acknowledge(interaction, secret) {
|
|
||||||
this.client.api.interactions(interaction.id, interaction.token).callback.post({
|
|
||||||
data: {
|
|
||||||
type: 5,
|
|
||||||
// data: {
|
|
||||||
// flags: flags(secret)
|
|
||||||
// },
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Send an interaction response
|
|
||||||
* @param {Interaction} interaction - Interaction object
|
|
||||||
* @param {*} content - Message content
|
|
||||||
* @param {boolean} secret - Ephemeral message? **NOTE: EMBEDS AND ATTACHMENTS DO NOT RENDER IF TRUE**
|
|
||||||
*/
|
|
||||||
async respond(interaction, content, secret) {
|
|
||||||
let application = await this.client.fetchApplication();
|
|
||||||
const send = this.client.api.webhooks(application.id, interaction.token).messages['@original'].patch;
|
|
||||||
if (typeof content === 'object')
|
|
||||||
await send({
|
|
||||||
data: {
|
|
||||||
type: 4,
|
|
||||||
data: {
|
|
||||||
flags: flags(secret),
|
|
||||||
...await createMessage(this.client, interaction.channel_id, content)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
else if (typeof content === 'string')
|
|
||||||
await send({
|
|
||||||
data: {
|
|
||||||
type: 4,
|
|
||||||
data: {
|
|
||||||
flags: flags(secret),
|
|
||||||
content
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
};
|
@ -1,17 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
OptionTypes: {
|
|
||||||
SUB_COMMAND: 1,
|
|
||||||
SUB_COMMAND_GROUP: 2,
|
|
||||||
STRING: 3,
|
|
||||||
INTEGER: 4,
|
|
||||||
BOOLEAN: 5,
|
|
||||||
USER: 6,
|
|
||||||
CHANNEL: 7,
|
|
||||||
ROLE: 8,
|
|
||||||
},
|
|
||||||
ResponseTypes: {
|
|
||||||
Pong: 1,
|
|
||||||
ChannelMessageWithSource: 4,
|
|
||||||
DeferredChannelMessageWithSource: 5,
|
|
||||||
}
|
|
||||||
};
|
|
@ -56,155 +56,61 @@ module.exports = class CommandManager {
|
|||||||
throw new Error(`A non-internal command with the name "${cmd.name}" already exists`);
|
throw new Error(`A non-internal command with the name "${cmd.name}" already exists`);
|
||||||
|
|
||||||
this.commands.set(cmd.name, cmd);
|
this.commands.set(cmd.name, cmd);
|
||||||
}
|
|
||||||
|
|
||||||
/** Check the command data */
|
let internal = cmd.internal ? 'internal ' : '';
|
||||||
check(data) {
|
this.client.log.commands(`Loaded ${internal}"${cmd.name}" command`);
|
||||||
|
|
||||||
if (typeof data.name !== 'string')
|
|
||||||
throw new TypeError(`Expected type of command name to be a string, got ${typeof data.name}`);
|
|
||||||
|
|
||||||
if (data.name.length < 3 || data.name.length > 32)
|
|
||||||
throw new TypeError('Length of command name must be 3-32');
|
|
||||||
|
|
||||||
if (typeof data.description !== 'string')
|
|
||||||
throw new TypeError(`Expected type of command description to be a string, got ${typeof data.description}`);
|
|
||||||
|
|
||||||
if (data.description.length < 1 || data.description.length > 100)
|
|
||||||
throw new TypeError('Length of description must be 3-32');
|
|
||||||
|
|
||||||
if (typeof data.options !== 'undefined' && !(data.options instanceof Array))
|
|
||||||
throw new TypeError(`Expected type of command options to be undefined or an array, got ${typeof data.options}`);
|
|
||||||
|
|
||||||
if (data.options)
|
|
||||||
this.checkOptions(data.options);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check the command data's options */
|
|
||||||
checkOptions(options) {
|
|
||||||
let num = 0;
|
|
||||||
options.forEach(o => {
|
|
||||||
if (typeof o.type !== 'number')
|
|
||||||
throw new TypeError(`Expected type of option ${num} type to be a number, got ${typeof o.type}`);
|
|
||||||
|
|
||||||
if (typeof o.name !== 'string')
|
|
||||||
throw new TypeError(`Expected type of option ${num} name to be a string, got ${typeof o.name}`);
|
|
||||||
|
|
||||||
if (o.name.length < 3 || o.name.length > 32)
|
|
||||||
throw new TypeError(`Length of option ${num} name must be 3-32`);
|
|
||||||
|
|
||||||
if (typeof o.description !== 'string')
|
|
||||||
throw new TypeError(`Expected type of option ${num} description to be a string, got ${typeof o.description}`);
|
|
||||||
|
|
||||||
if (o.description.length < 1 || o.description.length > 100)
|
|
||||||
throw new TypeError(`Length of option ${num} description must be 1-100`);
|
|
||||||
|
|
||||||
if (typeof o.required !== 'undefined' && typeof o.required !== 'boolean')
|
|
||||||
throw new TypeError(`Expected type of option ${num} required to be undefined or a boolean, got ${typeof o.required}`);
|
|
||||||
|
|
||||||
if (typeof o.choices !== 'undefined' && !(o.choices instanceof Array))
|
|
||||||
throw new TypeError(`Expected type of option ${num} choices to be undefined or an array, got ${typeof o.choices}`);
|
|
||||||
|
|
||||||
if (o.choices)
|
|
||||||
this.checkOptionChoices(o.choices);
|
|
||||||
|
|
||||||
if (typeof o.options !== 'undefined' && !(o.options instanceof Array))
|
|
||||||
throw new TypeError(`Expected type of option ${num} options to be undefined or an array, got ${typeof o.options}`);
|
|
||||||
|
|
||||||
if (o.options)
|
|
||||||
this.checkOptions(o.options);
|
|
||||||
|
|
||||||
num++;
|
|
||||||
});
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Check command option choices */
|
|
||||||
checkOptionChoices(choices) {
|
|
||||||
let num = 0;
|
|
||||||
choices.forEach(c => {
|
|
||||||
if (typeof c.name !== 'string')
|
|
||||||
throw new TypeError(`Expected type of option choice ${num} name to be a string, got ${typeof c.name}`);
|
|
||||||
|
|
||||||
if (c.name.length < 1 || c.name.length > 100)
|
|
||||||
throw new TypeError(`Length of option choice ${num} name must be 1-100`);
|
|
||||||
|
|
||||||
if (typeof c.value !== 'string' && typeof c.value !== 'number')
|
|
||||||
throw new TypeError(`Expected type of option choice ${num} value to be a string or number, got ${typeof c.value}`);
|
|
||||||
|
|
||||||
num++;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Execute a command
|
* Execute a command
|
||||||
* @param {(Interaction|Message)} interaction_or_message - Command interaction or message
|
* @param {Message} message - Command message
|
||||||
*/
|
*/
|
||||||
async handle(interaction_or_message, slash) {
|
async handle(message) {
|
||||||
slash = slash === false ? false : true;
|
|
||||||
let cmd_name,
|
|
||||||
args = {},
|
|
||||||
data = {},
|
|
||||||
guild_id,
|
|
||||||
channel_id,
|
|
||||||
member_id;
|
|
||||||
|
|
||||||
if (slash) {
|
let settings = await message.guild.settings;
|
||||||
cmd_name = interaction_or_message.data.name;
|
if (!settings) settings = await message.guild.createSettings();
|
||||||
|
const prefix = settings.command_prefix;
|
||||||
guild_id = interaction_or_message.guild_id;
|
|
||||||
channel_id = interaction_or_message.channel_id;
|
|
||||||
member_id = interaction_or_message.member.user.id;
|
|
||||||
|
|
||||||
if (interaction_or_message.data.options)
|
|
||||||
interaction_or_message.data.options.forEach(({ name, value }) => args[name] = value);
|
|
||||||
} else {
|
|
||||||
cmd_name = interaction_or_message.content.match(/^tickets\/(\S+)/mi);
|
|
||||||
if (cmd_name) cmd_name = cmd_name[1];
|
|
||||||
|
|
||||||
guild_id = interaction_or_message.guild.id;
|
|
||||||
channel_id = interaction_or_message.channel.id;
|
|
||||||
member_id = interaction_or_message.author.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (cmd_name === null || !this.commands.has(cmd_name))
|
|
||||||
return this.client.log.warn(`Received "${cmd_name}" command invocation, but the command manager does not have a "${cmd_name}" command registered`);
|
|
||||||
|
|
||||||
data.args = args;
|
|
||||||
data.guild = await this.client.guilds.fetch(guild_id);
|
|
||||||
data.channel = await this.client.channels.fetch(channel_id),
|
|
||||||
data.member = await data.guild.members.fetch(member_id);
|
|
||||||
|
|
||||||
let settings = await data.guild.settings;
|
|
||||||
if (!settings) settings = await data.guild.createSettings();
|
|
||||||
const i18n = this.client.i18n.get(settings.locale);
|
const i18n = this.client.i18n.get(settings.locale);
|
||||||
|
|
||||||
const cmd = this.commands.get(cmd_name);
|
let cmd_name = message.content.match(new RegExp(`^${prefix}(\\S+)`, 'mi'));
|
||||||
|
if (!cmd_name) return;
|
||||||
|
|
||||||
if (cmd.slash && !slash) {
|
let raw_args = message.content.replace(cmd_name[0], '').trim();
|
||||||
this.client.log.commands(`Blocking command execution for the "${cmd_name}" command as it was invoked by a message, not a slash command interaction.`);
|
cmd_name = cmd_name[1];
|
||||||
try {
|
|
||||||
data.channel.send(i18n('must_be_slash', cmd_name)); // interaction_or_message.reply
|
|
||||||
} catch (err) {
|
|
||||||
this.client.log.warn('Failed to reply to blocked command invocation message');
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const no_perm = cmd.permissions instanceof Array
|
const cmd = this.commands.find(cmd => cmd.aliases.includes(cmd_name));
|
||||||
&& !data.member.hasPermission(cmd.permissions);
|
if (!cmd);
|
||||||
|
|
||||||
|
let data = [...raw_args.matchAll(/(\w*)\s?:\s?("(.*)"|[\w<>@!#]*)/gmi)];
|
||||||
|
let args = {};
|
||||||
|
data.forEach(arg => args[arg[1]] = arg[3] || arg[2]);
|
||||||
|
|
||||||
|
const no_perm = cmd.permissions instanceof Array && !message.member.hasPermission(cmd.permissions);
|
||||||
if (no_perm) {
|
if (no_perm) {
|
||||||
let perms = cmd.permissions.map(p => `\`${p}\``).join(', ');
|
let perms = cmd.permissions.map(p => `\`${p}\``).join(', ');
|
||||||
let msg = i18n('no_perm', perms);
|
return message.channel.send(i18n('no_perm', perms));
|
||||||
if (slash) return await cmd.respond(interaction_or_message, msg, true);
|
}
|
||||||
else return await interaction_or_message.channel.send(msg);
|
|
||||||
|
let guild_categories = await this.client.db.models.Category.findAll({
|
||||||
|
where: {
|
||||||
|
guild: message.guild.id
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (cmd.staff_only) {
|
||||||
|
let staff_roles = new Set(); // eslint-disable-line no-undef
|
||||||
|
guild_categories.forEach(cat => {
|
||||||
|
cat.roles.forEach(r => staff_roles.add(r));
|
||||||
|
});
|
||||||
|
staff_roles = staff_roles.filter(r => message.member.roles.cache.has(r));
|
||||||
|
if (staff_roles.length === 0) {
|
||||||
|
return message.channel.send(i18n('staff_only'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (slash) await cmd.acknowledge(interaction_or_message, true); // respond to discord
|
this.client.log.commands(`Executing "${cmd_name}" command (invoked by ${message.author.tag})`);
|
||||||
this.client.log.commands(`Executing "${cmd_name}" command (invoked by ${data.member.user.tag})`);
|
await cmd.execute(message, args, raw_args); // execute the command
|
||||||
await cmd.execute(data, interaction_or_message); // run 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);
|
||||||
|
@ -1,10 +1,6 @@
|
|||||||
/* eslint-disable no-unused-vars */
|
/* eslint-disable no-unused-vars */
|
||||||
const { Client } = require('discord.js');
|
const { Client } = require('discord.js');
|
||||||
const Command = require('../commands/command');
|
const Command = require('../commands/command');
|
||||||
const {
|
|
||||||
OptionTypes,
|
|
||||||
ResponseTypes
|
|
||||||
} = require('../commands/helpers');
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const { join } = require('path');
|
const { join } = require('path');
|
||||||
const { path } = require('../../utils/fs');
|
const { path } = require('../../utils/fs');
|
||||||
@ -85,12 +81,6 @@ module.exports = class Plugin {
|
|||||||
name: clean,
|
name: clean,
|
||||||
path: path(`./user/plugins/${clean}`)
|
path: path(`./user/plugins/${clean}`)
|
||||||
};
|
};
|
||||||
|
|
||||||
this.helpers = {
|
|
||||||
Command,
|
|
||||||
OptionTypes,
|
|
||||||
ResponseTypes
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -26,6 +26,7 @@ module.exports = {
|
|||||||
debug: false,
|
debug: false,
|
||||||
defaults: {
|
defaults: {
|
||||||
colour: '#009999', // https://discord.js.org/#/docs/main/stable/typedef/ColorResolvable
|
colour: '#009999', // https://discord.js.org/#/docs/main/stable/typedef/ColorResolvable
|
||||||
|
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: '-',
|
prefix: '-',
|
||||||
|
Loading…
Reference in New Issue
Block a user