95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			95 lines
		
	
	
		
			2.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import * as openai from "@lib/openai.ts";
 | |
| import * as tmdb from "@lib/tmdb.ts";
 | |
| import { GenericResource } from "@lib/types.ts";
 | |
| import { parseRating } from "@lib/helpers.ts";
 | |
| import { createCache } from "@lib/cache.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: GenericResource,
 | |
|   description?: string,
 | |
| ) {
 | |
|   const cacheId = `${res.type}:${res.id.replaceAll(":", "")}`;
 | |
|   const resource = cache.get(cacheId) || {
 | |
|     id: res.id,
 | |
|     type: res.type,
 | |
|     rating: -1,
 | |
|   };
 | |
|   if (description && !resource.keywords) {
 | |
|     const keywords = await openai.createKeywords(res.type, description, res.id);
 | |
|     if (keywords?.length) {
 | |
|       resource.keywords = keywords;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   const { author, date, rating } = res.meta || {};
 | |
| 
 | |
|   if (res?.tags) {
 | |
|     resource.tags = res.tags;
 | |
|   }
 | |
| 
 | |
|   if (typeof rating !== "undefined") {
 | |
|     resource.rating = parseRating(rating);
 | |
|   }
 | |
| 
 | |
|   if (author) {
 | |
|     resource.author = author;
 | |
|   }
 | |
| 
 | |
|   if (description) {
 | |
|     resource.description = description;
 | |
|   }
 | |
| 
 | |
|   if (date) {
 | |
|     const d = typeof date === "string" ? new Date(date) : date;
 | |
|     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));
 | |
| }
 |