all repos — stealth-developers @ 09081644ff2bf482c3c68319af758a28e1626a15

Revert "bot(perf): reduce ticket open time to ~500ms from 1.7s"

This reverts commit b67a9627edd74694e4a3fa47bc78c20d8c534299.
vi did:web:vt3e.cat
Fri, 03 Jul 2026 21:12:49 +0100
commit

09081644ff2bf482c3c68319af758a28e1626a15

parent

b67a9627edd74694e4a3fa47bc78c20d8c534299

M apps/bot/src/feats/guild-actor.tsapps/bot/src/feats/guild-actor.ts

@@ -33,7 +33,7 @@ avatar: member.user.avatarURL(),

}, }); - if (actor) GUILD_ACTORS.set(guild.id, actor.actor); + if (actor) GUILD_ACTORS.set(guild.id, actor); logger.info({ actor }, `upserted guild actor for ${guild.id} (${guild.name})`); return actor;
M apps/bot/src/feats/tickets/actions/comments.tsapps/bot/src/feats/tickets/actions/comments.ts

@@ -48,6 +48,7 @@ * @param reasons

* @param cleanup whether to delete the ticket channel immediately after closing * @returns */ + export async function addComment(ctx: TicketContext, comment: string) { const { actor, guild, ticket } = ctx;
M apps/bot/src/feats/tickets/actions/lifecycle.tsapps/bot/src/feats/tickets/actions/lifecycle.ts

@@ -18,6 +18,7 @@ ContainerBuilder,

type Guild, OverwriteType, PermissionFlagsBits, + TextChannel, TextDisplayBuilder, } from "discord.js"; import { upsertGuildActor } from "f/guild-actor";

@@ -26,7 +27,7 @@

import type { AnyUser } from "@/types"; import { client } from "@/client"; -import { PublicError, logger, upsertUser } from "@/lib"; +import { PublicError, getCategory, logger, upsertUser } from "@/lib"; import type { CreateTicketArgs, NewTicketContext, TicketContext } from "../types";

@@ -41,16 +42,21 @@

export async function createTicket( ctx: NewTicketContext, args?: CreateTicketArgs, -): Promise<{ channelId: string; publicId: string; setupPromise: Promise<void> }> { +): Promise<{ channelId: string; publicId: string }> { const isOnBehalf = !!args?.for; const publicId = randomUUID(); - const { dbGuild, creatorActor: creator } = ctx; + const dbGuild = ctx.dbGuild; + if (!dbGuild) throw new PublicError("Failed to create ticket: Guild not found in database"); - const subjectUser = isOnBehalf - ? (args?.dbFor ?? (args?.for ? await upsertUser(args.for, ctx.guild) : creator)) - : creator; + const moderators = await getModerators(dbGuild.id); + if (!moderators) throw new PublicError("Failed to create ticket: No moderators found"); + const creator = ctx.creatorActor; + if (!creator) throw new PublicError("Failed to create ticket: Creator user not found"); + + const subject = isOnBehalf ? args?.for : ctx.creatorUser; + const subjectUser = subject ? await upsertUser(subject, ctx.guild) : creator; if (!subjectUser) throw new PublicError("Failed to create ticket: Subject user not found"); if (isOnBehalf && !creator.moderator)

@@ -60,38 +66,41 @@ if (!dbGuild.ticketCategory)

throw new PublicError( "Ticket category is not set up in this guild. Please contact an administrator.", ); + const ticketCategory = await getCategory(dbGuild.ticketCategory); + let createdChannel: TextChannel | undefined = undefined; - const [txResult, canDm] = await Promise.all([ - Result.fromAsync(async () => { - return await db.transaction(async (tx) => { - const [maxTicket] = await tx - .select({ localId: tickets.localId }) - .from(tickets) - .where(eq(tickets.guildId, creator.guildId)) - .orderBy(desc(tickets.localId)) - .limit(1); + const canDm = await canDmUser(subject); - const localId = (maxTicket?.localId ?? 0) + 1; + let ticketId: string | undefined = undefined; - const [ticket] = await tx - .insert(tickets) - .values({ - id: publicId, - guildId: creator.guildId, - localId: localId, - status: "provisioning", - openedAt: new Date(), - openedBy: creator.id, - subject: subjectUser.id, - }) - .returning(); + const txResult = await Result.fromAsync(async () => { + return await db.transaction(async (tx) => { + const [maxTicket] = await tx + .select({ localId: tickets.localId }) + .from(tickets) + .where(eq(tickets.guildId, creator.guildId)) + .orderBy(desc(tickets.localId)) + .limit(1); - if (!ticket) throw new PublicError("Failed to add ticket to database, please try again."); - return { ticket, localId }; - }); - }), - canDmUser(isOnBehalf ? args?.for : ctx.creatorUser), - ]); + const localId = (maxTicket?.localId ?? 0) + 1; + + const [ticket] = await tx + .insert(tickets) + .values({ + id: publicId, + guildId: creator.guildId, + localId: localId, + status: "provisioning", + openedAt: new Date(), + openedBy: creator.id, + subject: subjectUser.id, + }) + .returning(); + + if (!ticket) throw new PublicError("Failed to add ticket to database, please try again."); + return { ticket, localId }; + }); + }); if (txResult.isErr()) { const error = txResult.unwrapErr();

@@ -105,182 +114,174 @@ throw new PublicError(message);

} const { ticket, localId } = txResult.unwrap(); - - const permissionOverwrites = [ - { - id: ctx.guild.id, - type: OverwriteType.Role, - deny: [PermissionFlagsBits.ViewChannel], - }, - { - id: client.user!.id, - type: OverwriteType.Member, - allow: [ - PermissionFlagsBits.ViewChannel, - PermissionFlagsBits.ManageChannels, - PermissionFlagsBits.CreatePrivateThreads, - ], - }, - { - id: subjectUser.discordId!, - type: OverwriteType.Member, - allow: [ - PermissionFlagsBits.ViewChannel, - PermissionFlagsBits.SendMessages, - PermissionFlagsBits.AttachFiles, - ], - }, - ]; + ticketId = ticket.id; - if (dbGuild.moderatorRole) { - permissionOverwrites.push({ - id: dbGuild.moderatorRole, - type: OverwriteType.Role, - allow: [ - PermissionFlagsBits.ViewChannel, - PermissionFlagsBits.ManageChannels, - PermissionFlagsBits.CreatePrivateThreads, + const setupResult = await Result.fromAsync(async () => { + const channel = await ctx.guild.channels.create({ + type: ChannelType.GuildText, + parent: ticketCategory, + name: `ticket-${String(localId).padStart(4, "0")}`, + permissionOverwrites: [ + { + id: ctx.guild.id, + type: OverwriteType.Role, + deny: [PermissionFlagsBits.ViewChannel], + }, + { + id: dbGuild.moderatorRole!, + type: OverwriteType.Role, + allow: [ + PermissionFlagsBits.ViewChannel, + PermissionFlagsBits.ManageChannels, + PermissionFlagsBits.CreatePrivateThreads, + ], + }, + { + id: client.user!.id, + type: OverwriteType.Member, + allow: [ + PermissionFlagsBits.ViewChannel, + PermissionFlagsBits.ManageChannels, + PermissionFlagsBits.CreatePrivateThreads, + ], + }, + { + id: subjectUser.discordId!, + type: OverwriteType.Member, + allow: [ + PermissionFlagsBits.ViewChannel, + PermissionFlagsBits.SendMessages, + PermissionFlagsBits.AttachFiles, + ], + }, ], }); - } - const channel = await ctx.guild.channels.create({ - type: ChannelType.GuildText, - parent: dbGuild.ticketCategory, - name: `ticket-${String(localId).padStart(4, "0")}`, - permissionOverwrites, - }); + if (!channel) throw new PublicError("Failed to create Discord channel."); + createdChannel = channel; - if (!channel) { - await Result.fromAsync(() => db.delete(tickets).where(eq(tickets.id, ticket.id))); - throw new PublicError("Failed to create Discord channel."); - } + const greeting = dbGuild.ticketGreeting; + const components = []; - const setupPromise = (async () => { - try { - const greeting = dbGuild.ticketGreeting; - const components = []; - - if (greeting) { - components.push( - new ContainerBuilder() - .setAccentColor(0x3a9027) - .addTextDisplayComponents( - new TextDisplayBuilder({ - content: greeting.replaceAll("{user}", `<@${subjectUser.discordId}>`), - }), - ) - .addActionRowComponents( - new ActionRowBuilder<ButtonBuilder>().addComponents( - TicketButtonPresets.claimTicketButton(publicId), - TicketButtonPresets.closeTicketButton(publicId), - ), - ), - ); - } - - if (!canDm) { - components.push( - new ContainerBuilder() - .setAccentColor(0xdf8e1d) - .addTextDisplayComponents( - new TextDisplayBuilder().setContent("## I can't DM you!"), - new TextDisplayBuilder().setContent( - [ - "You won't receive a notification once your ticket has been handled.", - `To check the outcome, you can use the \`/ticket view\` command with the ID \`${ticket.localId}\``, - "or, see all of your tickets with `/ticket manage list`.", - ].join(" "), - ), - ), - ); - } - + if (greeting) { components.push( new ContainerBuilder() .setAccentColor(0x3a9027) .addTextDisplayComponents( new TextDisplayBuilder({ - content: [ - "# Uploading Videos\n", - "You can either upload your video directly to this channel, or", - "you can use the button below to upload it directly to us, which", - "allows you to upload videos up to 2GB in size.", - ].join(" "), + content: greeting.replaceAll("{user}", `<@${subjectUser.discordId}>`), }), ) .addActionRowComponents( new ActionRowBuilder<ButtonBuilder>().addComponents( - TicketButtonPresets.uploadLink(publicId), + TicketButtonPresets.claimTicketButton(publicId), + TicketButtonPresets.closeTicketButton(publicId), ), ), ); + } - const sendGreeting = channel.send({ - components, - flags: ["IsComponentsV2"], + if (!canDm) { + components.push( + new ContainerBuilder() + .setAccentColor(0xdf8e1d) + .addTextDisplayComponents( + new TextDisplayBuilder().setContent("## I can't DM you!"), + new TextDisplayBuilder().setContent( + [ + "You won't receive a notification once your ticket has been handled.", + `To check the outcome, you can use the \`/ticket view\` command with the ID \`${ticket.localId}\``, + "or, see all of your tickets with `/ticket manage list`.", + ].join(" "), + ), + ), + ); + } + + components.push( + new ContainerBuilder() + .setAccentColor(0x3a9027) + .addTextDisplayComponents( + new TextDisplayBuilder({ + content: [ + "# Uploading Videos\n", + "You can either upload your video directly to this channel, or", + "you can use the button below to upload it directly to us, which", + "allows you to upload videos up to 2GB in size.", + ].join(" "), + }), + ) + .addActionRowComponents( + new ActionRowBuilder<ButtonBuilder>().addComponents( + TicketButtonPresets.uploadLink(publicId), + ), + ), + ); + + await channel.send({ + components, + flags: ["IsComponentsV2"], + }); + + await db + .update(tickets) + .set({ channelId: channel.id, status: "open" }) + .where(eq(tickets.id, ticket.id)); + + try { + const modThread = await channel.threads.create({ + name: `Moderator Thread - #${String(ticket.localId).padStart(4, "0")}`, + type: ChannelType.PrivateThread, + autoArchiveDuration: 10080, + reason: "Private discussion thread for moderators", }); - const createModeratorThread = async (): Promise<string | null> => { - try { - const modThread = await channel.threads.create({ - name: `Moderator Thread - #${String(ticket.localId).padStart(4, "0")}`, - type: ChannelType.PrivateThread, - autoArchiveDuration: 10080, - reason: "Private discussion thread for moderators", - }); + await modThread.send({ + content: `This thread is only visible to moderators, use it to discuss the ticket.`, + }); + + await channel.send({ + content: `Moderator thread created at ${modThread.url}`, + }); + + await db.update(tickets).set({ threadId: modThread.id }).where(eq(tickets.id, ticket.id)); + } catch (threadError) { + logger.error( + threadError, + `Failed to create private moderator thread for ticket ${ticket.id}`, + ); + } - await Promise.all([ - modThread.send({ - content: `This thread is only visible to moderators, use it to discuss the ticket.`, - }), - channel.send({ - content: `Moderator thread created at ${modThread.url}`, - }), - ]); + return channel; + }); + + if (setupResult.isErr()) { + if (createdChannel) { + await Result.fromAsync(() => (createdChannel as TextChannel).delete()); + } + + await Result.fromAsync(() => db.delete(tickets).where(eq(tickets.id, ticketId!))); - return modThread.id; - } catch (threadError) { - logger.error( - threadError, - `Failed to create private moderator thread for ticket ${ticket.id}`, - ); - return null; - } - }; + const error = setupResult.unwrapErr(); + const message = + error instanceof PublicError + ? `Failed to create ticket: ${error.message}` + : "There was an error creating the ticket."; - const [_, threadId] = await Promise.all([sendGreeting, createModeratorThread()]); + if (error instanceof Error) logger.error(error.stack, error.message); - db.update(tickets) - .set({ - channelId: channel.id, - status: "open", - threadId: threadId, - }) - .where(eq(tickets.id, ticket.id)); + throw new PublicError(message); + } - addParticipant( - ctx.guild.id, - { - actor: subjectUser, - ticketId: ticket.id, - role: "subject", - reason: "subject of ticket", - }, - true, - ) - .then() - .catch(); - } catch (error) { - await Result.fromAsync(() => channel.delete()); - await Result.fromAsync(() => db.delete(tickets).where(eq(tickets.id, ticket.id))); - logger.error(error, `failed background setup for ticket ${ticket.id}; deleted channel.`); - throw error; - } - })(); + await addParticipant(ctx.guild.id, { + actor: subjectUser, + ticketId: ticketId!, + role: "subject", + reason: "subject of ticket", + }); - console.timeEnd("createTicketExec"); - return { channelId: channel.id, publicId, setupPromise }; + const channel = setupResult.unwrap(); + return { channelId: channel.id, publicId }; } export async function triggerCloseTicket(user: AnyUser, guild: Guild, channelId: string) {

@@ -293,7 +294,7 @@

const ticket = await getTicketByChannelId(channelId); if (!ticket) throw new PublicError("Failed to close ticket: Ticket not found in database"); - return TicketModalPresets.close(ticket.id, Boolean(dbUser.actor.moderator)); + return TicketModalPresets.close(ticket.id, Boolean(dbUser.moderator)); } /**

@@ -391,7 +392,7 @@ );

if (messageRes.isErr()) { await addTicketComment({ - actorId: botActor.actor.id, + actorId: botActor.id, ticketId: result.id, content: `User has DMs closed, a notification was not sent.`, });

@@ -400,7 +401,7 @@

const logChannel = dbGuild.ticketLogChannel; if (!logChannel) { await addTicketComment({ - actorId: botActor.actor.id, + actorId: botActor.id, ticketId: result.id, content: `No log channel was found, a notification was not sent.`, });

@@ -418,7 +419,7 @@ );

if (message.isErr()) { await addTicketComment({ - actorId: botActor.actor.id, + actorId: botActor.id, ticketId: result.id, content: `Failed to send log message: ${message.unwrapErr()}`, });
M apps/bot/src/feats/tickets/buttons.tsapps/bot/src/feats/tickets/buttons.ts

@@ -18,6 +18,8 @@ import { TicketModalPresets } from "./modals";

export const newTicketButton = useGetTicketData.button("b-open-ticket", { async run(interaction, _, { actor, guild }) { + await interaction.deferReply({ flags: ["Ephemeral"] }); + if (!guild || !interaction.guild) { return errorMessage(interaction, "You must run this command in a guild"); } else if (!actor) {

@@ -34,31 +36,19 @@

const ticketResult = await Result.fromAsync(async () => func); if (ticketResult.isErr()) { const error = ticketResult.unwrapErr(); - return errorMessage( - interaction, - error instanceof PublicError - ? error.message - : "An unexpected error occurred while creating the ticket.", - ); - } - const { channelId, setupPromise } = ticketResult.unwrap(); + if (error instanceof PublicError) { + return errorMessage(interaction, error.message); + } else { + console.error(error); + return errorMessage(interaction, "An unexpected error occurred while creating the ticket."); + } + } - await interaction.reply({ + const { channelId } = ticketResult.unwrap(); + return interaction.editReply({ content: `Opened ticket <#${channelId}>.`, - flags: ["Ephemeral"], }); - - try { - await setupPromise; - } catch { - await interaction - .editReply({ - content: - "An error occurred during ticket setup, and the ticket was closed. Please try again.", - }) - .catch(() => {}); - } }, });
M apps/bot/src/feats/tickets/commands.tsapps/bot/src/feats/tickets/commands.ts

@@ -16,7 +16,7 @@ } from "@stealth-developers/db";

import { ActionRowBuilder, ButtonBuilder, ContainerBuilder, TextDisplayBuilder } from "discord.js"; import { ChannelType } from "discord.js"; -import { PublicError, errorMessage, getTextChannel, handleError, upsertUser } from "@/lib"; +import { PublicError, errorMessage, getTextChannel, handleError, logger, upsertUser } from "@/lib"; import { useGetTicketData } from "@/middleware"; import { getGuildActor } from "../guild-actor";

@@ -33,6 +33,7 @@

ticketCommand.subcommand("new", { description: "Open a new ticket.", async run(interaction, _, { actor, guild }) { + await interaction.deferReply({ flags: ["Ephemeral"] }); if (!guild || !interaction.guild) { return errorMessage(interaction, "You must run this command in a guild"); } else if (!actor) {

@@ -49,31 +50,19 @@

const ticketResult = await Result.fromAsync(async () => func); if (ticketResult.isErr()) { const error = ticketResult.unwrapErr(); - return errorMessage( - interaction, - error instanceof PublicError - ? error.message - : "An unexpected error occurred while creating the ticket.", - ); + + if (error instanceof PublicError) { + return errorMessage(interaction, error.message); + } else { + console.error(error); + return errorMessage(interaction, "An unexpected error occurred while creating the ticket."); + } } - const { channelId, setupPromise } = ticketResult.unwrap(); - - await interaction.reply({ + const { channelId } = ticketResult.unwrap(); + return interaction.editReply({ content: `Opened ticket <#${channelId}>.`, - flags: ["Ephemeral"], }); - - try { - await setupPromise; - } catch { - await interaction - .editReply({ - content: - "An error occurred during ticket setup, and the ticket was closed. Please try again.", - }) - .catch(() => {}); - } }, });

@@ -84,6 +73,8 @@ user: option.user("The user to open the ticket for", { required: true }),

reason: option.string("The reason for opening the ticket"), }, async run(interaction, args, { actor, guild }) { + await interaction.deferReply({ flags: ["Ephemeral"] }); + if (!guild || !interaction.guild) { return errorMessage(interaction, "You must run this command in a guild"); } else if (!actor) {

@@ -115,7 +106,7 @@ dbGuild: guild,

}, { for: args.user, - dbFor: forActor.actor, + dbFor: forActor, reason: args.reason, }, );

@@ -123,31 +114,19 @@

const ticketResult = await Result.fromAsync(async () => func); if (ticketResult.isErr()) { const error = ticketResult.unwrapErr(); - return errorMessage( - interaction, - error instanceof PublicError - ? error.message - : "An unexpected error occurred while creating the ticket.", - ); + + if (error instanceof PublicError) { + return errorMessage(interaction, error.message); + } else { + logger.error(error); + return errorMessage(interaction, "An unexpected error occurred while creating the ticket."); + } } - const { channelId, setupPromise } = ticketResult.unwrap(); - - await interaction.reply({ + const { channelId } = ticketResult.unwrap(); + return interaction.editReply({ content: `Opened ticket <#${channelId}>.`, - flags: ["Ephemeral"], }); - - try { - await setupPromise; - } catch { - await interaction - .editReply({ - content: - "An error occurred during ticket setup, and the ticket was closed. Please try again.", - }) - .catch(() => {}); - } }, });

@@ -156,12 +135,8 @@ description: "View a ticket",

options: { ticket: option.number("The ticket's ID", { required: true }), }, - async run(interaction, args, ctx) { - if (!ctx.user) return errorMessage(interaction, "Failed to fetch your profile"); - const activeUser = ctx.user as NonNullable<typeof ctx.user>; - - if (ctx.guild && ctx.actor) { - const { guild, actor } = ctx; + async run(interaction, args, { guild, actor, user }) { + if (guild && actor) { const ticket = await getTicketByGuild(guild.id, args.ticket); if (!ticket) return errorMessage(interaction, `Ticket with ID ${args.ticket} not found.`);

@@ -170,13 +145,19 @@ return errorMessage(interaction, "You don't have permission to view this ticket.");

const container = actions.getTicketContainer(ticket, !actor.moderator); await interaction.reply({ components: [container], flags: ["Ephemeral", "IsComponentsV2"] }); - } else if (activeUser) { - const ticket = await getTicketByUser(activeUser.id, args.ticket); + return; + } + + if (user) { + const ticket = await getTicketByUser(user.id, args.ticket); if (!ticket) return errorMessage(interaction, `Ticket with ID ${args.ticket} not found.`); const container = actions.getTicketContainer(ticket, false); await interaction.reply({ components: [container], flags: ["Ephemeral", "IsComponentsV2"] }); + return; } + + await errorMessage(interaction, "We couldn't find a ticket with that ID."); }, });

@@ -408,7 +389,7 @@

await actions.addParticipant( interaction.guild.id, { - actor: participant.actor, + actor: participant, ticketId: ticket.id, role: "participant", reason: args.reason,

@@ -723,7 +704,7 @@

const dbActor = await upsertUser(user, interaction.guild); if (!dbActor) return errorMessage(interaction, "Failed to add moderator."); - await editActor(dbActor.actor.id, { + await editActor(dbActor.id, { moderator: true, });

@@ -749,7 +730,7 @@

const dbActor = await upsertUser(user, interaction.guild); if (!dbActor) return errorMessage(interaction, "Failed to remove moderator."); - await editActor(dbActor.actor.id, { + await editActor(dbActor.id, { moderator: false, });
M apps/bot/src/feats/tickets/listeners.tsapps/bot/src/feats/tickets/listeners.ts

@@ -80,9 +80,9 @@

const authorDb = await upsertUser(message.author, message.guild); if (!authorDb) return; - const isModerator = authorDb.actor.moderator; + const isModerator = authorDb.moderator; const isBot = message.author.bot; - const isSubject = authorDb?.actor.discordId === ticket.subjectActor?.discordId; + const isSubject = authorDb?.discordId === ticket.subjectActor?.discordId; const role = isModerator ? "moderator" : isBot ? "bot" : isSubject ? "subject" : "participant"; const subjectDiscordId = ticket.subjectActor?.discordId;

@@ -165,7 +165,7 @@ const messageResult = await Result.fromAsync(

await createTicketMessageWithAttachments({ id: messageId, ticketId: ticket.id, - actorId: authorDb.actor.id, + actorId: authorDb.id, messageId: message.id, content: anonymisedContent, actorRole: role,

@@ -182,11 +182,11 @@ })),

}), ); - if (authorDb.actor.id === ticket?.claimedBy) { + if (authorDb.id === ticket?.claimedBy) { await editTicket(ticket.id, { lastClaimantActivityAt: new Date(), }); - } else if (authorDb.actor.id === ticket.subject) { + } else if (authorDb.id === ticket.subject) { await editTicket(ticket.id, { lastSubjectActivityAt: new Date(), });
M apps/bot/src/lib/db.tsapps/bot/src/lib/db.ts

@@ -1,5 +1,5 @@

import { upsertActor } from "@stealth-developers/db"; -import { Guild, GuildMember, PermissionsBitField, User } from "discord.js"; +import { Guild, GuildMember, User } from "discord.js"; import type { AnyUser } from "@/types";

@@ -23,10 +23,11 @@ displayName = nick || globalName || user.username;

avatar = member.avatar || user.avatar; if (member instanceof GuildMember) { - isModerator = member.permissions.has(PermissionsBitField.Flags.ModerateMembers); + isModerator = member.permissions.has("ModerateMembers"); } else if (member.permissions) { + const { PermissionsBitField } = await import("discord.js"); const perms = new PermissionsBitField(BigInt(member.permissions)); - isModerator = perms.has(PermissionsBitField.Flags.ModerateMembers); + isModerator = perms.has("ModerateMembers"); } } else { const user = input;

@@ -35,15 +36,10 @@ username = user.username;

displayName = user.displayName; avatar = user.avatar; - const cachedMember = guild.members.cache.get(user.id); - if (cachedMember) { - isModerator = cachedMember.permissions.has(PermissionsBitField.Flags.ModerateMembers); - } else { - try { - const member = await guild.members.fetch(user.id); - isModerator = member.permissions.has(PermissionsBitField.Flags.ModerateMembers); - } catch {} - } + try { + const member = await guild.members.fetch(user.id); + isModerator = member.permissions.has("ModerateMembers"); + } catch {} } return upsertActor({
M apps/bot/src/middleware/index.tsapps/bot/src/middleware/index.ts

@@ -1,26 +1,48 @@

import { HaltExecution } from "@purrkit/router"; import { Result } from "@sapphire/framework"; -import { getTicketByChannelId, getTicketByGuild, getTicketById } from "@stealth-developers/db"; +import { + getTicketByChannelId, + getTicketByGuild, + getTicketById, + upsertGuild, +} from "@stealth-developers/db"; import { kitten } from "@/client"; import { getTextChannel, logger, upsertUser } from "@/lib"; const base = kitten.builder(); -export const useGetData = base.use(async (interaction) => { - if (!interaction.guild) return {}; +export const useGetData = base + .use(async (interaction) => { + if (!interaction.guild) return {}; - const memberOrUser = interaction.member ?? interaction.user; - const result = await upsertUser(memberOrUser, interaction.guild); + const user = await upsertUser(interaction.user, interaction.guild); + if (!user) throw new HaltExecution("Failed to add you to the database. Please try again."); - if (!result) throw new HaltExecution("Failed to add you to the database. Please try again."); + return { user }; + }) + .use(async (interaction) => { + if (!interaction.guild) return {}; - return { - user: result.user, - actor: result.actor, - guild: result.guild, - }; -}); + const actor = await upsertUser(interaction.user, interaction.guild); + if (!actor) throw new HaltExecution("Failed to add you to the database. Please try again."); + + return { actor }; + }) + .use(async (interaction) => { + if (!interaction.guild) return {}; + + const guild = await upsertGuild({ + discordId: interaction.guild.id, + icon: interaction.guild.iconURL(), + name: interaction.guild.name, + }); + + if (!guild) + throw new HaltExecution("Failed to find your guild in the database. Please try again."); + + return { guild }; + }); export const useGetTicketData = useGetData.use(async (interaction, { guild }) => { if (interaction.isChatInputCommand()) {

@@ -34,7 +56,7 @@ }

if (interaction.isButton()) { const customId = interaction.customId; - if (customId.startsWith("ticket:")) { + if (customId.includes("ticket:")) { const ticketId = customId.split(":")[1]; if (ticketId) { const ticket = await getTicketById(ticketId);

@@ -52,8 +74,6 @@ }

return { ticket, ticketChannel: ticketChannelResult.unwrap() }; } - } else { - return {}; } }
M pkgs/db/src/utils/user.tspkgs/db/src/utils/user.ts

@@ -46,15 +46,13 @@ avatar: string | null;

}; moderator: boolean; }) { - const [dbGuild, dbUser] = await Promise.all([ - upsertGuild(data.guild), - upsertUser({ - id: data.user.discordId, - username: data.user.username, - displayName: data.user.displayName, - avatar: data.user.avatar, - }), - ]); + const dbGuild = await upsertGuild(data.guild); + const dbUser = await upsertUser({ + id: data.user.discordId, + username: data.user.username, + displayName: data.user.displayName, + avatar: data.user.avatar, + }); if (!dbGuild || !dbUser) { throw new Error("Failed to upsert guild or user");

@@ -85,13 +83,7 @@ },

}) .returning(); - if (!actor) throw new Error("Failed to insert actor"); - - return { - actor: actor, - user: dbUser, - guild: dbGuild, - }; + return actor; } export async function setActorPin(id: number, pin: string) {