From 4f1a0379eab1fae2d3cc2ce085ce99769c01c358 Mon Sep 17 00:00:00 2001 From: UltraLionFr Date: Tue, 26 Aug 2025 14:41:28 +0200 Subject: [PATCH] chore: Ajout du transcript fonctionnel pour les tickets --- SlashCommand/tickets/alert.js | 6 +- SlashCommand/tickets/close.js | 37 ++----- events/clients/deploy-commands.js | 2 +- events/clients/transcript-server.js | 34 +++++++ handlers/ticketCloser.js | 144 +++++++++++++++++++++++++++ interactions/closeTicket.js | 8 +- package.json | 2 + transcripts/1409681989061312522.html | 27 +++++ transcripts/1409682431824494777.html | 51 ++++++++++ transcripts/1409683178918121575.html | 106 ++++++++++++++++++++ transcripts/1409683864762454198.html | 47 +++++++++ transcripts/1409684303440384081.html | 55 ++++++++++ transcripts/1409685755047186432.html | 1 + transcripts/1409686366085976114.html | 11 ++ transcripts/1409687084507201591.html | 7 ++ transcripts/1409687628491653254.html | 1 + transcripts/1409688266164277403.html | 48 +++++++++ transcripts/1409691379910836377.html | 78 +++++++++++++++ transcripts/1409692074542104587.html | 79 +++++++++++++++ transcripts/1409708563588317337.html | 33 ++++++ transcripts/1409708885333512313.html | 42 ++++++++ 21 files changed, 778 insertions(+), 41 deletions(-) create mode 100644 events/clients/transcript-server.js create mode 100644 handlers/ticketCloser.js create mode 100644 transcripts/1409681989061312522.html create mode 100644 transcripts/1409682431824494777.html create mode 100644 transcripts/1409683178918121575.html create mode 100644 transcripts/1409683864762454198.html create mode 100644 transcripts/1409684303440384081.html create mode 100644 transcripts/1409685755047186432.html create mode 100644 transcripts/1409686366085976114.html create mode 100644 transcripts/1409687084507201591.html create mode 100644 transcripts/1409687628491653254.html create mode 100644 transcripts/1409688266164277403.html create mode 100644 transcripts/1409691379910836377.html create mode 100644 transcripts/1409692074542104587.html create mode 100644 transcripts/1409708563588317337.html create mode 100644 transcripts/1409708885333512313.html diff --git a/SlashCommand/tickets/alert.js b/SlashCommand/tickets/alert.js index 833f81e..35a1a54 100644 --- a/SlashCommand/tickets/alert.js +++ b/SlashCommand/tickets/alert.js @@ -6,8 +6,9 @@ const { ActionRowBuilder, } = require('discord.js'); const { config, lang } = require('../../handlers/configLoader'); -const { getTicketByChannel, closeTicket } = require('../../handlers/database'); +const { getTicketByChannel } = require('../../handlers/database'); const { scheduleTicketClosure } = require('../../handlers/alertManager'); +const { closeTicketWithTranscript } = require('../../handlers/ticketCloser'); const ms = require('ms'); module.exports = { @@ -106,8 +107,7 @@ module.exports = { }); scheduleTicketClosure(interaction.channel, alertDuration, async () => { - closeTicket(interaction.channel.id); - await interaction.channel.delete().catch(() => {}); + await closeTicketWithTranscript(interaction.channel, interaction.user); }); }, }; diff --git a/SlashCommand/tickets/close.js b/SlashCommand/tickets/close.js index 2554db2..5c30fb5 100644 --- a/SlashCommand/tickets/close.js +++ b/SlashCommand/tickets/close.js @@ -1,10 +1,7 @@ -const { - SlashCommandBuilder, - EmbedBuilder, - MessageFlags, -} = require('discord.js'); -const { getTicketByChannel, closeTicket } = require('../../handlers/database'); -const { config, lang } = require('../../handlers/configLoader'); +const { SlashCommandBuilder, MessageFlags } = require('discord.js'); +const { getTicketByChannel } = require('../../handlers/database'); +const { lang } = require('../../handlers/configLoader'); +const { closeTicketWithTranscript } = require('../../handlers/ticketCloser'); module.exports = { data: new SlashCommandBuilder() @@ -21,32 +18,10 @@ module.exports = { }); } - closeTicket(interaction.channel.id); - await interaction.reply(lang.ticket.closing); - // Log fermeture - const logChannel = await interaction.client.channels - .fetch(config.logsChannel) - .catch(() => null); - if (logChannel) { - const embed = new EmbedBuilder() - .setTitle('🔒 Ticket fermé') - .addFields( - { name: 'Salon', value: `${interaction.channel.name}`, inline: true }, - { - name: 'Fermé par', - value: `${interaction.user.tag} (${interaction.user.id})`, - inline: true, - } - ) - .setColor(0xe74c3c) - .setTimestamp(); - logChannel.send({ embeds: [embed] }); - } - - setTimeout(() => { - interaction.channel.delete().catch(() => {}); + setTimeout(async () => { + await closeTicketWithTranscript(interaction.channel, interaction.user); }, 5000); }, }; diff --git a/events/clients/deploy-commands.js b/events/clients/deploy-commands.js index b845412..6d55a06 100644 --- a/events/clients/deploy-commands.js +++ b/events/clients/deploy-commands.js @@ -5,7 +5,7 @@ const logger = require('../../handlers/logger'); module.exports = { name: 'clientReady', once: true, - async execute(client) { + async execute() { const commands = getCommandsJSON(); const rest = new REST({ version: '10' }).setToken( process.env.DISCORD_TOKEN diff --git a/events/clients/transcript-server.js b/events/clients/transcript-server.js new file mode 100644 index 0000000..ad5b788 --- /dev/null +++ b/events/clients/transcript-server.js @@ -0,0 +1,34 @@ +const fs = require('fs'); +const path = require('path'); +const express = require('express'); + +module.exports = { + name: 'clientReady', + once: true, + async execute() { + const app = express(); + const transcriptsPath = path.join(__dirname, '../../transcripts'); + + app.use('/transcript', express.static(transcriptsPath)); + + app.get('/', (req, res) => { + res.send( + '✅ Serveur Transcript actif. Utilise /transcript/:id pour voir un ticket.' + ); + }); + + app.get('/transcript/:id', (req, res) => { + const file = path.join(transcriptsPath, `${req.params.id}.html`); + if (fs.existsSync(file)) { + res.sendFile(file); + } else { + res.status(404).send('❌ Transcript introuvable'); + } + }); + + const PORT = process.env.TRANSCRIPT_PORT || 3000; + app.listen(PORT, () => { + console.log(`🌐 Serveur Transcript dispo sur http://localhost:${PORT}`); + }); + }, +}; diff --git a/handlers/ticketCloser.js b/handlers/ticketCloser.js new file mode 100644 index 0000000..afbc1b3 --- /dev/null +++ b/handlers/ticketCloser.js @@ -0,0 +1,144 @@ +const fs = require('fs'); +const path = require('path'); +const { EmbedBuilder, StickerFormatType } = require('discord.js'); +const { closeTicket } = require('./database'); +const { config } = require('./configLoader'); + +async function generateTranscript(channel, user) { + const messages = await channel.messages.fetch({ limit: 100 }); + const sorted = [...messages.values()].reverse(); + + let html = ` + + + + Transcript - ${channel.name} + + + +

Transcript - ${channel.name}

+ `; + + for (const msg of sorted) { + const time = msg.createdAt.toLocaleString(); + const avatar = msg.author.displayAvatarURL(); + let content = msg.content || ''; + + // Mentions + if (content) { + content = content.replace(/<@!?(\d+)>/g, (match, id) => { + const u = channel.client.users.cache.get(id); + return u ? `@${u.username}` : match; + }); + + // Emojis custom + content = content.replace(//g, (match, id) => { + const isAnimated = match.startsWith('`; + }); + } + + html += ` +
+ + ${msg.author.tag} + (${time}) +
${content}
+ `; + + // Pièces jointes + if (msg.attachments.size > 0) { + msg.attachments.forEach((att) => { + if (att.contentType?.startsWith('image/')) { + html += `
`; + } else { + html += ``; + } + }); + } + + // Stickers + if (msg.stickers.size > 0) { + msg.stickers.forEach((sticker) => { + if (sticker.format === StickerFormatType.LOTTIE) { + html += `
[Sticker Lottie non supporté]
`; + return; + } + const url = `https://cdn.discordapp.com/stickers/${sticker.id}.png`; + html += ` +
+ ${sticker.name} +
${sticker.name}
+
+ `; + }); + } + + // Embeds + if (msg.embeds.length > 0) { + msg.embeds.forEach((embed) => { + html += `
`; + if (embed.title) html += `
${embed.title}
`; + if (embed.description) html += `
${embed.description}
`; + if (embed.url) + html += ``; + if (embed.thumbnail?.url) { + html += ``; + } + html += `
`; + }); + } + + html += `
`; + } + + html += ``; + + const transcriptsDir = path.join(__dirname, '../transcripts'); + if (!fs.existsSync(transcriptsDir)) fs.mkdirSync(transcriptsDir); + + const filePath = path.join(transcriptsDir, `${channel.id}.html`); + fs.writeFileSync(filePath, html, 'utf8'); + + // Logs + const logChannel = await channel.client.channels + .fetch(config.logsChannel) + .catch(() => null); + if (logChannel) { + const embed = new EmbedBuilder() + .setTitle('🔒 Ticket fermé') + .addFields( + { name: 'Salon', value: `${channel.name}`, inline: true }, + { + name: 'Fermé par', + value: user ? `${user.tag} (${user.id})` : 'Automatique', + inline: true, + }, + { + name: 'Transcript', + value: `http://localhost:3000/transcript/${channel.id}`, + } + ) + .setColor(0xe74c3c) + .setTimestamp(); + await logChannel.send({ embeds: [embed] }); + } +} + +async function closeTicketWithTranscript(channel, user) { + await generateTranscript(channel, user); + closeTicket(channel.id); + await channel.delete().catch(() => {}); +} + +module.exports = { closeTicketWithTranscript }; diff --git a/interactions/closeTicket.js b/interactions/closeTicket.js index 3e8414b..ca66277 100644 --- a/interactions/closeTicket.js +++ b/interactions/closeTicket.js @@ -1,6 +1,5 @@ -const { PermissionFlagsBits } = require('discord.js'); -const { closeTicket } = require('../handlers/database'); const { config, lang } = require('../handlers/configLoader'); +const { closeTicketWithTranscript } = require('../handlers/ticketCloser'); module.exports = { id: 'closeTicket', @@ -17,13 +16,10 @@ module.exports = { }); } - const channel = interaction.channel; - await interaction.reply({ content: lang.ticket.closing }); setTimeout(async () => { - closeTicket(channel.id); - await channel.delete().catch(() => {}); + await closeTicketWithTranscript(interaction.channel, interaction.user); }, 5000); }, }; diff --git a/package.json b/package.json index cbbb30e..d456e9e 100644 --- a/package.json +++ b/package.json @@ -17,8 +17,10 @@ "dependencies": { "@dotenvx/dotenvx": "^1.49.0", "chalk": "^4.1.2", + "discord-html-transcripts": "^3.2.0", "discord.js": "^14.22.1", "dotenv": "^17.2.1", + "express": "^5.1.0", "sql.js": "^1.13.0", "yaml": "^2.8.1" }, diff --git a/transcripts/1409681989061312522.html b/transcripts/1409681989061312522.html new file mode 100644 index 0000000..b8cbba3 --- /dev/null +++ b/transcripts/1409681989061312522.html @@ -0,0 +1,27 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ Bot Local#7738 + (26/08/2025 01:32:57) : +
🎟️ Bonjour <@281113457833672706>, un membre du staff va bientôt te répondre.
+
+ +
+ Bot Local#7738 + (26/08/2025 01:34:19) : +
⏳ Fermeture du ticket dans 5 secondes...
+
+ \ No newline at end of file diff --git a/transcripts/1409682431824494777.html b/transcripts/1409682431824494777.html new file mode 100644 index 0000000..eb4e53c --- /dev/null +++ b/transcripts/1409682431824494777.html @@ -0,0 +1,51 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ Bot Local#7738 + (26/08/2025 01:34:44) : +
🎟️ Bonjour <@281113457833672706>, un membre du staff va bientôt te répondre.
+
+ +
+ ultralion + (26/08/2025 01:34:47) : +
https://tenor.com/view/frank-leboeuf-salut-c%27est-frank-leboeuf-vendez-votre-voiture-pub-gif-17219703131657425039
+
+ +
+ ultralion + (26/08/2025 01:34:50) : +
[Embed/Média]
+
+ +
+ ultralion + (26/08/2025 01:34:52) : +
[Embed/Média]
+
+ +
+ ultralion + (26/08/2025 01:34:54) : +
+
+ +
+ Bot Local#7738 + (26/08/2025 01:34:57) : +
⏳ Fermeture du ticket dans 5 secondes...
+
+ \ No newline at end of file diff --git a/transcripts/1409683178918121575.html b/transcripts/1409683178918121575.html new file mode 100644 index 0000000..557626c --- /dev/null +++ b/transcripts/1409683178918121575.html @@ -0,0 +1,106 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 01:37:41) +
+ 🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre. +
+
+
+ + ultralion + (26/08/2025 01:37:44) +
+ qsdqsd +
+
+
+ + ultralion + (26/08/2025 01:37:44) +
+ qsd +
+
+
+ + ultralion + (26/08/2025 01:37:45) +
+ qsd +
+
+
+ + ultralion + (26/08/2025 01:37:45) +
+ qsd +
+
+
+ + ultralion + (26/08/2025 01:37:49) +
+ https://tenor.com/view/congratulations-congrats-gif-25269017 +
+
+
+ + ultralion + (26/08/2025 01:37:51) +
+ +
+
+
+ + ultralion + (26/08/2025 01:37:53) +
+ +
+
+
+ + ultralion + (26/08/2025 01:37:56) +
+ +
+
+
+ + ultralion + (26/08/2025 01:37:59) +
+ <:KEKW:771561273619644417> +
+
+
+ + Bot Local#7738 + (26/08/2025 01:38:02) +
+ ⏳ Fermeture du ticket dans 5 secondes... +
+
\ No newline at end of file diff --git a/transcripts/1409683864762454198.html b/transcripts/1409683864762454198.html new file mode 100644 index 0000000..6f503a3 --- /dev/null +++ b/transcripts/1409683864762454198.html @@ -0,0 +1,47 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 01:40:24) +
+ 🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre. +
+
+
+ + ultralion + (26/08/2025 01:40:27) +
+ +
+ +
+ bubz +
bubz
+
+
+
+ + Bot Local#7738 + (26/08/2025 01:40:32) +
+ ⏳ Fermeture du ticket dans 5 secondes... +
+
\ No newline at end of file diff --git a/transcripts/1409684303440384081.html b/transcripts/1409684303440384081.html new file mode 100644 index 0000000..c3ba943 --- /dev/null +++ b/transcripts/1409684303440384081.html @@ -0,0 +1,55 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 01:42:09) +
+ 🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre. +
+
+
+ + ultralion + (26/08/2025 01:42:13) +
+ +
+ +
+ bubz +
bubz
+
+
+
+ + ultralion + (26/08/2025 01:42:16) +
+ +
+
+
+ + Bot Local#7738 + (26/08/2025 01:42:19) +
+ ⏳ Fermeture du ticket dans 5 secondes... +
+
\ No newline at end of file diff --git a/transcripts/1409685755047186432.html b/transcripts/1409685755047186432.html new file mode 100644 index 0000000..144f6d3 --- /dev/null +++ b/transcripts/1409685755047186432.html @@ -0,0 +1 @@ +ticket-ultralionThis is the start of #ticket-ultralion channel. Bonjour UltraLion, un membre du staff va bientôt te répondre.https://tenor.com/view/cat-sticker-line-sticker-bye-sticker-goodbye-sticker-hand-wave-gif-2765574846828776801 Fermeture du ticket dans 5 secondes...
Exporté 6 messages
\ No newline at end of file diff --git a/transcripts/1409686366085976114.html b/transcripts/1409686366085976114.html new file mode 100644 index 0000000..3d1771a --- /dev/null +++ b/transcripts/1409686366085976114.html @@ -0,0 +1,11 @@ +ticket-ultralionThis is the start of #ticket-ultralion channel. Bonjour UltraLion, un membre du staff va bientôt te répondre.https://tenor.com/view/spongebob-cant-wait-impatient-anxious-eagerly-gif-12243170376163390127 Fermeture du ticket dans 5 secondes...
Exporté 7 messages
+
+ Hmmmm +
Hmmmm
+
+ +
+ danse +
danse
+
+ \ No newline at end of file diff --git a/transcripts/1409687084507201591.html b/transcripts/1409687084507201591.html new file mode 100644 index 0000000..fadb6f2 --- /dev/null +++ b/transcripts/1409687084507201591.html @@ -0,0 +1,7 @@ +ticket-ultralionThis is the start of #ticket-ultralion channel. Bonjour UltraLion, un membre du staff va bientôt te répondre. + bubz +
bubz
+ + " timestamp="2025-08-25T23:53:16.144Z" edited="false" highlight="false" profile="281113457833672706">
Fermeture du ticket dans 5 secondes...
Exporté 3 messages
\ No newline at end of file diff --git a/transcripts/1409687628491653254.html b/transcripts/1409687628491653254.html new file mode 100644 index 0000000..fa8a766 --- /dev/null +++ b/transcripts/1409687628491653254.html @@ -0,0 +1 @@ +ticket-ultralionThis is the start of #ticket-ultralion channel. Bonjour UltraLion, un membre du staff va bientôt te répondre. Fermeture du ticket dans 5 secondes...
Exporté 3 messages
\ No newline at end of file diff --git a/transcripts/1409688266164277403.html b/transcripts/1409688266164277403.html new file mode 100644 index 0000000..23075fe --- /dev/null +++ b/transcripts/1409688266164277403.html @@ -0,0 +1,48 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 01:57:53) +
+ 🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre. +
+
+
+ + ultralion + (26/08/2025 01:57:59) +
+ +
+ +
+ bubz +
bubz
+
+
+
+ + Bot Local#7738 + (26/08/2025 01:58:02) +
+ ⏳ Fermeture du ticket dans 5 secondes... +
+
\ No newline at end of file diff --git a/transcripts/1409691379910836377.html b/transcripts/1409691379910836377.html new file mode 100644 index 0000000..83ac7f4 --- /dev/null +++ b/transcripts/1409691379910836377.html @@ -0,0 +1,78 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 02:10:16) +
+ 🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre. +
+
+
+ + ultralion + (26/08/2025 02:10:21) +
+ https://tenor.com/view/spongebob-cant-wait-impatient-anxious-eagerly-gif-12243170376163390127 +
+
+
+ + ultralion + (26/08/2025 02:10:23) +
+ +
+ +
+ KEK +
KEK
+
+
+
+ + ultralion + (26/08/2025 02:10:27) +
+ +
+ +
+ bubz +
bubz
+
+
+
+ + ultralion + (26/08/2025 02:10:29) +
+ +
+
+
+ + Bot Local#7738 + (26/08/2025 02:10:32) +
+ ⏳ Fermeture du ticket dans 5 secondes... +
+
\ No newline at end of file diff --git a/transcripts/1409692074542104587.html b/transcripts/1409692074542104587.html new file mode 100644 index 0000000..6d633f8 --- /dev/null +++ b/transcripts/1409692074542104587.html @@ -0,0 +1,79 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 02:13:01) +
🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre.
+
+ + ultralion + (26/08/2025 02:13:05) +
qsdqsd
+
+ + ultralion + (26/08/2025 02:13:05) +
qsd
+
+ + ultralion + (26/08/2025 02:13:05) +
qs
+
+ + ultralion + (26/08/2025 02:13:05) +
dqs
+
+ + ultralion + (26/08/2025 02:13:06) +
d
+
+ + ultralion + (26/08/2025 02:13:06) +
qsd
+
+ + ultralion + (26/08/2025 02:13:07) +
qsdqsdqsdqsdqsd
+
+ + ultralion + (26/08/2025 02:13:10) +
+
+ + ultralion + (26/08/2025 02:13:12) + +
+ bubz +
bubz
+
+
+
+ + Bot Local#7738 + (26/08/2025 02:13:15) +
⏳ Fermeture du ticket dans 5 secondes...
\ No newline at end of file diff --git a/transcripts/1409708563588317337.html b/transcripts/1409708563588317337.html new file mode 100644 index 0000000..667213f --- /dev/null +++ b/transcripts/1409708563588317337.html @@ -0,0 +1,33 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 03:18:32) +
<@&1066466155574857884>
+
🎟️ Facturation
👤 Ouvert par: <@281113457833672706> + +**ID de facture** : qsdqsd +**Explique ton problème** : qsdqsd
+
+ + Bot Local#7738 + (26/08/2025 03:18:38) +
@ultralion
+
⏳ Une alerte de fermeture a été envoyée. Le ticket sera fermé si aucune réponse n’est donnée. Inactivité détectée depuis .
\ No newline at end of file diff --git a/transcripts/1409708885333512313.html b/transcripts/1409708885333512313.html new file mode 100644 index 0000000..09454d4 --- /dev/null +++ b/transcripts/1409708885333512313.html @@ -0,0 +1,42 @@ + + + + + Transcript - ticket-ultralion + + + +

Transcript - ticket-ultralion

+ +
+ + Bot Local#7738 + (26/08/2025 03:19:49) +
🎟️ Bonjour @ultralion, un membre du staff va bientôt te répondre.
+
+
+ + ultralion + (26/08/2025 03:19:53) +
+ +
+ bubz +
bubz
+
+
+
+ + Bot Local#7738 + (26/08/2025 03:19:56) +
⏳ Fermeture du ticket dans 5 secondes...
+
\ No newline at end of file