import type { BotStatus } from "@saas/shared"; import type { Pool } from "pg"; export interface StoredBotCredentials { id: string; tenantId: string; ownerUserId: string; discordBotId: string; displayName: string; tokenCiphertext: string; tokenIv: string; tokenTag: string; status: BotStatus; } const mapBotCredentials = ( row: Record, ): StoredBotCredentials => { return { id: String(row.id), tenantId: String(row.tenant_id), ownerUserId: String(row.owner_user_id), discordBotId: String(row.discord_bot_id), displayName: String(row.display_name), tokenCiphertext: String(row.token_ciphertext), tokenIv: String(row.token_iv), tokenTag: String(row.token_tag), status: row.status as BotStatus, }; }; export const listBotsToRestore = async ( pool: Pool, ): Promise => { const result = await pool.query( ` SELECT id, tenant_id, owner_user_id, discord_bot_id, display_name, token_ciphertext, token_iv, token_tag, status FROM bots WHERE status IN ('running', 'starting') ORDER BY created_at ASC `, ); return result.rows.map((row) => mapBotCredentials(row as Record), ); }; export const getBotCredentialsById = async ( pool: Pool, botId: string, ): Promise => { const result = await pool.query( ` SELECT id, tenant_id, owner_user_id, discord_bot_id, display_name, token_ciphertext, token_iv, token_tag, status FROM bots WHERE id = $1 LIMIT 1 `, [botId], ); if (!result.rows[0]) { return null; } return mapBotCredentials(result.rows[0] as Record); }; export const setBotStatusById = async ( pool: Pool, botId: string, status: BotStatus, lastError: string | null = null, ): Promise => { await pool.query( ` UPDATE bots SET status = $2, last_error = $3, updated_at = NOW() WHERE id = $1 `, [botId, status, lastError], ); }; export const insertRuntimeEvent = async ( pool: Pool, input: { tenantId: string; botId: string; level: "info" | "warn" | "error"; message: string; metadata?: unknown; }, ): Promise => { await pool.query( ` INSERT INTO bot_runtime_events (tenant_id, bot_id, level, message, metadata) VALUES ($1, $2, $3, $4, $5::jsonb) `, [ input.tenantId, input.botId, input.level, input.message, JSON.stringify(input.metadata ?? {}), ], ); };