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, authors, rating }: SearchParams, ): Promise { let 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); if (tags?.length) { resources = resources.filter((r) => { return tags?.every((t) => r.tags.includes(t)); }); } if (authors?.length) { resources = resources.filter((r) => { return r?.meta?.author && authors.includes(r?.meta?.author); }); } if (rating) { resources = resources.filter((r) => { return r?.meta?.rating && r.meta.rating >= rating; }); } if (q.length && q !== "*") { const results = fuzzysort.go(q, resources, { keys: ["content", "name", "description"], threshold: 0.3, }); resources = results.map((r) => r.obj); } return resources; }