memorium/lib/search.ts

94 lines
2.6 KiB
TypeScript
Raw Normal View History

2023-08-10 16:59:18 +02:00
import { resources } from "@lib/resources.ts";
2025-01-05 23:14:19 +01:00
import fuzzysort from "npm:fuzzysort";
import { GenericResource } from "@lib/types.ts";
2023-08-10 16:59:18 +02:00
import { extractHashTags } from "@lib/string.ts";
2025-01-05 23:14:19 +01:00
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";
2023-08-10 16:59:18 +02:00
type ResourceType = keyof typeof resources;
type SearchParams = {
q: string;
2025-01-05 23:14:19 +01:00
types?: string[];
2023-08-10 16:59:18 +02:00
tags?: string[];
2025-01-05 23:14:19 +01:00
rating?: number;
authors?: string[];
2023-08-10 16:59:18 +02:00
};
2023-09-08 13:33:29 +02:00
export function parseResourceUrl(_url: string | URL): SearchParams | undefined {
2023-08-10 16:59:18 +02:00
try {
2023-09-08 13:33:29 +02:00
const url = typeof _url === "string" ? new URL(_url) : _url;
let query = url.searchParams.get("q") || "*";
2023-08-10 16:59:18 +02:00
if (!query) {
return undefined;
}
query = decodeURIComponent(query);
const hashTags = extractHashTags(query);
for (const tag of hashTags) {
query = query.replace("#" + tag, "");
}
return {
q: query,
2025-01-05 23:14:19 +01:00
types: url.searchParams.get("type")?.split(",") as ResourceType[] ||
undefined,
2023-08-10 16:59:18 +02:00
tags: hashTags,
2025-01-05 23:14:19 +01:00
rating: url.searchParams.has("rating")
? parseInt(url.searchParams.get("rating")!)
: undefined,
2023-08-10 16:59:18 +02:00
};
} catch (_err) {
return undefined;
}
}
2025-01-05 23:14:19 +01:00
const isResource = (
item: Movie | Series | Article | Recipe | boolean,
): item is Movie | Series | Article | Recipe => {
return !!item;
};
2023-08-10 16:59:18 +02:00
export async function searchResource(
2025-01-05 23:14:19 +01:00
{ q, tags = [], types, authors, rating }: SearchParams,
): Promise<GenericResource[]> {
console.log("searchResource", { q, tags, types, authors, rating });
2023-08-10 16:59:18 +02:00
2025-01-05 23:14:19 +01:00
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);
2023-08-10 16:59:18 +02:00
if (tags?.length) {
2025-01-05 23:14:19 +01:00
resources = resources.filter((r) => {
return tags?.every((t) => r.tags.includes(t));
});
2023-08-10 16:59:18 +02:00
}
2025-01-05 23:14:19 +01:00
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;
});
}
2025-01-05 23:14:19 +01:00
if (q.length && q !== "*") {
const results = fuzzysort.go(q, resources, {
keys: ["content", "name", "description"],
threshold: 0.3,
2023-08-10 16:59:18 +02:00
});
2025-01-05 23:14:19 +01:00
resources = results.map((r) => r.obj);
}
return resources;
2023-08-10 16:59:18 +02:00
}