refac(bot): cryptographically secure keys !
vi did:web:vt3e.cat
Wed, 20 May 2026 05:55:48 +0100
4 files changed,
37 insertions(+),
88 deletions(-)
M
pkgs/bot/src/database/schema/tickets.ts
→
pkgs/bot/src/database/schema/tickets.ts
@@ -1,5 +1,6 @@
import { defineRelations, sql } from "drizzle-orm"; import { index, integer, sqliteTable, text } from "drizzle-orm/sqlite-core"; +import { randomUUID } from "node:crypto"; export const tickets = sqliteTable( "tickets",@@ -7,6 +8,10 @@ {
id: integer("id").primaryKey({ autoIncrement: true }), guildId: text("guild_id").notNull(), ticketNumber: integer("ticket_number"), + publicId: text("public_id") + .$defaultFn(() => randomUUID()) + .unique() + .notNull(), channelId: text("channel_id"),@@ -15,10 +20,7 @@ anonymousId: text("anonymous_id").notNull(),
claimedBy: text("claimed_by"), claimedAt: integer("claimed_at", { mode: "timestamp" }), - addedUsers: text("added_users", { mode: "json" }) - .$type<string[]>() - .default([]) - .notNull(), + addedUsers: text("added_users", { mode: "json" }).$type<string[]>().default([]).notNull(), type: text("type").notNull(), status: text("status", { enum: ["open", "closed", "archived"] })@@ -46,6 +48,7 @@ (t) => [
index("tickets_guild_idx").on(t.guildId), index("tickets_author_idx").on(t.authorId), index("tickets_status_idx").on(t.status), + index("tickets_public_id_idx").on(t.publicId), ], );@@ -55,6 +58,10 @@ {
id: integer("id").primaryKey({ autoIncrement: true }), ticketId: integer("ticket_id") .references(() => tickets.id, { onDelete: "cascade" }) + .notNull(), + publicId: text("public_id") + .$defaultFn(() => randomUUID()) + .unique() .notNull(), messageId: text("message_id"),
M
pkgs/bot/src/events/messageCreate.ts
→
pkgs/bot/src/events/messageCreate.ts
@@ -9,13 +9,7 @@ } from "discord.js";
import { and, eq } from "drizzle-orm"; import { nanoid } from "nanoid"; -import { - attachments, - db, - ticketMessages, - tickets, - userPreferences, -} from "@/database"; +import { attachments, db, ticketMessages, tickets, userPreferences } from "@/database"; import { getPublicUrl, s3 } from "@/utils/s3"; import { handleMessage } from "@/automod";@@ -44,9 +38,7 @@ // const allowed = await checkUwuifyRateLimit(message.author.id);
const allowed = true; if (!allowed) { const info = await getRateLimitInfo(message.author.id); - const resetTime = info?.resetAt - ? Math.floor(info.resetAt.getTime() / 1000) - : Date.now(); + const resetTime = info?.resetAt ? Math.floor(info.resetAt.getTime() / 1000) : Date.now(); try { await message.reply({@@ -67,14 +59,9 @@ try {
let replyReference = null; if (message.reference?.messageId) { try { - replyReference = await message.channel.messages.fetch( - message.reference.messageId, - ); + replyReference = await message.channel.messages.fetch(message.reference.messageId); } catch (error) { - logger.warn( - error, - "Failed to fetch referenced message for uwuified reply", - ); + logger.warn(error, "Failed to fetch referenced message for uwuified reply"); } }@@ -83,9 +70,7 @@ for (const attachment of message.attachments.values()) {
try { const resp = await fetch(attachment.url); if (!resp.ok) { - logger.warn( - `Failed to fetch attachment ${attachment.name}, status ${resp.status}`, - ); + logger.warn(`Failed to fetch attachment ${attachment.name}, status ${resp.status}`); continue; }@@ -101,9 +86,7 @@ }
message.delete(); - const contentParts = [ - `**<@${message.author.id}>**: ${uwuify(message.content)}`, - ]; + const contentParts = [`**<@${message.author.id}>**: ${uwuify(message.content)}`]; if (message.channel.isSendable()) { const sendOptions: {@@ -148,9 +131,7 @@
const triggers = ["grok is this true", "grok is this false "]; if ( message.channel.isSendable() && - triggers.some((trigger) => - message.content.toLowerCase().includes(trigger), - ) + triggers.some((trigger) => message.content.toLowerCase().includes(trigger)) ) { const chance = Math.random() * 100; if (chance < 25 || message.author.id === "470956810866655242") {@@ -161,10 +142,7 @@ message.channel.send("yeh");
} } - if ( - message.channel.isSendable() && - message.content.includes("gorque is this true") - ) { + if (message.channel.isSendable() && message.content.includes("gorque is this true")) { message.channel.send("oui 🇫🇷🥖"); }@@ -174,19 +152,14 @@ const ticket = db
.select() .from(tickets) .where( - and( - eq(tickets.channelId, message.channelId), - eq(tickets.guildId, message.guildId ?? ""), - ), + and(eq(tickets.channelId, message.channelId), eq(tickets.guildId, message.guildId ?? "")), ) .get(); if (!ticket) return; const isSystem = message.author.id === client.user.id; - const isModerator = await hasManagerPermissions( - message?.member as GuildMember, - ); + const isModerator = await hasManagerPermissions(message?.member as GuildMember); const authorType = isSystem ? "system" : isModerator ? "staff" : "user"; try {@@ -202,10 +175,7 @@ }
} catch {} try { - let anonymisedContent = message.content.replace( - new RegExp(ticket.authorId, "g"), - "Reporter", - ); + let anonymisedContent = message.content.replace(new RegExp(ticket.authorId, "g"), "Reporter"); for (const [index, userId] of (ticket.addedUsers || []).entries()) { anonymisedContent = anonymisedContent.replace(@@ -242,8 +212,7 @@
const formatSize = (size: number) => { if (size < 1024) return `${size} B`; if (size < 1024 * 1024) return `${(size / 1024).toFixed(2)} KB`; - if (size < 1024 * 1024 * 1024) - return `${(size / (1024 * 1024)).toFixed(2)} MB`; + if (size < 1024 * 1024 * 1024) return `${(size / (1024 * 1024)).toFixed(2)} MB`; return `${(size / (1024 * 1024 * 1024)).toFixed(2)} GB`; };@@ -286,11 +255,9 @@ if (!statusMessage) continue;
try { statusList[i].status = "uploading"; - await statusMessage.edit( - `**Attachment upload status**\n${renderBoard()}`, - ); + await statusMessage.edit(`**Attachment upload status**\n${renderBoard()}`); - const key = `${ticket.anonymousId}/${savedMessage.id}/${nanoid(8)}_${attachment.name}`; + const key = `${ticket.publicId}/${savedMessage.id}/${nanoid(8)}_${attachment.name}`; const file = s3.file(key); const resp = await fetch(attachment.url);@@ -313,18 +280,11 @@ });
statusList[i].status = "done"; statusList[i].url = publicUrl; - await statusMessage.edit( - `**Attachment upload status**\n${renderBoard()}`, - ); + await statusMessage.edit(`**Attachment upload status**\n${renderBoard()}`); } catch (error) { - logger.error( - error, - `Failed to upload attachment ${attachment.name}`, - ); + logger.error(error, `Failed to upload attachment ${attachment.name}`); statusList[i].status = "failed"; - await statusMessage.edit( - `**Attachment upload status**\n${renderBoard()}`, - ); + await statusMessage.edit(`**Attachment upload status**\n${renderBoard()}`); } } }
M
pkgs/bot/src/server/index.ts
→
pkgs/bot/src/server/index.ts
@@ -326,7 +326,7 @@ const safeName = String(fileName)
.replace(/[^a-zA-Z0-9._-]/g, "_") .slice(0, 200); - const key = `${ticket.anonymousId}/web/${nanoid(8)}_${safeName}`; + const key = `${ticket.publicId}/web/${nanoid(8)}_${safeName}`; const requestedMethod = (body?.method || "PUT").toUpperCase(); const allowed = ["PUT", "POST", "GET", "DELETE"];