135 lines
4 KiB
TypeScript
135 lines
4 KiB
TypeScript
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";
|
|
const DEFAULT_UA = "MediaCluster v1.3.2";
|
|
|
|
export async function isOpenSubtitlesEnabled(): Promise<boolean> {
|
|
const row = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } });
|
|
if (!row) return true;
|
|
return row.enabled;
|
|
}
|
|
|
|
export type OpenSubtitlesSettingsPublic = {
|
|
configured: boolean;
|
|
enabled: boolean;
|
|
username: string;
|
|
userAgent: string;
|
|
hasApiKey: boolean;
|
|
hasPassword: boolean;
|
|
comOk: boolean;
|
|
orgOk: boolean;
|
|
warning: string | null;
|
|
};
|
|
|
|
export async function getOpenSubtitlesSettingsPublic(): Promise<OpenSubtitlesSettingsPublic> {
|
|
const row = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } });
|
|
const enabled = row?.enabled ?? true;
|
|
return {
|
|
configured: enabled,
|
|
enabled,
|
|
username: row?.username ?? "",
|
|
userAgent: row?.userAgent?.trim() || DEFAULT_UA,
|
|
hasApiKey: !!row?.apiKeyEnc,
|
|
hasPassword: !!row?.passwordEnc,
|
|
comOk: false,
|
|
orgOk: false,
|
|
warning: null,
|
|
};
|
|
}
|
|
|
|
export async function upsertOpenSubtitlesSettings(
|
|
sessionSecret: string,
|
|
input: {
|
|
apiKey?: string;
|
|
username?: string;
|
|
password?: string;
|
|
userAgent?: string;
|
|
enabled?: boolean;
|
|
}
|
|
): Promise<OpenSubtitlesSettingsPublic> {
|
|
const existing = await prisma.integrationSetting.findUnique({ where: { id: OS_ID } });
|
|
const apiKeyTrim = input.apiKey?.trim();
|
|
const apiKeyEnc = apiKeyTrim
|
|
? encryptSecret(apiKeyTrim, sessionSecret)
|
|
: existing?.apiKeyEnc ?? null;
|
|
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;
|
|
const userAgent =
|
|
input.userAgent !== undefined
|
|
? input.userAgent.trim() || DEFAULT_UA
|
|
: existing?.userAgent?.trim() || DEFAULT_UA;
|
|
|
|
await prisma.integrationSetting.upsert({
|
|
where: { id: OS_ID },
|
|
create: {
|
|
id: OS_ID,
|
|
apiKeyEnc,
|
|
username,
|
|
passwordEnc,
|
|
userAgent,
|
|
enabled: input.enabled ?? true,
|
|
},
|
|
update: {
|
|
apiKeyEnc,
|
|
username,
|
|
passwordEnc,
|
|
userAgent,
|
|
enabled: input.enabled ?? true,
|
|
},
|
|
});
|
|
|
|
let comOk = false;
|
|
let orgOk = false;
|
|
let warning: string | null = null;
|
|
|
|
const client = await createOpenSubtitlesClientFromDb(sessionSecret);
|
|
if (client) {
|
|
try {
|
|
await client.search({ imdbId: "tt1375666", languages: "nl" });
|
|
comOk = true;
|
|
} catch (err) {
|
|
warning = err instanceof Error ? err.message : "OpenSubtitles.com test mislukt";
|
|
}
|
|
}
|
|
|
|
try {
|
|
const { OpenSubtitlesOrgClient } = await import("../opensubtitles/org-client");
|
|
await new OpenSubtitlesOrgClient().search({ imdbId: "tt1375666", languages: "nl" });
|
|
orgOk = true;
|
|
} catch (err) {
|
|
const msg = err instanceof Error ? err.message : "OpenSubtitles.org test mislukt";
|
|
warning = warning ? `${warning} · ${msg}` : msg;
|
|
}
|
|
|
|
if (!comOk && !orgOk) {
|
|
throw new AppError("OPENSUBTITLES", warning || "Geen OpenSubtitles-bron bereikbaar", 400);
|
|
}
|
|
|
|
// Opslaan mag als .org OK is, ook als .com login/API 403 geeft
|
|
const pub = await getOpenSubtitlesSettingsPublic();
|
|
return { ...pub, comOk, orgOk, warning };
|
|
}
|
|
|
|
export async function createOpenSubtitlesClientFromDb(
|
|
sessionSecret: string
|
|
): Promise<OpenSubtitlesClient | null> {
|
|
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,
|
|
row.userAgent
|
|
);
|
|
}
|