diff --git a/src/i18n/en-GB.yml b/src/i18n/en-GB.yml index da77e06..4ca9725 100644 --- a/src/i18n/en-GB.yml +++ b/src/i18n/en-GB.yml @@ -160,7 +160,13 @@ log: create: created delete: deleted update: updated - tickets: + ticket: + description: '{user} {verb} ticket' + ticket: Ticket + title: Ticket {verb} + verb: + create: created + close: closed menus: category: placeholder: Select a ticket category diff --git a/src/lib/logging.js b/src/lib/logging.js index 8289cf9..7140b3a 100644 --- a/src/lib/logging.js +++ b/src/lib/logging.js @@ -60,8 +60,6 @@ async function getLogChannel(client, guildId) { async function logAdminEvent(client, { guildId, userId, action, target, diff, }) { - const user = await client.users.fetch(userId); - client.log.info.settings(`${user.tag} ${action}d ${target.type} ${target.id}`); const settings = await client.prisma.guild.findUnique({ select: { footer: true, @@ -70,6 +68,10 @@ async function logAdminEvent(client, { }, where: { id: guildId }, }); + /** @type {import("discord.js").Guild} */ + const guild = client.guilds.cache.get(guildId); + const member = await guild.members.fetch(userId); + client.log.info.settings(`${member.user.tag} ${action}d ${target.type} ${target.id}`); if (!settings.logChannel) return; const colour = action === 'create' ? 'Green' : action === 'update' @@ -77,7 +79,7 @@ async function logAdminEvent(client, { ? 'Red' : 'Default'; const getMessage = client.i18n.getLocale(settings.locale); const i18nOptions = { - user: `<@${user.id}>`, + user: `<@${member.user.id}>`, verb: getMessage(`log.admin.verb.${action}`), }; const channel = client.channels.cache.get(settings.logChannel); @@ -86,8 +88,8 @@ async function logAdminEvent(client, { new EmbedBuilder() .setColor(colour) .setAuthor({ - iconURL: user.avatarURL(), - name: user.username, + iconURL: member.displayAvatarURL(), + name: member.displayName, }) .setTitle(getMessage('log.admin.title.joined', { ...i18nOptions, @@ -119,7 +121,66 @@ async function logAdminEvent(client, { return await channel.send({ embeds }); } +/** + * @param {import("client")} client + * @param {object} details + * @param {string} details.guildId + * @param {string} details.userId + * @param {string} details.action +*/ +async function logTicketEvent(client, { + userId, action, target, +}) { + const ticket = await client.prisma.ticket.findUnique({ + include: { guild: true }, + where: { id: target.id }, + }); + if (!ticket) return; + /** @type {import("discord.js").Guild} */ + const guild = client.guilds.cache.get(ticket.guild.id); + const member = await guild.members.fetch(userId); + client.log.info.tickets(`${member.user.tag} ${action}d ticket ${target.id}`); + if (!ticket.guild.logChannel) return; + const colour = action === 'create' + ? 'Aqua' : action === 'close' + ? 'DarkAqua' : action === 'claim' + ? 'LuminousVividPink' : action === 'unclaim' + ? 'DarkVividPink' : 'Default'; + const getMessage = client.i18n.getLocale(ticket.guild.locale); + const i18nOptions = { + user: `<@${member.user.id}>`, + verb: getMessage(`log.ticket.verb.${action}`), + }; + const channel = client.channels.cache.get(ticket.guild.logChannel); + if (!channel) return; + const embeds = [ + new EmbedBuilder() + .setColor(colour) + .setAuthor({ + iconURL: member.displayAvatarURL(), + name: member.displayName, + }) + .setTitle(getMessage('log.ticket.title', { + ...i18nOptions, + verb: getMessage(`log.ticket.verb.${action}`), + })) + .setDescription(getMessage('log.ticket.description', { + ...i18nOptions, + verb: getMessage(`log.ticket.verb.${action}`), + })) + .addFields([ + { + name: getMessage('log.ticket.ticket'), + value: target.name ?? target.id, + }, + ]), + ]; + + return await channel.send({ embeds }); +} + module.exports = { getLogChannel, logAdminEvent, + logTicketEvent, }; \ No newline at end of file diff --git a/src/lib/tickets/manager.js b/src/lib/tickets/manager.js index 626eae9..7a5194d 100644 --- a/src/lib/tickets/manager.js +++ b/src/lib/tickets/manager.js @@ -1,6 +1,7 @@ /* eslint-disable max-lines */ const { ActionRowBuilder, + ButtonBuilder, ButtonStyle, ModalBuilder, SelectMenuBuilder, @@ -11,7 +12,7 @@ const { const emoji = require('node-emoji'); const ms = require('ms'); const ExtendedEmbedBuilder = require('../embed'); -const { ButtonBuilder } = require('discord.js'); +const { logTicketEvent } = require('../logging'); /** * @typedef {import('@prisma/client').Category & {guild: import('@prisma/client').Guild} & {questions: import('@prisma/client').Question[]}} CategoryGuildQuestions @@ -274,10 +275,12 @@ module.exports = class TicketManager { new ExtendedEmbedBuilder() .setColor(category.guild.primaryColour) .setFields( - category.questions.map(q => ({ - name: q.label, - value: interaction.fields.getTextInputValue(q.id) || getMessage('ticket.answers.no_value'), - })), + category.questions + .sort((a, b) => a.order - b.order) + .map(q => ({ + name: q.label, + value: interaction.fields.getTextInputValue(q.id) || getMessage('ticket.answers.no_value'), + })), ), ); // embeds[0].setFields( @@ -342,7 +345,7 @@ module.exports = class TicketManager { const pings = category.pingRoles.map(r => `<@&${r}>`).join(' '); const sent = await channel.send({ - components: components.components.length >=1 ? [components] : [], + components: components.components.length >= 1 ? [components] : [], content: getMessage('ticket.opening_message.content', { creator: interaction.user.toString(), staff: pings ? pings + ',' : '', @@ -392,6 +395,13 @@ module.exports = class TicketManager { .setDescription(getMessage('ticket.created.description', { channel: channel.toString() })), ], }); - // TODO: log channel + await logTicketEvent(this.client, { // FIXME: remove await + action: 'create', + target: { + id: ticket.id, + name: channel.toString(), + }, + userId: interaction.user.id, + }); } }; \ No newline at end of file