mirror of
https://github.com/Hessenuk/DiscordTickets.git
synced 2024-12-23 00:03:09 +02:00
Settings command, many small changes, improvements, and fixes
This commit is contained in:
parent
e6fa1d067f
commit
ffc415354a
@ -1,4 +1,6 @@
|
||||
const Command = require('../modules/commands/command');
|
||||
const fetch = require('node-fetch');
|
||||
const { MessageAttachment } = require('discord.js');
|
||||
|
||||
module.exports = class SettingsCommand extends Command {
|
||||
constructor(client) {
|
||||
@ -12,11 +14,108 @@ module.exports = class SettingsCommand extends Command {
|
||||
});
|
||||
}
|
||||
|
||||
async execute({ guild, member, channel, args }, message) {
|
||||
async execute({ guild, channel, member }, message) {
|
||||
|
||||
let settings = await guild.settings;
|
||||
const i18n = this.client.i18n.get(settings.locale);
|
||||
|
||||
channel.send('Settings!');
|
||||
let attachments = [ ...message.attachments.values() ];
|
||||
|
||||
if (attachments.length >= 1) {
|
||||
// load settings from json
|
||||
let data = await (await fetch(attachments[0].url)).json();
|
||||
|
||||
settings.colour = data.colour;
|
||||
settings.error_colour = data.error_colour;
|
||||
settings.locale = data.locale;
|
||||
settings.log_messages = data.log_messages;
|
||||
settings.success_colour = data.success_colour;
|
||||
await settings.save();
|
||||
|
||||
for (let c of data.categories) {
|
||||
let permissions = [
|
||||
...[
|
||||
{
|
||||
id: guild.roles.everyone,
|
||||
deny: ['VIEW_CHANNEL']
|
||||
}
|
||||
],
|
||||
...c.roles.map(r => {
|
||||
return {
|
||||
id: r,
|
||||
allow: ['VIEW_CHANNEL', 'READ_MESSAGE_HISTORY', 'SEND_MESSAGES', 'ATTACH_FILES']
|
||||
};
|
||||
})
|
||||
];
|
||||
|
||||
if (c.id) {
|
||||
// existing category
|
||||
let category = await this.client.db.models.Category.findOne({
|
||||
where: {
|
||||
id: c.id
|
||||
}
|
||||
});
|
||||
category.name = c.name;
|
||||
category.roles = c.roles;
|
||||
category.save();
|
||||
|
||||
let cat_channel = await this.client.channels.fetch(c.id);
|
||||
await cat_channel.edit({
|
||||
name: c.name, // await cat_channel.setName(c.name);
|
||||
permissionOverwrites: permissions // await cat_channel.overwritePermissions(permissions);
|
||||
},
|
||||
`Tickets category updated by ${member.user.tag}`
|
||||
);
|
||||
} else {
|
||||
// create a new category
|
||||
let created = await guild.channels.create(c.name, {
|
||||
type: 'category',
|
||||
reason: `Tickets category created by ${member.user.tag}`,
|
||||
permissionOverwrites: permissions
|
||||
});
|
||||
await this.client.db.models.Category.create({
|
||||
id: created.id,
|
||||
name: c.name,
|
||||
guild: guild.id,
|
||||
roles: c.roles
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
channel.send(`\`\`\`json\n${JSON.stringify(data, null, 2)}\n\`\`\``);
|
||||
} else {
|
||||
// upload settings as json to be modified
|
||||
let data = {
|
||||
categories: [],
|
||||
colour: settings.colour,
|
||||
error_colour: settings.error_colour,
|
||||
locale: settings.locale,
|
||||
log_messages: settings.log_messages,
|
||||
success_colour: settings.success_colour,
|
||||
};
|
||||
|
||||
let categories = await this.client.db.models.Category.findAll({
|
||||
where: {
|
||||
guild: guild.id
|
||||
}
|
||||
});
|
||||
|
||||
for (let c of categories) {
|
||||
data.categories.push({
|
||||
id: c.id,
|
||||
name: c.name,
|
||||
roles: c.roles
|
||||
});
|
||||
}
|
||||
|
||||
let attachment = new MessageAttachment(
|
||||
Buffer.from(JSON.stringify(data, null, 2)),
|
||||
`Settings for ${guild.name}.json`
|
||||
);
|
||||
|
||||
channel.send(i18n('commands.settings.response'), {
|
||||
files: [attachment]
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
@ -5,7 +5,6 @@ const {
|
||||
const { path } = require('../utils/fs');
|
||||
const config = require('../../user/config');
|
||||
const types = require('./dialects');
|
||||
const supported = Object.keys(types);
|
||||
|
||||
module.exports = async (log) => {
|
||||
|
||||
@ -21,6 +20,7 @@ module.exports = async (log) => {
|
||||
|
||||
let type = (DB_TYPE || 'sqlite').toLowerCase();
|
||||
|
||||
const supported = Object.keys(types);
|
||||
if (!supported.includes(type)) {
|
||||
log.error(new Error(`DB_TYPE (${type}) is not a valid type`));
|
||||
return process.exit();
|
||||
@ -68,10 +68,22 @@ module.exports = async (log) => {
|
||||
primaryKey: true,
|
||||
allowNull: false,
|
||||
},
|
||||
locale: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: config.locale
|
||||
},
|
||||
colour: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: config.defaults.colour
|
||||
},
|
||||
success_colour: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'GREEN'
|
||||
},
|
||||
error_colour: {
|
||||
type: DataTypes.STRING,
|
||||
defaultValue: 'RED'
|
||||
},
|
||||
log_messages: {
|
||||
type: DataTypes.BOOLEAN,
|
||||
defaultValue: config.defaults.log_messages
|
||||
@ -100,6 +112,9 @@ module.exports = async (log) => {
|
||||
},
|
||||
unique: 'name_guild'
|
||||
},
|
||||
roles: {
|
||||
type: DataTypes.JSON
|
||||
}
|
||||
}, {
|
||||
tableName: DB_TABLE_PREFIX + 'categories'
|
||||
});
|
||||
|
@ -5,7 +5,7 @@ module.exports = {
|
||||
|
||||
switch (interaction.type) {
|
||||
case 1:
|
||||
client.log.debug('Received interaction ping, responding with pong');
|
||||
client.log.info('Received interaction ping, responding with pong');
|
||||
await client.api.interactions(interaction.id, interaction.token).callback.post({
|
||||
data: {
|
||||
type: 1, // PONG
|
||||
@ -13,7 +13,7 @@ module.exports = {
|
||||
});
|
||||
break;
|
||||
case 2:
|
||||
client.commands.handle(interaction);
|
||||
client.commands.handle(interaction, true);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,6 @@ module.exports = {
|
||||
event: 'messageDelete',
|
||||
execute: async (client, message) => {
|
||||
|
||||
if (message.partial)
|
||||
try {
|
||||
await message.fetch();
|
||||
} catch (err) {
|
||||
return client.log.error(err);
|
||||
}
|
||||
|
||||
let settings = await message.guild?.settings;
|
||||
|
||||
if (settings?.log_messages) {
|
||||
|
@ -2,12 +2,13 @@ module.exports = {
|
||||
event: 'msgUpdate',
|
||||
execute: async (client, oldm, newm) => {
|
||||
|
||||
if (newm.partial)
|
||||
if (newm.partial) {
|
||||
try {
|
||||
await newm.fetch();
|
||||
} catch (err) {
|
||||
return client.log.error(err);
|
||||
}
|
||||
}
|
||||
|
||||
let settings = await newm.guild?.settings;
|
||||
|
||||
|
@ -23,6 +23,7 @@
|
||||
"description": "Configure Discord Tickets"
|
||||
}
|
||||
},
|
||||
"must_be_slash": "❌ This command must be invoked by a slash command interaction (`/%s`).",
|
||||
"no_perm": "❌ You do not have the permissions required to use this command:\n%s",
|
||||
"support_only": "❌ You must be a member of staff to use this command."
|
||||
}
|
@ -70,7 +70,7 @@ module.exports = class CommandManager {
|
||||
if (typeof data.description !== 'string')
|
||||
throw new TypeError(`Expected type of command description to be a string, got ${typeof data.description}`);
|
||||
|
||||
if (data.name.length < 1 || data.name.length > 100)
|
||||
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))
|
||||
@ -139,9 +139,9 @@ module.exports = class CommandManager {
|
||||
|
||||
/**
|
||||
* Execute a command
|
||||
* @param {(Interaction|Message)} interaction - Command interaction, or message
|
||||
* @param {(Interaction|Message)} interaction_or_message - Command interaction or message
|
||||
*/
|
||||
async handle(interaction, slash) {
|
||||
async handle(interaction_or_message, slash) {
|
||||
slash = slash === false ? false : true;
|
||||
let cmd_name,
|
||||
args = {},
|
||||
@ -151,54 +151,62 @@ module.exports = class CommandManager {
|
||||
member_id;
|
||||
|
||||
if (slash) {
|
||||
cmd_name = interaction.data.name;
|
||||
cmd_name = interaction_or_message.data.name;
|
||||
|
||||
guild_id = interaction.guild_id;
|
||||
channel_id = interaction.channel_id;
|
||||
member_id = interaction.member.user.id;
|
||||
guild_id = interaction_or_message.guild_id;
|
||||
channel_id = interaction_or_message.channel_id;
|
||||
member_id = interaction_or_message.member.user.id;
|
||||
|
||||
if (interaction.data.options)
|
||||
interaction.data.options.forEach(({ name, value }) => args[name] = value);
|
||||
if (interaction_or_message.data.options)
|
||||
interaction_or_message.data.options.forEach(({ name, value }) => args[name] = value);
|
||||
} else {
|
||||
cmd_name = interaction.content.match(/^tickets\/(\S+)/mi);
|
||||
cmd_name = interaction_or_message.content.match(/^tickets\/(\S+)/mi);
|
||||
if (cmd_name) cmd_name = cmd_name[1];
|
||||
|
||||
guild_id = interaction.guild.id;
|
||||
channel_id = interaction.channel.id;
|
||||
member_id = interaction.author.id;
|
||||
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))
|
||||
throw new Error(`Received "${cmd_name}" command invocation, but the command manager does not have a "${cmd_name}" command`);
|
||||
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);
|
||||
|
||||
const cmd = this.commands.get(cmd_name);
|
||||
|
||||
let settings = await data.guild.settings;
|
||||
if (!settings) settings = await data.guild.createSettings();
|
||||
const i18n = this.client.i18n.get(settings.locale);
|
||||
|
||||
// if (cmd.staff_only) {}
|
||||
const cmd = this.commands.get(cmd_name);
|
||||
|
||||
if (cmd.slash && !slash) {
|
||||
this.client.log.commands(`Blocking command execution for the "${cmd_name}" command as it was invoked by a message, not a slash command interaction_or_message.`);
|
||||
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
|
||||
&& !data.member.hasPermission(cmd.permissions);
|
||||
if (no_perm) {
|
||||
let perms = cmd.permissions.map(p => `\`${p}\``).join(', ');
|
||||
let msg = i18n('no_perm', perms);
|
||||
if (slash) return await cmd.sendResponse(interaction, msg, true);
|
||||
else return await interaction.channel.send(msg);
|
||||
if (slash) return await cmd.respond(interaction_or_message, msg, true);
|
||||
else return await interaction_or_message.channel.send(msg);
|
||||
}
|
||||
|
||||
try {
|
||||
if (slash) await cmd.acknowledge(interaction, true); // respond to discord
|
||||
if (slash) await cmd.acknowledge(interaction_or_message, true); // respond to discord
|
||||
this.client.log.commands(`Executing "${cmd_name}" command (invoked by ${data.member.user.tag})`);
|
||||
await cmd.execute(data, interaction); // run the command
|
||||
await cmd.execute(data, interaction_or_message); // run the command
|
||||
} catch (e) {
|
||||
this.client.log.warn(`(COMMANDS) An error occurred whilst executed the ${cmd_name} command`);
|
||||
this.client.log.warn(`An error occurred whilst executing the ${cmd_name} command`);
|
||||
this.client.log.error(e);
|
||||
}
|
||||
|
||||
|
@ -39,16 +39,36 @@ module.exports = class TicketManager extends EventEmitter {
|
||||
/**
|
||||
* Close a ticket
|
||||
* @param {string} ticket - The channel ID, or the ticket number
|
||||
* @param {string} [closer] - ID of the member who is closing the ticket
|
||||
*/
|
||||
async close(ticket) {
|
||||
|
||||
async close(ticket, closer) {
|
||||
if (!this.client.channels.resolve(ticket)) {
|
||||
let row = await this.client.db.Models.Ticket.findOne({
|
||||
where: {
|
||||
number: ticket
|
||||
}
|
||||
});
|
||||
if (!row) throw new Error(`Could not find a ticket with number ${ticket}`);
|
||||
ticket = row.id;
|
||||
}
|
||||
|
||||
let row = await this.client.db.Models.Ticket.findOne({
|
||||
where: {
|
||||
id: ticket
|
||||
}
|
||||
});
|
||||
|
||||
if (!row) throw new Error(`Could not find a ticket with ID ${ticket}`);
|
||||
|
||||
this.emit('beforeClose', ticket, closer);
|
||||
|
||||
/**
|
||||
* Close multiple tickets
|
||||
* @param {string[]} tickets - An array of channel IDs to close **(does not accept ticket numbers)**
|
||||
*
|
||||
*
|
||||
* for each message in table, create entities
|
||||
*
|
||||
*
|
||||
*/
|
||||
async closeMultiple(tickets) {
|
||||
|
||||
}
|
||||
|
||||
};
|
@ -25,12 +25,12 @@
|
||||
module.exports = {
|
||||
debug: false,
|
||||
defaults: {
|
||||
colour: '#009999',
|
||||
colour: '#009999', // https://discord.js.org/#/docs/main/stable/typedef/ColorResolvable
|
||||
log_messages: true, // transcripts/archives will be empty if false
|
||||
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.__',
|
||||
},
|
||||
locale: 'en-GB',
|
||||
locale: 'en-GB', // used for globals (such as commands) and the default guild locale
|
||||
logs: {
|
||||
enabled: true,
|
||||
keep_for: 30
|
||||
|
Loading…
Reference in New Issue
Block a user