Skip to content

Commit

Permalink
v0.15.16
Browse files Browse the repository at this point in the history
- FixFailed to delete message: DiscordAPIError[10008]: Unknown Message
- Code optimization
  • Loading branch information
LucasB25 committed Jun 4, 2024
1 parent 67984fe commit 4a8d162
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 155 deletions.
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "AikouTicket",
"version": "0.15.15",
"version": "0.15.16",
"description": "A simple AikouTicket bot for discord",
"type": "module",
"main": "dist/index.js",
Expand Down Expand Up @@ -30,7 +30,7 @@
"homepage": "https://github.com/LucasB25/AikouTicket#readme",
"devDependencies": {
"@biomejs/biome": "^1.7.3",
"@types/node": "^20.14.0",
"@types/node": "^20.14.1",
"@types/signale": "^1.4.7",
"@typescript-eslint/eslint-plugin": "^7.12.0",
"@typescript-eslint/parser": "^7.12.0",
Expand Down
149 changes: 60 additions & 89 deletions src/events/client/InteractionCreate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ export default class InteractionCreate extends Event {
const config = await TicketManager.readConfigFile();
const supportRoles = config.supportRoles;

const memberRoles = interaction.member.roles.cache.map((role: any) => role.id);
const memberRoles = interaction.member.roles.cache.map((role) => role.id);
const isSupport = memberRoles.some((role) => supportRoles.includes(role));

if (!isSupport) {
Expand All @@ -132,7 +132,6 @@ export default class InteractionCreate extends Event {
}

const userName = interaction.user.username;

const embed = new EmbedBuilder()
.setColor('#00FF00')
.setTitle('Ticket Claimed')
Expand All @@ -148,48 +147,14 @@ export default class InteractionCreate extends Event {
ephemeral: false,
});

const components = interaction.message.components[0].components;
const claimButtonIndex = components.findIndex((component) => component.customId === 'claim-ticket');

if (claimButtonIndex !== -1) {
components[claimButtonIndex] = new ButtonBuilder()
.setCustomId('claim-ticket')
.setLabel('Claimed')
.setStyle(ButtonStyle.Secondary)
.setDisabled(true)
.setEmoji('🎫');

const unclaimButton = new ButtonBuilder()
.setCustomId('unclaim-ticket')
.setLabel('Unclaim')
.setStyle(ButtonStyle.Danger)
.setEmoji('⚠️');

components.push(unclaimButton);
}

const embeds = interaction.message.embeds;
if (embeds.length > 0) {
const existingEmbed = embeds[0];
const updatedEmbed = new EmbedBuilder(existingEmbed).setDescription(
`${existingEmbed.description}\n\n> **Claimed by**: ${userName}`,
);
interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
embeds: [updatedEmbed],
});
} else {
await interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
});
}
await this.updateClaimButton(interaction, userName, 'claimed');
}

private async handleUnclaimTicketButton(interaction: any): Promise<void> {
const config = await TicketManager.readConfigFile();
const supportRoles = config.supportRoles;

const memberRoles = interaction.member.roles.cache.map((role: any) => role.id);
const memberRoles = interaction.member.roles.cache.map((role) => role.id);
const isSupport = memberRoles.some((role) => supportRoles.includes(role));

if (!isSupport) {
Expand All @@ -200,37 +165,7 @@ export default class InteractionCreate extends Event {
return;
}

const components = interaction.message.components[0].components;
const claimButtonIndex = components.findIndex((component) => component.customId === 'claim-ticket');

if (claimButtonIndex !== -1) {
components[claimButtonIndex] = new ButtonBuilder()
.setCustomId('claim-ticket')
.setLabel('Claim')
.setStyle(ButtonStyle.Primary)
.setEmoji('🎫');
}

const unclaimButtonIndex = components.findIndex((component) => component.customId === 'unclaim-ticket');

if (unclaimButtonIndex !== -1) {
components.splice(unclaimButtonIndex, 1);
}
const userName = interaction.user.username;
const embeds = interaction.message.embeds;
if (embeds.length > 0) {
const existingEmbed = embeds[0];
const updatedDescription = existingEmbed.description.replace(`\n\n> **Claimed by**: ${userName}`, '');
const updatedEmbed = new EmbedBuilder(existingEmbed).setDescription(updatedDescription);
interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
embeds: [updatedEmbed],
});
} else {
await interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
});
}
await this.updateClaimButton(interaction, interaction.user.username, 'unclaimed');
}

private async handleCloseTicketButton(interaction: any): Promise<void> {
Expand All @@ -239,18 +174,13 @@ export default class InteractionCreate extends Event {
const closeTicketStaffOnly = config.closeTicketStaffOnly;

const memberRoles = interaction.member.roles.cache.map((role: any) => role.id);
const isSupport = memberRoles.some((role) => supportRoles.includes(role));
const isSupport = memberRoles.some((role: any) => supportRoles.includes(role));

if (closeTicketStaffOnly) {
if (!isSupport) {
await interaction.reply({
content: 'You do not have permission to close this ticket.',
ephemeral: true,
});
return;
}
} else if (interaction.channel.topic?.includes(interaction.user.id)) {
await this.handleConfirmCloseTicketButton(interaction);
if (closeTicketStaffOnly && !isSupport) {
await interaction.reply({
content: 'You do not have permission to close this ticket.',
ephemeral: true,
});
return;
}

Expand Down Expand Up @@ -297,7 +227,7 @@ export default class InteractionCreate extends Event {
const transcriptsFilter = (i: MessageComponentInteraction): boolean => i.customId === 'transcripts-ticket';
const transcriptsCollector = interaction.channel.createMessageComponentCollector({
filter: transcriptsFilter,
time: 0,
time: 60000,
});

transcriptsCollector.on('collect', async (i) => {
Expand All @@ -319,7 +249,6 @@ export default class InteractionCreate extends Event {

private async handleConfirmCloseTicketButton(interaction: any): Promise<void> {
const channel = interaction.channel as TextChannel;

const categoryLabelMatch = channel.topic?.match(/Ticket Type: (.+)/);
const categoryLabel = categoryLabelMatch ? categoryLabelMatch[1] : 'unknown';

Expand All @@ -343,13 +272,8 @@ export default class InteractionCreate extends Event {

collector.on('collect', async (message) => {
shouldCloseTicket = true;

try {
reason = message.content;
await LogsManager.logTicketDeletion(interaction, this.client, interaction.user.username, categoryLabel, channel, reason);
} catch (error) {
this.client.logger.error('Failed to log ticket deletion:', error);
}
reason = message.content;
await LogsManager.logTicketDeletion(interaction, this.client, interaction.user.username, categoryLabel, channel, reason);
});

collector.on('end', async () => {
Expand Down Expand Up @@ -430,4 +354,51 @@ export default class InteractionCreate extends Event {
});
}
}

private async updateClaimButton(interaction: any, userName: string, action: string): Promise<void> {
const components = interaction.message.components[0].components;
const claimButtonIndex = components.findIndex((component) => component.customId === 'claim-ticket');
const isClaimed = action === 'claimed';

if (claimButtonIndex !== -1) {
components[claimButtonIndex] = new ButtonBuilder()
.setCustomId('claim-ticket')
.setLabel(isClaimed ? 'Claimed' : 'Claim')
.setStyle(isClaimed ? ButtonStyle.Secondary : ButtonStyle.Primary)
.setDisabled(isClaimed)
.setEmoji('🎫');

if (isClaimed) {
const unclaimButton = new ButtonBuilder()
.setCustomId('unclaim-ticket')
.setLabel('Unclaim')
.setStyle(ButtonStyle.Danger)
.setEmoji('⚠️');

components.push(unclaimButton);
} else {
const unclaimButtonIndex = components.findIndex((component) => component.customId === 'unclaim-ticket');
if (unclaimButtonIndex !== -1) {
components.splice(unclaimButtonIndex, 1);
}
}
}

const embeds = interaction.message.embeds;
if (embeds.length > 0) {
const existingEmbed = embeds[0];
const updatedDescription = isClaimed
? `${existingEmbed.description}\n\n> **Claimed by**: ${userName}`
: existingEmbed.description.replace(`\n\n> **Claimed by**: ${userName}`, '');
const updatedEmbed = new EmbedBuilder(existingEmbed).setDescription(updatedDescription);
await interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
embeds: [updatedEmbed],
});
} else {
await interaction.message.edit({
components: [new ActionRowBuilder<ButtonBuilder>().addComponents(components)],
});
}
}
}
134 changes: 70 additions & 64 deletions src/utils/LogsManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,21 @@ export class LogsManager {
client: Bot,
ticketChannel: GuildChannel,
): Promise<void> {
const logChannel = await LogsManager.getLogChannel(client);
const embed = LogsManager.createLogEmbed(
interaction,
interaction.user.username,
'#2FF200',
'🎟️ Ticket Created',
`- **Ticket Creator:** \n> ${interaction.user.username}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${
ticketChannel.name
} - ID: ${ticketChannel.id}) \n\n- **Category:** \n> ${categoryLabel}`,
);
await logChannel.send({ embeds: [embed] });
try {
const logChannel = await LogsManager.getLogChannel(client);
const embed = LogsManager.createLogEmbed(
interaction,
interaction.user.username,
'#2FF200',
'🎟️ Ticket Created',
`- **Ticket Creator:** \n> ${interaction.user.username}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${
ticketChannel.name
} - ID: ${ticketChannel.id}) \n\n- **Category:** \n> ${categoryLabel}`,
);
await logChannel.send({ embeds: [embed] });
} catch (error) {
client.logger.error('Failed to log ticket creation:', error);
}
}

public static async logTicketDeletion(
Expand All @@ -45,37 +49,28 @@ export class LogsManager {
ticketChannel: GuildChannel,
reason: string,
): Promise<void> {
const config = await LogsManager.readConfigFile();
const logChannel = await LogsManager.getLogChannel(client);

const embed = LogsManager.createLogEmbed(
interaction,
userName,
'#FF2400',
'⛔ Ticket Closed',
`- **Closed By:** \n> ${interaction.user.username}\n\n- **Ticket Creator:** \n> ${
interaction.user.username
}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${ticketChannel.name} - ID: ${
ticketChannel.id
}) \n\n- **Category:** \n> ${categoryLabel}\n\n- **Reason:** \n> ${reason}`,
);
try {
const config = await LogsManager.readConfigFile();
const logChannel = await LogsManager.getLogChannel(client);
const embed = LogsManager.createLogEmbed(
interaction,
userName,
'#FF2400',
'⛔ Ticket Closed',
`- **Closed By:** \n> ${interaction.user.username}\n\n- **Ticket Creator:** \n> ${
interaction.user.username
}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${ticketChannel.name} - ID: ${
ticketChannel.id
}) \n\n- **Category:** \n> ${categoryLabel}\n\n- **Reason:** \n> ${reason}`,
);

if (config.enableTranscripts) {
try {
const transcript = await discordTranscripts.createTranscript(ticketChannel as TextChannel);
await logChannel.send({
embeds: [embed],
files: [transcript],
});
} catch (error) {
client.logger.error('Failed to create transcript:', error);
await logChannel.send({
embeds: [embed],
content: 'Failed to create transcript.',
});
if (config.enableTranscripts) {
await LogsManager.sendTranscript(logChannel, embed, ticketChannel as TextChannel, client);
} else {
await logChannel.send({ embeds: [embed] });
}
} else {
await logChannel.send({ embeds: [embed] });
} catch (error) {
client.logger.error('Failed to log ticket deletion:', error);
}
}

Expand All @@ -85,32 +80,22 @@ export class LogsManager {
userName: string,
ticketChannel: GuildChannel,
): Promise<void> {
const config = await LogsManager.readConfigFile();
const logChannel = await LogsManager.getLogChannel(client);
const transcriptLogsChannel = (await client.channels.fetch(config.transcriptLogsChannelId)) as TextChannel;

const embed = LogsManager.createLogEmbed(
interaction,
userName,
'#3498DB',
'📝 Transcript Generated',
`- **Transcript Generated By:** \n> ${interaction.user.username}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${
ticketChannel.name
} - ID: ${ticketChannel.id})`,
);

try {
const transcript = await discordTranscripts.createTranscript(ticketChannel as TextChannel);
await transcriptLogsChannel.send({
embeds: [embed],
files: [transcript],
});
const config = await LogsManager.readConfigFile();
const transcriptLogsChannel = (await client.channels.fetch(config.transcriptLogsChannelId)) as TextChannel;
const embed = LogsManager.createLogEmbed(
interaction,
userName,
'#3498DB',
'📝 Transcript Generated',
`- **Transcript Generated By:** \n> ${interaction.user.username}\n\n- **Ticket:** \n> ${ticketChannel.toString()} \n> (${
ticketChannel.name
} - ID: ${ticketChannel.id})`,
);

await LogsManager.sendTranscript(transcriptLogsChannel, embed, ticketChannel as TextChannel, client);
} catch (error) {
client.logger.error('Failed to create transcript:', error);
await logChannel.send({
embeds: [embed],
content: 'Failed to create transcript.',
});
client.logger.error('Failed to log ticket transcript:', error);
}
}

Expand Down Expand Up @@ -157,4 +142,25 @@ export class LogsManager {
throw new Error(`Failed to read config file: ${error.message}`);
}
}

private static async sendTranscript(
logChannel: TextChannel,
embed: EmbedBuilder,
ticketChannel: TextChannel,
client: Bot,
): Promise<void> {
try {
const transcript = await discordTranscripts.createTranscript(ticketChannel);
await logChannel.send({
embeds: [embed],
files: [transcript],
});
} catch (error) {
client.logger.error('Failed to create transcript:', error);
await logChannel.send({
embeds: [embed],
content: 'Failed to create transcript.',
});
}
}
}

0 comments on commit 4a8d162

Please sign in to comment.