mirror of
https://github.com/jakejarvis/sofa.git
synced 2026-08-29 06:15:39 -04:00
77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import path from "node:path";
|
|
import { eq } from "drizzle-orm";
|
|
import { Vibrant } from "node-vibrant/node";
|
|
import { db } from "@/lib/db/client";
|
|
import { titles } from "@/lib/db/schema";
|
|
import { createLogger } from "@/lib/logger";
|
|
import {
|
|
downloadAndCacheImage,
|
|
getLocalImagePath,
|
|
imageCacheEnabled,
|
|
isImageCached,
|
|
} from "@/lib/services/image-cache";
|
|
|
|
const log = createLogger("colors");
|
|
|
|
export interface ColorPalette {
|
|
vibrant: string | null;
|
|
darkVibrant: string | null;
|
|
lightVibrant: string | null;
|
|
muted: string | null;
|
|
darkMuted: string | null;
|
|
lightMuted: string | null;
|
|
}
|
|
|
|
export async function extractAndStoreColors(
|
|
titleId: string,
|
|
posterPath: string | null,
|
|
): Promise<ColorPalette | null> {
|
|
if (!posterPath) return null;
|
|
|
|
// Use local cached image, downloading first if needed
|
|
let source: string;
|
|
const filename = path.basename(posterPath);
|
|
if (imageCacheEnabled()) {
|
|
if (!(await isImageCached("posters", filename))) {
|
|
await downloadAndCacheImage(posterPath, "posters");
|
|
}
|
|
source = getLocalImagePath("posters", filename);
|
|
} else {
|
|
const baseUrl =
|
|
process.env.TMDB_IMAGE_BASE_URL || "https://image.tmdb.org/t/p";
|
|
source = `${baseUrl}/w300${posterPath}`;
|
|
}
|
|
|
|
try {
|
|
const palette = await Vibrant.from(source).getPalette();
|
|
|
|
const colors: ColorPalette = {
|
|
vibrant: palette.Vibrant?.hex ?? null,
|
|
darkVibrant: palette.DarkVibrant?.hex ?? null,
|
|
lightVibrant: palette.LightVibrant?.hex ?? null,
|
|
muted: palette.Muted?.hex ?? null,
|
|
darkMuted: palette.DarkMuted?.hex ?? null,
|
|
lightMuted: palette.LightMuted?.hex ?? null,
|
|
};
|
|
|
|
db.update(titles)
|
|
.set({ colorPalette: JSON.stringify(colors) })
|
|
.where(eq(titles.id, titleId))
|
|
.run();
|
|
|
|
return colors;
|
|
} catch (err) {
|
|
log.error(`Failed to extract colors for title ${titleId}:`, err);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function parseColorPalette(raw: string | null): ColorPalette | null {
|
|
if (!raw) return null;
|
|
try {
|
|
return JSON.parse(raw) as ColorPalette;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|