import userAuth from "@/src/functions/backend/auth/user-auth"; import grabBotFile from "@/src/functions/backend/db/bot-files/grab-bot-file"; import grabBotFileQuotaBytes, { grabBotFileQuotaMb, } from "@/src/functions/backend/db/bot-files/grab-bot-file-quota-bytes"; import grabStorageUsage from "@/src/functions/backend/db/bot-files/grab-storage-usage"; import listBotFiles, { listBotFolders } from "@/src/functions/backend/db/bot-files/list-bot-files"; import grabUserBot from "@/src/functions/backend/db/bots/grab-user-bot"; import grabUserWorkspace from "@/src/functions/backend/db/workspaces/grab-user-workspace"; import grabMediaURL from "@/src/functions/backend/media/grab-media-url"; import type { BotFileScopesPayload } from "@/src/types"; import safeErrorMessage from "@/src/utils/safe-error-message"; import type { BotFileScope } from "@/src/dict/bot-file-dict"; import type { APIResponseObject, BunextAPIRouteHandler } from "@moduletrace/bunext/types"; /** * A conversation's files: the bot's own, or a workspace's shared ones. * `?file_id=` returns one (for a message's file chip), else a folder's * files. Only a user who reaches the bot or workspace sees them. */ export const handler: BunextAPIRouteHandler> = async ({ req, }) => { try { if (req.method != "GET") { return { success: false, msg: `Method not allowed` }; } const { user } = await userAuth({ req }); if (!user?.logged_in_status || !user.id) { return { success: false, msg: `Unauthorized`, logoutUser: true }; } const url = new URL(req.url); const bot_id = Number(url.searchParams.get("bot_id")); const workspace_id = Number(url.searchParams.get("workspace_id")); const file_id = Number(url.searchParams.get("file_id")); const folder = url.searchParams.get("folder") || ""; const search = url.searchParams.get("search") || ""; const scope: { scope: BotFileScope; owner_id: number } | null = workspace_id ? (await grabUserWorkspace({ workspace_id, user_id: user.id })) ? { scope: "workspace", owner_id: workspace_id } : null : bot_id ? (await grabUserBot({ bot_id, user_id: user.id })) ? { scope: "bot", owner_id: bot_id } : null : null; if (!scope) { return { success: false, msg: `Not found.` }; } const scopes = [scope]; if (file_id) { const file = await grabBotFile({ scopes, file_id }); if (!file?.id) return { success: false, msg: `Not found.` }; return { success: true, singleRes: { files: [toPublicFile({ file })], folders: [], usage: { bytes: 0, files: 0 }, quota_bytes: 0, quota_mb: 0, }, }; } const [files, folders, usage, quota_bytes, quota_mb] = await Promise.all([ listBotFiles({ scopes, folder, search }), listBotFolders({ scopes }), grabStorageUsage(scope), grabBotFileQuotaBytes(), grabBotFileQuotaMb(), ]); return { success: true, singleRes: { files: files.map((file) => toPublicFile({ file })), folders, usage, quota_bytes, quota_mb, }, }; } catch (error: unknown) { return { success: false, msg: safeErrorMessage({ error }) }; } }; function toPublicFile({ file }: { file: BotFileWithMediaLite }) { const { media_url } = grabMediaURL({ media: { ...(file.media || {}), id: file.media_id } as any }); return { id: Number(file.id), name: file.name || "", path: file.path || "", size: Number(file.size) || 0, media_type: file.media_type || "document", purpose: file.purpose || "writing", scope: file.scope || "bot", owner_id: Number(file.owner_id) || 0, ingested_at: file.ingested_at ? Number(file.ingested_at) : undefined, ingest_error: file.ingest_error || undefined, created_at: Number(file.created_at) || 0, url: media_url || "", }; } type BotFileWithMediaLite = { id?: number | ""; media_id?: number | ""; name?: string; path?: string; size?: number | ""; media_type?: string; purpose?: string; scope?: string; owner_id?: number | ""; ingested_at?: number | ""; ingest_error?: string; created_at?: number | ""; media?: Record | null; };