| import { |
| CommandInteraction, |
| GuildMember, |
| Message, |
| ActionRowBuilder, |
| ButtonBuilder, |
| MessageComponentInteraction, |
| TextChannel, |
| ButtonStyle, |
| User, |
| ThreadChannel |
| } from "discord.js"; |
| import EmojiEmbed from "../utils/generateEmojiEmbed.js"; |
| import getEmojiByName from "../utils/getEmojiByName.js"; |
| import client from "../utils/client.js"; |
| import { messageException } from "../utils/createTemporaryStorage.js"; |
| |
| const noTopic = new EmojiEmbed() |
| .setTitle("User not found") |
| .setDescription("There is no user associated with this ticket.") |
| .setStatus("Danger") |
| .setEmoji("CONTROL.BLOCKCROSS"); |
| |
| export default async function (interaction: CommandInteraction | MessageComponentInteraction) { |
| if (interaction.channel === null) return; |
| if (!(interaction.channel instanceof TextChannel || interaction.channel instanceof ThreadChannel)) return; |
| const { log, NucleusColors, entry, renderUser, renderDelta } = client.logger; |
| |
| let messages: Message[] = []; |
| let deletedCount: number; |
| |
| do { |
| const fetched = await (interaction.channel as TextChannel).messages.fetch({ limit: 100 }); |
| const deleted = await (interaction.channel as TextChannel).bulkDelete(fetched, true); |
| deletedCount = deleted.size; |
| messages = messages.concat(Array.from(deleted.values() as Iterable<Message>)); |
| if (messages.length === 1) messageException(interaction.guild!.id, interaction.channel.id, messages[0]!.id); |
| } while (deletedCount === 100); |
| messages = messages.filter( |
| (message) => |
| !message.components.some((component) => |
| component.components.some((child) => child.customId?.includes("transcript") ?? false) |
| ) |
| ); |
| |
| let topic; |
| let member: GuildMember = interaction.guild?.members.me!; |
| if (interaction.channel instanceof TextChannel) { |
| topic = interaction.channel.topic; |
| if (topic === null) return await interaction.reply({ embeds: [noTopic] }); |
| const mem = interaction.guild!.members.cache.get(topic.split(" ")[1]!); |
| if (mem) member = mem; |
| } else { |
| topic = interaction.channel.name; |
| const split = topic.split("-").map((p) => p.trim()) as [string, string, string]; |
| const mem = interaction.guild!.members.cache.get(split[1]); |
| if (mem) member = mem; |
| } |
| |
| const newOut = await client.database.transcripts.createTranscript(messages, interaction, member); |
| |
| const [code, key, iv] = await client.database.transcripts.create(newOut); |
| if (!code) |
| return await interaction.reply({ |
| embeds: [ |
| new EmojiEmbed() |
| .setTitle("Error") |
| .setDescription("An error occurred while creating the transcript.") |
| .setStatus("Danger") |
| .setEmoji("CONTROL.BLOCKCROSS") |
| ] |
| }); |
| const guildConfig = await client.database.guilds.read(interaction.guild!.id); |
| const m: Message = (await interaction.reply({ |
| embeds: [ |
| new EmojiEmbed() |
| .setTitle("Transcript") |
| .setDescription( |
| "You can view the transcript using the link below. You can save the link for later" + |
| (guildConfig.logging.logs.channel |
| ? ` or find it in <#${guildConfig.logging.logs.channel}> once you press delete below. After this the channel will be deleted.` |
| : ". It will be automatically deleted after 30 days if a logging channel is not set.") |
| ) |
| .setStatus("Success") |
| .setEmoji("CONTROL.DOWNLOAD") |
| ], |
| components: [ |
| new ActionRowBuilder<ButtonBuilder>().addComponents([ |
| new ButtonBuilder() |
| .setLabel("View") |
| .setStyle(ButtonStyle.Link) |
| .setURL(`https://testing.coded.codes/nucleus/transcript/${code}?key=${key}&iv=${iv}`), |
| new ButtonBuilder() |
| .setLabel("Delete") |
| .setStyle(ButtonStyle.Danger) |
| .setCustomId("close") |
| .setEmoji(getEmojiByName("CONTROL.CROSS", "id")) |
| ]) |
| ], |
| fetchReply: true |
| })) as Message; |
| let i; |
| try { |
| i = await m.awaitMessageComponent({ |
| time: 300000, |
| filter: (i) => { |
| return ( |
| i.user.id === interaction.user.id && |
| i.channel!.id === interaction.channel!.id && |
| i.message.id === m.id |
| ); |
| } |
| }); |
| await i.deferUpdate(); |
| } catch { |
| return; |
| } |
| const data = { |
| meta: { |
| type: "ticketDeleted", |
| displayName: "Ticket Deleted", |
| calculateType: "ticketUpdate", |
| color: NucleusColors.red, |
| emoji: "GUILD.TICKET.CLOSE", |
| timestamp: Date.now() |
| }, |
| list: { |
| ticketFor: entry(member.id, renderUser(member.user)), |
| deletedBy: entry(interaction.member!.user.id, renderUser(interaction.member!.user as User)), |
| deleted: entry(Date.now().toString(), renderDelta(Date.now())), |
| transcript: entry(code, `https://clicks.codes/nucleus/transcript/${code}`) |
| }, |
| hidden: { |
| guild: interaction.guild!.id |
| } |
| }; |
| log(data); |
| await interaction.channel.delete(); |
| return; |
| } |