import { resources } from "@lib/resources.ts"; import fuzzysort from "fuzzysort"; import { extractHashTags } from "@lib/string.ts"; import { listResources } from "./marka/index.ts"; import { GenericResource } from "./marka/schema.ts"; import { parseRating } from "./helpers.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: GenericResource | boolean | undefined, ): item is GenericResource => { return !!item; }; export async function searchResource( { q, tags = [], types, rating }: SearchParams, ): Promise { const resources = (await Promise.all([ (!types || types.includes("movie")) && listResources("movies"), (!types || types.includes("series")) && listResources("series"), (!types || types.includes("article")) && listResources("articles"), (!types || types.includes("recipe")) && listResources("recipes"), ])).flat().filter(isResource); const results: Record = {}; for (const resource of resources) { if ( !(resource.name in results) && tags?.length && resource.content.keywords?.length && tags.every((t) => resource.content.keywords?.includes(t)) ) { results[resource.name] = resource; } if ( !(resource.name in results) && rating && resource.content.reviewRating?.ratingValue && parseRating(resource.content.reviewRating.ratingValue) >= rating ) { results[resource.name] = resource; } } if (q.length && q !== "*") { const fuzzyResult = fuzzysort.go(q, resources, { keys: [ "name", "content.articleBody", "content.reviewBody", "content.name", "content.description", "content.author.name", ], threshold: 0.3, }); for (const result of fuzzyResult) { results[result.obj.name] = result.obj; } } return Object.values(results); }