Files
worst-scan-web/src/lib/cover-cache.ts
T

76 lines
2.2 KiB
TypeScript

import fs from "fs"
import path from "path"
import { get } from "./settings"
const COVERS_DIR = process.env.COVERS_DIR || path.join(process.cwd(), "data", "covers")
function ensureDir() {
fs.mkdirSync(COVERS_DIR, { recursive: true })
}
function extFromContentType(ct: string | null): string {
if (!ct) return ".jpg"
const m = ct.match(/image\/(\w+)/)
if (!m) return ".jpg"
const exts: Record<string, string> = {
jpeg: ".jpg",
png: ".png",
webp: ".webp",
gif: ".gif",
}
return exts[m[1]] || ".jpg"
}
// Descarga la portada DIRECTAMENTE del upstream (API_BASE_URL), con la misma
// API key que usa el resto de la app. NO pasa por el proxy /api/proxy/* (que el
// middleware protege), evitando el redirect a /login que guardaba HTML como portada.
export async function cacheCover(gid: string): Promise<string | null> {
ensureDir()
try {
const apiBase = get("API_BASE_URL", "http://127.0.0.1:8080/api/v1")
const apiKey = get("API_KEY")
const headers: Record<string, string> = {}
if (apiKey) headers["X-API-Key"] = apiKey
const res = await fetch(`${apiBase}/galleries/${gid}/cover`, {
headers,
signal: AbortSignal.timeout(15000),
})
if (!res.ok) return null
const buffer = Buffer.from(await res.arrayBuffer())
const ext = extFromContentType(res.headers.get("content-type"))
const filePath = path.join(COVERS_DIR, `${gid}${ext}`)
fs.writeFileSync(filePath, buffer)
return filePath
} catch {
return null
}
}
export function getCoverPath(gid: string): string | null {
ensureDir()
const files = fs.readdirSync(COVERS_DIR).filter((f) => f.startsWith(`${gid}.`))
if (files.length === 0) return null
return path.join(COVERS_DIR, files[0])
}
export function getCoverContentType(gid: string): string {
const fp = getCoverPath(gid)
if (!fp) return "image/jpeg"
const ext = path.extname(fp).toLowerCase()
const m: Record<string, string> = {
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".png": "image/png",
".webp": "image/webp",
".gif": "image/gif",
}
return m[ext] || "image/jpeg"
}
export function deleteCover(gid: string): void {
const fp = getCoverPath(gid)
if (fp) fs.unlinkSync(fp)
}