fix: make search usable again

This commit is contained in:
Max Richter
2025-11-05 00:42:53 +01:00
parent 7664abe089
commit 581f1c1926
9 changed files with 120 additions and 62 deletions

View File

@@ -31,6 +31,9 @@ const cacheLock = new Map<string, Promise<Resource>>();
async function fetchAndStoreUrl(url: string) {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`Failed to fetch resource: ${response.status}`);
}
const res = await response.json();
fetchCache.set(url, res);
return res;
@@ -54,7 +57,7 @@ async function cachedFetch(
return res;
}
export async function fetchResource<T extends Resource>(
export async function fetchResource<T extends GenericResource>(
resource: string,
): Promise<T | undefined> {
try {
@@ -80,6 +83,7 @@ export async function listResources<T extends GenericResource>(
.map((res) => addImageToResource(res) as Promise<T>),
);
} catch (_e) {
console.log(`Failed to fetch resource: ${resource}`, _e);
return [];
}
}

View File

@@ -19,7 +19,7 @@ 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) {
if (!(typeof query === "string")) {
return undefined;
}
query = decodeURIComponent(query);
@@ -54,12 +54,14 @@ export async function searchResource(
{ q, tags = [], types, rating }: SearchParams,
): Promise<GenericResource[]> {
const resources = (await Promise.all([
(!types || types.includes("movie")) && listResources("movies"),
(!types || types.includes("movies")) && listResources("movies"),
(!types || types.includes("series")) && listResources("series"),
(!types || types.includes("article")) && listResources("articles"),
(!types || types.includes("recipe")) && listResources("recipes"),
(!types || types.includes("articles")) && listResources("articles"),
(!types || types.includes("recipes")) && listResources("recipes"),
])).flat().filter(isResource);
console.log({ types, rating, tags, q });
const results: Record<string, GenericResource> = {};
for (const resource of resources) {
@@ -71,9 +73,18 @@ export async function searchResource(
results[resource.name] = resource;
}
// Select not-rated resources
if (
rating === 0 &&
resource.content?.reviewRating?.ratingValue === undefined
) {
results[resource.name] = resource;
}
if (
!(resource.name in results) &&
rating && resource.content.reviewRating?.ratingValue &&
typeof rating == "number" &&
resource.content.reviewRating?.ratingValue &&
parseRating(resource.content.reviewRating.ratingValue) >= rating
) {
results[resource.name] = resource;
@@ -81,6 +92,7 @@ export async function searchResource(
}
if (q.length && q !== "*") {
q = decodeURIComponent(q);
const fuzzyResult = fuzzysort.go(q, resources, {
keys: [
"name",

View File

@@ -17,7 +17,7 @@ export function safeFileName(input: string): string {
.normalize("NFKD")
.replace(/[\u0300-\u036f]/g, "")
.replace(/[\s-]+/g, "_")
.replace(/[^A-Za-z0-9._]+/g, "")
.replace(/[^A-Za-z0-9_]+/g, "")
.replace(/_+/g, "_")
// Trim underscores/dots from ends and prevent leading dots
.replace(/^[_\.]+|[_\.]+$/g, "").replace(/^\.+/, "")

View File

@@ -74,6 +74,11 @@ export interface PageInfo {
resultsPerPage: number;
}
export async function getYoutubeVideoCover(id: string): Promise<ArrayBuffer> {
const res = await fetch(`https://i.ytimg.com/vi/${id}/maxresdefault.jpg`);
return res.arrayBuffer();
}
export async function getYoutubeVideoDetails(
id: string,
): Promise<Item> {
@@ -81,6 +86,5 @@ export async function getYoutubeVideoDetails(
`${BASE_URL}videos?part=snippet%2CcontentDetails%2Cstatistics&id=${id}&key=${YOUTUBE_API_KEY}`,
);
const json = await response.json();
return json?.items[0];
}