From cc63dee71e78c947462b026f98107d3a4f3c5d8a Mon Sep 17 00:00:00 2001 From: Samuel Shuert Date: Fri, 3 Mar 2023 18:54:29 -0500 Subject: [PATCH] Development (#12) Co-authored-by: PineaFan Co-authored-by: pineafan Co-authored-by: PineappleFan Co-authored-by: Skyler --- .eslintignore | 2 +- src/api/index.ts | 4 ++-- src/commands/mod/purge.ts | 7 +++++-- src/commands/privacy.ts | 8 +++++--- src/context/messages/purgeto.ts | 8 ++++++-- src/events/guildDelete.ts | 10 ++++++++++ src/premium/createTranscript.ts | 8 ++++++-- src/utils/database.ts | 35 +++++++++++++++++++++++++++++---- 8 files changed, 66 insertions(+), 16 deletions(-) create mode 100644 src/events/guildDelete.ts diff --git a/.eslintignore b/.eslintignore index 45ad95d..d7b2f7f 100644 --- a/.eslintignore +++ b/.eslintignore @@ -1 +1 @@ -ClicksMigratingProblems/**/* +ClicksMigratingProblems/**/* \ No newline at end of file diff --git a/src/api/index.ts b/src/api/index.ts index 9676194..c8b7b14 100644 --- a/src/api/index.ts +++ b/src/api/index.ts @@ -152,7 +152,7 @@ const runServer = (client: NucleusClient) => { app.get("/transcript/:code/human", jsonParser, async function (req: express.Request, res: express.Response) { const code = req.params.code; if (code === undefined) return res.status(400).send("No code provided"); - const entry = await client.database.transcripts.read(code); + const entry = await client.database.transcripts.read(code, req.query.key as string, req.query.iv as string); if (entry === null) return res.status(404).send("Could not find a transcript by that code"); // Convert to a human readable format const data = client.database.transcripts.toHumanReadable(entry); @@ -164,7 +164,7 @@ const runServer = (client: NucleusClient) => { app.get("/transcript/:code", jsonParser, async function (req: express.Request, res: express.Response) { const code = req.params.code; if (code === undefined) return res.status(400).send("No code provided"); - const entry = await client.database.transcripts.read(code); + const entry = await client.database.transcripts.read(code, req.query.key as string, req.query.iv as string); if (entry === null) return res.status(404).send("Could not find a transcript by that code"); // Convert to a human readable format return res.status(200).send(entry); diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts index 8644e26..004f5ff 100644 --- a/src/commands/mod/purge.ts +++ b/src/commands/mod/purge.ts @@ -318,7 +318,8 @@ const callback = async (interaction: CommandInteraction): Promise => { )).map(message => message as Message); const newOut = await client.database.transcripts.createTranscript(messageArray, interaction, interaction.member as GuildMember); - const code = await client.database.transcripts.create(newOut); + const [code, key, iv] = await client.database.transcripts.create(newOut); + await interaction.editReply({ embeds: [ new EmojiEmbed() @@ -329,7 +330,9 @@ const callback = async (interaction: CommandInteraction): Promise => { ], components: [ new Discord.ActionRowBuilder().addComponents([ - new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript?code=${code}`), + + new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript/${code}?key=${key}&iv=${iv}`).setDisabled(!code), + ]) ] }); diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts index 46784f5..dcdebb1 100644 --- a/src/commands/privacy.ts +++ b/src/commands/privacy.ts @@ -179,9 +179,11 @@ const callback = async (interaction: CommandInteraction): Promise => { continue; } if (confirmation.success) { - client.database.guilds.delete(interaction.guild!.id); - client.database.history.delete(interaction.guild!.id); - client.database.notes.delete(interaction.guild!.id); + await client.database.guilds.delete(interaction.guild!.id); + await client.database.history.delete(interaction.guild!.id); + await client.database.notes.delete(interaction.guild!.id); + await client.database.transcripts.deleteAll(interaction.guild!.id); + nextFooter = "All data cleared"; continue; } else { diff --git a/src/context/messages/purgeto.ts b/src/context/messages/purgeto.ts index aef159b..616b085 100644 --- a/src/context/messages/purgeto.ts +++ b/src/context/messages/purgeto.ts @@ -193,7 +193,9 @@ const callback = async (interaction: MessageContextMenuCommandInteraction) => { ) )).map(message => message as Message); const transcript = await client.database.transcripts.createTranscript(messageArray, interaction, interaction.member as GuildMember); - const code = await client.database.transcripts.create(transcript); + + const [code, key, iv] = await client.database.transcripts.create(transcript); + await interaction.editReply({ embeds: [ new EmojiEmbed() @@ -204,7 +206,9 @@ const callback = async (interaction: MessageContextMenuCommandInteraction) => { ], components: [ new Discord.ActionRowBuilder().addComponents([ - new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript?code=${code}`), + + new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript/${code}?key=${key}&iv=${iv}`).setDisabled(!code), + ]) ] }); diff --git a/src/events/guildDelete.ts b/src/events/guildDelete.ts new file mode 100644 index 0000000..92af401 --- /dev/null +++ b/src/events/guildDelete.ts @@ -0,0 +1,10 @@ +import client, { NucleusClient } from '../utils/client.js' +import type { Guild } from 'discord.js' + +export const event = 'guildDelete' +export const callback = async (_client: NucleusClient, guild: Guild) => { + await client.database.guilds.delete(guild.id); + await client.database.history.delete(guild.id); + await client.database.notes.delete(guild.id); + await client.database.transcripts.deleteAll(guild.id); +} \ No newline at end of file diff --git a/src/premium/createTranscript.ts b/src/premium/createTranscript.ts index 67aed04..dd01a98 100644 --- a/src/premium/createTranscript.ts +++ b/src/premium/createTranscript.ts @@ -60,7 +60,9 @@ export default async function (interaction: CommandInteraction | MessageComponen const newOut = await client.database.transcripts.createTranscript(messages, interaction, member); - const code = await client.database.transcripts.create(newOut); + + const [code, key, iv] = await client.database.transcripts.create(newOut); + if(!code) return await interaction.reply({ embeds: [ new EmojiEmbed() @@ -86,7 +88,9 @@ export default async function (interaction: CommandInteraction | MessageComponen ], components: [ new ActionRowBuilder().addComponents([ - new ButtonBuilder().setLabel("View").setStyle(ButtonStyle.Link).setURL(`https://clicks.codes/nucleus/transcript/${code}`), + + 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) diff --git a/src/utils/database.ts b/src/utils/database.ts index 2e64320..06c41f0 100644 --- a/src/utils/database.ts +++ b/src/utils/database.ts @@ -22,6 +22,9 @@ const database = mongoClient.db(); const collectionOptions = { authdb: "admin" }; +const getIV = () => crypto.randomBytes(16); + + export class Guilds { guilds: Collection; defaultData: GuildConfig; @@ -203,15 +206,39 @@ export class Transcript { do { code = crypto.randomBytes(64).toString("base64").replace(/=/g, "").replace(/\//g, "_").replace(/\+/g, "-"); } while (await this.transcripts.findOne({ code: code })); + const key = crypto.randomBytes(32**2).toString("base64").replace(/=/g, "").replace(/\//g, "_").replace(/\+/g, "-").substring(0, 32); + const iv = getIV().toString("base64").replace(/=/g, "").replace(/\//g, "_").replace(/\+/g, "-"); + for(const message of transcript.messages) { + if(message.content) { + const encCipher = crypto.createCipheriv("AES-256-CBC", key, iv); + message.content = encCipher.update(message.content, "utf8", "base64") + encCipher.final("base64"); + } + } const doc = await this.transcripts.insertOne(Object.assign(transcript, { code: code }), collectionOptions); - if(doc.acknowledged) return code; - else return null; + if(doc.acknowledged) return [code, key, iv]; + else return [null, null, null]; } - async read(code: string) { + async read(code: string, key: string, iv: string) { // console.log("Transcript read") - return await this.transcripts.findOne({ code: code }); + const doc = await this.transcripts.findOne({ code: code }); + if(!doc) return null; + for(const message of doc.messages) { + if(message.content) { + const decCipher = crypto.createDecipheriv("AES-256-CBC", key, iv); + message.content = decCipher.update(message.content, "base64", "utf8") + decCipher.final("utf8"); + } + } + return doc; + } + + async deleteAll(guild: string) { + // console.log("Transcript delete") + const filteredDocs = await this.transcripts.find({ guild: guild }).toArray(); + for (const doc of filteredDocs) { + await this.transcripts.deleteOne({ code: doc.code }); + } } async createTranscript(messages: Message[], interaction: MessageComponentInteraction | CommandInteraction, member: GuildMember) {