import { prisma } from "../database/client"; import { decryptSecret, encryptSecret } from "../security/crypto"; import { AppError } from "../security/errors"; import { OpenSubtitlesClient } from "../opensubtitles/client"; const OS_ID = "opensubtitles"; export type OpenSubtitlesSettingsPublic = { configured: boolean; enabled: boolean; username: string; hasApiKey: boolean; hasPassword: boolean; }; export async function getOpenSubtitlesSettingsPublic(): Promise { const row = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } }); return { configured: !!(row?.apiKeyEnc && row.enabled), enabled: row?.enabled ?? true, username: row?.username ?? "", hasApiKey: !!row?.apiKeyEnc, hasPassword: !!row?.passwordEnc, }; } export async function upsertOpenSubtitlesSettings( sessionSecret: string, input: { apiKey?: string; username?: string; password?: string; enabled?: boolean; } ): Promise { const existing = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } }); const apiKeyTrim = input.apiKey?.trim(); if (!apiKeyTrim && !existing?.apiKeyEnc) { throw new AppError("INVALID_REQUEST", "API-key is verplicht", 400); } const apiKeyEnc = apiKeyTrim ? encryptSecret(apiKeyTrim, sessionSecret) : existing!.apiKeyEnc; const passwordEnc = input.password !== undefined ? input.password.trim() ? encryptSecret(input.password.trim(), sessionSecret) : null : existing?.passwordEnc ?? null; const username = input.username !== undefined ? input.username.trim() || null : existing?.username ?? null; await prisma.integrationSetting.upsert({ where: { id: OS_ID }, create: { id: OS_ID, apiKeyEnc, username, passwordEnc, enabled: input.enabled ?? true, }, update: { apiKeyEnc, username, passwordEnc, enabled: input.enabled ?? true, }, }); // Validate by searching a known movie (optional light check: login if creds) const client = await createOpenSubtitlesClientFromDb(sessionSecret); if (!client) throw new AppError("OPENSUBTITLES", "Kon client niet maken", 400); try { await client.search({ imdbId: "tt1375666", languages: "nl" }); } catch (err) { const message = err instanceof Error ? err.message : "OpenSubtitles test mislukt"; throw new AppError("OPENSUBTITLES", message, 400); } return getOpenSubtitlesSettingsPublic(); } export async function createOpenSubtitlesClientFromDb( sessionSecret: string ): Promise { const row = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } }); if (!row?.enabled || !row.apiKeyEnc) return null; const apiKey = decryptSecret(row.apiKeyEnc, sessionSecret); const password = row.passwordEnc ? decryptSecret(row.passwordEnc, sessionSecret) : undefined; return new OpenSubtitlesClient(apiKey, row.username ?? undefined, password); }