chore: code qual sweep idk if everything still works but it should i think
@@ -0,0 +1,31 @@
+import client, { rest } from "@/discord"; +import config from "../src/config.ts"; +import { codeBlock, Events, Routes } from "discord.js"; + +await client.login(config.discord.token) + +client.on(Events.ClientReady, async (client) => { + const servers = await client.guilds.fetch() + console.log(`You are in ${servers.size} servers!`) + for (const [id, server] of servers) { + console.log(id, server.name) + + const channels = await client.guilds.cache.get(id)?.channels.fetch() + if (!channels) continue + for (const [id, channel] of channels) { + // console.log(`\t${id}, ${channel?.name}`) + + if (id === "1478940790112915486") { + if (!channel?.isSendable()) continue + + // await channel.send("??? that returned an error but the message did go through good job discord") + + const messages = await channel.messages.fetch({ limit: 100 }) + for (const [id, message] of messages) { + console.log(`${message.author.tag} ${message.content}`) + } + } + } + + } +})
@@ -26,5 +26,4 @@ startTicketWatcher(client);
}); export default client; - -export const rest = new REST({ version: "9" }).setToken(config.discord.token); +export const rest = new REST({ version: "10" }).setToken(config.discord.token);
@@ -1,6 +1,7 @@
import { type BaseInteraction, type Client, Events } from "discord.js"; import { commands } from "../handlers/interactions"; +import { parseComponentId } from "@/utils/discord/components"; import { loggers } from "@/utils/logging"; const logger = loggers.interactions;@@ -18,14 +19,21 @@ logger.error(
error, `there was an error while executing ${interaction.commandName}`, ); - interaction.deferReply({ flags: ["Ephemeral"] }); - await interaction.followUp({ - content: "there was an error while executing this command!", - flags: ["Ephemeral"], - }); + + if (interaction.deferred || interaction.replied) { + await interaction.followUp({ + content: "there was an error while executing this command!", + flags: ["Ephemeral"], + }); + } else { + await interaction.reply({ + content: "there was an error while executing this command!", + flags: ["Ephemeral"], + }); + } } } else if (interaction.isButton()) { - const [commandName, ..._args] = interaction.customId.split(":"); + const { commandName } = parseComponentId(interaction.customId); const command = commands.get(commandName); if (!command || !command.buttonExecute) { return interaction.reply({@@ -40,13 +48,21 @@ logger.error(
error, `there was an error while executing button with customId ${interaction.customId}`, ); - await interaction.reply({ - content: "there was an error while executing this button command!", - flags: ["Ephemeral"], - }); + + if (interaction.deferred || interaction.replied) { + await interaction.followUp({ + content: "there was an error while executing this button command!", + flags: ["Ephemeral"], + }); + } else { + await interaction.reply({ + content: "there was an error while executing this button command!", + flags: ["Ephemeral"], + }); + } } } else if (interaction.isModalSubmit()) { - const [commandName, ..._args] = interaction.customId.split(":"); + const { commandName } = parseComponentId(interaction.customId); const command = commands.get(commandName); if (!command || !command.modalExecute) return; try {@@ -56,10 +72,18 @@ logger.error(
error, `there was an error while executing modal with customId ${interaction.customId}`, ); - await interaction.reply({ - content: "there was an error while executing this modal!", - flags: ["Ephemeral"], - }); + + if (interaction.deferred || interaction.replied) { + await interaction.followUp({ + content: "there was an error while executing this modal!", + flags: ["Ephemeral"], + }); + } else { + await interaction.reply({ + content: "there was an error while executing this modal!", + flags: ["Ephemeral"], + }); + } } } else if (interaction.isAutocomplete()) { const command = commands.get(interaction.commandName);@@ -73,7 +97,8 @@ `there was an error while executing autocomplete command for ${interaction.commandName}`,
); } } else if (interaction.isStringSelectMenu()) { - const command = commands.get(interaction.customId.split(":")[0]); + const { commandName } = parseComponentId(interaction.customId); + const command = commands.get(commandName); if (!command || !command.selectMenuExecute) return interaction.reply({ content: "couldn't find the associated command!",@@ -86,10 +111,18 @@ logger.error(
error, `there was an error while executing select menu with customId ${interaction.customId}`, ); - await interaction.reply({ - content: "there was an error while executing this select menu!", - flags: ["Ephemeral"], - }); + + if (interaction.deferred || interaction.replied) { + await interaction.followUp({ + content: "there was an error while executing this select menu!", + flags: ["Ephemeral"], + }); + } else { + await interaction.reply({ + content: "there was an error while executing this select menu!", + flags: ["Ephemeral"], + }); + } } } },
@@ -1,9 +1,11 @@
import config from "./config.ts"; import logger from "./utils/logging.ts"; +import { migrateDb } from "./database/index.ts"; import client from "./discord.ts"; async function main() { + await migrateDb(); await client.login(config.discord.token); }@@ -15,5 +17,4 @@ });
process.on("uncaughtException", (error) => { logger.error(error, "uncaught exception"); - console.error(error); });
@@ -1,24 +1,22 @@
-import { unlink, writeFile } from "node:fs/promises"; -import os from "node:os"; -import path from "node:path"; import { bugs, db } from "@/database"; import { getGuild } from "@/database/queries"; +import { parseComponentId } from "@/utils/discord/components"; import { AttachmentBuilder } from "discord.js"; import type { Client, ModalSubmitInteraction } from "discord.js"; import { eq, sql } from "drizzle-orm"; import { INPUT_IDS, - MODAL_IDS, VALIDATION, constructContainer, updateBugEmbed, } from "./_shared"; export async function handleNewBugModal( - client: Client, + _client: Client, interaction: ModalSubmitInteraction, ) { - if (!interaction.guildId) return; + const guildId = interaction.guildId; + if (!guildId) return; const title = interaction.fields.getTextInputValue(INPUT_IDS.TITLE); const description = interaction.fields.getTextInputValue(@@ -28,66 +26,55 @@ const affected = interaction.fields.getStringSelectValues(INPUT_IDS.AFFECTED);
const media = interaction.fields.getUploadedFiles(INPUT_IDS.MEDIA); await interaction.deferReply({ flags: ["Ephemeral"] }); - const [{ count }] = await db - .select({ count: sql<number>`COUNT(*)`.mapWith(Number) }) - .from(bugs) - .where(eq(bugs.guildId, interaction.guildId)); + const bug = await db.transaction(async (tx) => { + const [{ count }] = await tx + .select({ count: sql<number>`COUNT(*)`.mapWith(Number) }) + .from(bugs) + .where(eq(bugs.guildId, guildId)); - const bugNumber = count + 1; - const paddedNumber = bugNumber.toString().padStart(4, "0"); + const bugNumber = count + 1; - const bug = await db - .insert(bugs) - .values({ - guildId: interaction.guildId, - bugNumber: bugNumber, + return await tx + .insert(bugs) + .values({ + guildId: guildId, + bugNumber: bugNumber, - authorId: interaction.user.id, - status: "open", + authorId: interaction.user.id, + status: "open", - title: title, - description: description, - projects: [...affected], + title: title, + description: description, + projects: [...affected], - sent: false, - messageId: null, - threadId: null, + sent: false, + messageId: null, + threadId: null, - createdAt: new Date(), - updatedAt: new Date(), - closedAt: null, - }) - .returning(); + createdAt: new Date(), + updatedAt: new Date(), + closedAt: null, + }) + .returning(); + }); - const tempFiles: string[] = []; let attachment: AttachmentBuilder | undefined; - if (media) { - for (const [_, _attachment] of media) { - try { - const fileUrl = _attachment.url; - const fileName = _attachment.name; - if (!fileUrl) continue; - + if (media && media.size > 0) { + const [_, _attachment] = Array.from(media)[0]; + try { + const fileUrl = _attachment.url; + const fileName = _attachment.name; + if (fileUrl) { const res = await fetch(fileUrl); - if (!res.ok) continue; - - const arrayBuffer = await res.arrayBuffer(); - const buffer = Buffer.from(arrayBuffer); - - const safeName = fileName.replace(/[^a-zA-Z0-9._-]/g, "_"); - const tmpPath = path.join( - os.tmpdir(), - `${Date.now()}-${Math.random().toString(36).slice(2)}-${safeName}`, - ); - - await writeFile(tmpPath, buffer); - tempFiles.push(tmpPath); - - attachment = new AttachmentBuilder(buffer, { name: fileName }); - } catch (err) { - console.error("error processing uploaded file:", err); + if (res.ok) { + const arrayBuffer = await res.arrayBuffer(); + const buffer = Buffer.from(arrayBuffer); + attachment = new AttachmentBuilder(buffer, { name: fileName }); + } } + } catch (err) { + console.error("error processing uploaded file:", err); } }@@ -98,7 +85,7 @@ attachment,
); if (!container) return; - const { data, exists } = await getGuild(interaction.guildId); + const { data, exists } = await getGuild(guildId); if (!exists) return; const channelId = data.bug_channel_id;@@ -113,20 +100,13 @@ flags: ["IsComponentsV2"],
...(attachment ? { files: [attachment] } : {}), }); - for (const filePath of tempFiles) { - try { - await unlink(filePath); - } catch (err) { - console.error("error deleting temp file:", err); - } - } - // thread function truncateTitle(title: string, maxLength: number): string { return title.length > maxLength ? `${title.substring(0, maxLength)}...` : title; } + const paddedNumber = bug[0].bugNumber.toString().padStart(4, "0"); const threadName = `#${paddedNumber} ${truncateTitle(title, VALIDATION.THREAD_NAME_MAX_LENGTH)}`; const thread = await message.startThread({ name: threadName,@@ -151,10 +131,11 @@ export async function handleEditModal(
client: Client, interaction: ModalSubmitInteraction, ) { - if (!interaction.guildId) return; + const guildId = interaction.guildId; + if (!guildId) return; - const parts = interaction.customId.split(":"); - const id = parts[2]; + const { parts } = parseComponentId(interaction.customId); + const id = parts[1]; // bug:edit:ID -> parts is ["edit", "ID"] if (!id) { await interaction.reply({ content: "❌ Could not determine bug id.",@@ -208,7 +189,7 @@ });
return; } - const { data, exists } = await getGuild(interaction.guildId); + const { data, exists } = await getGuild(guildId); if (!exists) { await interaction.reply({ content:
@@ -1,17 +1,13 @@
-import config from "@/config"; -import { tsExact, tsRelative } from "@/roblox/profile"; -import { text } from "@/utils/discord/components"; import { type ChatInputCommandInteraction, type Client, - ContainerBuilder, SlashCommandBuilder, } from "discord.js"; import Uwuifier from "uwuifier"; const commandData = new SlashCommandBuilder() .setName("uwuify") - .setDescription(`ok`) + .setDescription("ok") .addStringOption((option) => option .setName("text")
@@ -113,7 +113,6 @@ const err: ApiError = isApiError(body)
? body : errorFromStatus(res.status, res.statusText); - console.log(res); return [null, err]; }@@ -129,8 +128,10 @@ userId: string,
): Promise<Result<UserRestrictionLog[]>> { const allLogs: UserRestrictionLog[] = []; let pageToken = ""; + let pages = 0; + const MAX_PAGES = 50; - while (true) { + while (pages < MAX_PAGES) { const filter = encodeURIComponent( `place == '' && user == 'users/${userId}'`, );@@ -143,6 +144,7 @@ allLogs.push(...data.logs);
if (!data.nextPageToken) break; pageToken = data.nextPageToken; + pages++; } return [allLogs, null];