101 lines
2.4 KiB
TypeScript
101 lines
2.4 KiB
TypeScript
import * as openai from "@lib/openai.ts";
|
|
import * as tmdb from "@lib/tmdb.ts";
|
|
import { parseRating } from "@lib/helpers.ts";
|
|
import { createCache } from "@lib/cache.ts";
|
|
import { GenericResource, ReviewResource } from "./marka/schema.ts";
|
|
|
|
type RecommendationResource = {
|
|
id: string;
|
|
type: string;
|
|
rating: number;
|
|
tags?: string[];
|
|
description?: string;
|
|
keywords?: string[];
|
|
author?: string;
|
|
year?: number;
|
|
};
|
|
|
|
const cache = createCache<RecommendationResource>("recommendations");
|
|
|
|
export async function createRecommendationResource(
|
|
res: ReviewResource,
|
|
description?: string,
|
|
) {
|
|
const cacheId = `${res.type}:${res.name.replaceAll(":", "")}`;
|
|
const resource = cache.get(cacheId) || {
|
|
id: res.name,
|
|
type: res.type,
|
|
rating: -1,
|
|
};
|
|
if (description && !resource.keywords) {
|
|
const keywords = await openai.createKeywords(
|
|
res.type,
|
|
description,
|
|
res.name,
|
|
);
|
|
if (keywords?.length) {
|
|
resource.keywords = keywords;
|
|
}
|
|
}
|
|
|
|
const { author, datePublished, reviewRating } = res.content;
|
|
|
|
if (res?.content?.keywords) {
|
|
resource.keywords = res.content.keywords;
|
|
}
|
|
|
|
if (typeof reviewRating?.ratingValue !== "undefined") {
|
|
resource.rating = parseRating(reviewRating?.ratingValue);
|
|
}
|
|
|
|
if (author?.name) {
|
|
resource.author = author.name;
|
|
}
|
|
|
|
if (description) {
|
|
resource.description = description;
|
|
}
|
|
|
|
if (datePublished) {
|
|
const d = typeof datePublished === "string"
|
|
? new Date(datePublished)
|
|
: datePublished;
|
|
resource.year = d.getFullYear();
|
|
}
|
|
|
|
cache.set(cacheId, JSON.stringify(resource));
|
|
}
|
|
|
|
export function getRecommendation(
|
|
id: string,
|
|
type: string,
|
|
): RecommendationResource | undefined {
|
|
return cache.get(`recommendations:${type}:${id}`);
|
|
}
|
|
|
|
export async function getSimilarMovies(id: string) {
|
|
const recs = getRecommendation(id, "movie");
|
|
if (!recs?.keywords?.length) return;
|
|
|
|
const recommendations = await openai.getMovieRecommendations(
|
|
recs.keywords.join(),
|
|
[recs.id],
|
|
);
|
|
if (!recommendations) return;
|
|
|
|
const movies = await Promise.all(recommendations.map(async (rec) => {
|
|
const m = await tmdb.searchMovie(rec.title, rec.year);
|
|
return m?.results?.[0];
|
|
}));
|
|
|
|
return movies.filter(Boolean);
|
|
}
|
|
|
|
export async function getAllRecommendations(): Promise<
|
|
RecommendationResource[]
|
|
> {
|
|
const keys = cache.keys();
|
|
const res = await Promise.all(keys.map((k) => cache.get(k)));
|
|
return res.map((r) => JSON.parse(r));
|
|
}
|