From 637c2800d42e36d715c69391f7bdc61cd9d64f17 Mon Sep 17 00:00:00 2001 From: Danya H Date: Mon, 10 Jun 2024 16:46:21 +0100 Subject: [PATCH] users now cant create more than 3 tickets + ticket now closes and locks --- src/commands/admin/create-ticket-system.ts | 73 ++++++++++++++++------ src/lib/logger.ts | 8 ++- 2 files changed, 62 insertions(+), 19 deletions(-) diff --git a/src/commands/admin/create-ticket-system.ts b/src/commands/admin/create-ticket-system.ts index 8b04e2b..0741c25 100644 --- a/src/commands/admin/create-ticket-system.ts +++ b/src/commands/admin/create-ticket-system.ts @@ -9,8 +9,8 @@ import { GuildTextThreadCreateOptions, MessageCreateOptions, Role, - roleMention, - userMention, + roleMention, ThreadChannel, + userMention } from 'discord.js' import { db, DBTableEnum } from '../../db' @@ -124,18 +124,36 @@ export class CreateTicketSystem { return } - const ticketRole = await db.get(DBTableEnum.TICKET_ROLE) + // prevent creating ticket for users with 3 or more tickets + const allThreads = await interaction.channel.threads.fetch() + const ownedThreads = allThreads.threads.reduce((total, thread) => { + if (thread.ownerId === interaction.user.id && (!thread.archived || !thread.locked)) total += 1 + return total + }, 0) + if (ownedThreads >= 3 && interaction.user.id !== interaction.guild.ownerId) { + logger.action('Denied ticket creation', `User: ${interaction.user.username}(${interaction.user.id})\nActive tickets: ${ownedThreads}`) + await interaction.editReply('❌ You already have too many tickets') + return + } - // create ticket channel - const threadChannelSettings: GuildTextThreadCreateOptions = - { - name: `${interaction.user.username}`, - type: ChannelType.PrivateThread, - invitable: false, - } - const threadChannel = await interaction.channel.threads.create( - threadChannelSettings, - ) + const ticketRole = await db.get(DBTableEnum.TICKET_ROLE) + let threadChannel: ThreadChannel + + try { + // create ticket channel + const threadChannelSettings: GuildTextThreadCreateOptions = + { + name: `${interaction.user.username}-${(new Date).toLocaleDateString().replaceAll('/', '-')}`, + type: ChannelType.PrivateThread, + invitable: false, + } + threadChannel = await interaction.channel.threads.create( + threadChannelSettings, + ) + } catch (e) { + logger.error('Create ticket channel', e) + return + } // welcoming message in ticket const threadChannelMessage: MessageCreateOptions = { @@ -168,6 +186,8 @@ export class CreateTicketSystem { await threadChannel.members.add(user) await threadChannel.members.add(owner) + logger.action('Created ticket', `User: ${user.user.username}(${user.id})\nChannel: ${threadChannel.name}(${threadChannel.id})`) + // close interaction await interaction.editReply({ embeds: [ @@ -182,15 +202,32 @@ export class CreateTicketSystem { @ButtonComponent({ id: 'close-btn' }) async closeBtn(interaction: ButtonInteraction): Promise { await interaction.deferReply() - if (!interaction.channel) { + + logger.action('Ticket close attempt', `User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`) + + if (!interaction.channel || !interaction.guild) { await interaction.editReply('❌ Ticket channel does not exist') return } - if (interaction.channel.isThread() && !interaction.channel.archived) { - await interaction.editReply('Closing ticket..') - await interaction.channel.setArchived(true, `Archived by ${userMention(interaction.user.id)}(${interaction.user.id})`) + if (!interaction.channel.isThread() || interaction.channel.archived) { return } - await interaction.editReply('❌ Ticket is not a thread') + + await interaction.editReply('Closing ticket..') + + try { + // remove ticket owner if exists + const ticketOwner = interaction.channel.ownerId ? await interaction.guild.members.fetch(interaction.channel.ownerId) : null + ticketOwner ? await interaction.channel.members.remove(ticketOwner) : null + + // lock + archive thread + await interaction.channel.setLocked(true, `Locked by ${userMention(interaction.user.id)}(${interaction.user.id})`) + await interaction.channel.setArchived(true, `Archived by ${userMention(interaction.user.id)}(${interaction.user.id})`) + } catch (e) { + logger.error('Closing ticket', e) + return + } + + logger.action('Ticket close attempt successful', `User: ${interaction.user.username}(${interaction.user.id})\nChannel: ${interaction.channel?.id}`) } } diff --git a/src/lib/logger.ts b/src/lib/logger.ts index 0f3d2b8..f1cdf85 100644 --- a/src/lib/logger.ts +++ b/src/lib/logger.ts @@ -1,7 +1,7 @@ import c from 'chalk' class Logger { - error(msg: string, err: string) { + error(msg: string, err: unknown) { console.log(c.red.bold('Error: ') + c.red(msg) + '\n' + err + '\n') } @@ -10,6 +10,12 @@ class Logger { c.cyan.bold('Entry: ') + c.cyan(field) + '\n' + value + '\n', ) } + + action(msg: string, value: string) { + console.log( + c.blueBright.bold('Action: ') + c.blueBright(msg) + '\n' + value + '\n', + ) + } } export const logger = new Logger()