import { resources } from "@lib/resources.ts"; import fuzzysort from "npm:fuzzysort"; import { GenericResource } from "@lib/types.ts"; import { extractHashTags } from "@lib/string.ts"; import { getAllMovies, Movie } from "@lib/resource/movies.ts"; import { Article, getAllArticles } from "@lib/resource/articles.ts"; import { getAllRecipes, Recipe } from "@lib/resource/recipes.ts"; import { getAllSeries, Series } from "@lib/resource/series.ts"; type ResourceType = keyof typeof resources; type SearchParams = { q: string; types?: string[]; tags?: string[]; rating?: number; authors?: string[]; }; export function parseResourceUrl(_url: string | URL): SearchParams | undefined { try { const url = typeof _url === "string" ? new URL(_url) : _url; let query = url.searchParams.get("q") || "*"; if (!query) { return undefined; } query = decodeURIComponent(query); const hashTags = extractHashTags(query); for (const tag of hashTags) { query = query.replace("#" + tag, ""); } return { q: query, types: url.searchParams.get("type")?.split(",") as ResourceType[] || undefined, tags: hashTags, rating: url.searchParams.has("rating") ? parseInt(url.searchParams.get("rating")!) : undefined, }; } catch (_err) { return undefined; } } const isResource = ( item: Movie | Series | Article | Recipe | boolean, ): item is Movie | Series | Article | Recipe => { return !!item; }; export async function searchResource( { q, tags = [], types, rating }: SearchParams, ): Promise { const resources = (await Promise.all([ (!types || types.includes("movie")) && getAllMovies(), (!types || types.includes("series")) && getAllSeries(), (!types || types.includes("article")) && getAllArticles(), (!types || types.includes("recipe")) && getAllRecipes(), ])).flat().filter(isResource); const results: Record = {}; for (const resource of resources) { if ( !(resource.id in results) && tags?.length && resource.tags.length && tags.every((t) => resource.tags.includes(t)) ) { results[resource.id] = resource; } if ( !(resource.id in results) && rating && resource?.meta?.rating && resource.meta.rating >= rating ) { results[resource.id] = resource; } } if (q.length && q !== "*") { const fuzzyResult = fuzzysort.go(q, resources, { keys: ["content", "name", "description", "meta.author"], threshold: 0.3, }); for (const result of fuzzyResult) { results[result.obj.id] = result.obj; } } return Object.values(results); }