import { Post, ProviderContext } from "../types"; export const getPosts = async function ({ filter, page, signal, providerContext, }: { filter: string; page: number; providerValue: string; signal: AbortSignal; providerContext: ProviderContext; }): Promise { const { getBaseUrl } = providerContext; const baseUrl = await getBaseUrl("drive"); const url = `${baseUrl + filter}page/${page}/`; return posts({ url, signal, providerContext }); }; export const getSearchPosts = async function ({ searchQuery, page, signal, providerContext, }: { searchQuery: string; page: number; providerValue: string; providerContext: ProviderContext; signal: AbortSignal; }): Promise { const { getBaseUrl } = providerContext; const baseUrl = await getBaseUrl("drive"); const url = buildSearchUrl(baseUrl, searchQuery, page); return searchPosts({ url, baseUrl, signal, }); }; async function posts({ url, signal, providerContext, }: { url: string; signal: AbortSignal; providerContext: ProviderContext; }): Promise { try { console.log("Fetching URL:", url); const { cheerio } = providerContext; const res = await fetch(url, { signal }); const data = await res.text(); const $ = cheerio.load(data); const catalog: Post[] = []; $(".poster-card").map((i, element) => { const title = $(element).find(".poster-title").text(); const link = $(element).parent().attr("href"); const image = $(element).find(".poster-image img").attr("src"); if (title && link && image) { catalog.push({ title: title.replace("Download", "").trim(), link: link, image: image, }); } }); return catalog; } catch (err) { console.error("drive error ", err); return []; } } async function searchPosts({ url, baseUrl, signal, }: { url: string; baseUrl: string; signal: AbortSignal; }): Promise { try { console.log("Fetching drive search URL:", url); const res = await fetch(url, { signal }); if (!res.ok) { throw new Error(`drive search failed with status ${res.status}`); } const data = (await res.json()) as { hits?: Array<{ document?: { permalink?: string; post_thumbnail?: string; post_title?: string; }; }>; }; return ( data.hits ?.map((hit) => { const document = hit.document; const title = document?.post_title?.trim(); const link = document?.permalink ? normalizeUrl(baseUrl, document.permalink) : ""; const image = document?.post_thumbnail ? normalizeUrl(baseUrl, document.post_thumbnail) : ""; if (!title || !link || !image) { return null; } return { title, link, image, }; }) .filter((post): post is Post => post !== null) ?? [] ); } catch (err) { console.error("drive search error ", err); return []; } } function buildSearchUrl( baseUrl: string, searchQuery: string, page: number, ): string { const separator = baseUrl.includes("?") ? "&" : "?"; return `${trimTrailingSlash(baseUrl)}/search.php${separator}q=${encodeURIComponent( searchQuery, )}&page=${page}`; } function normalizeUrl(baseUrl: string, value: string): string { if (!value) { return ""; } if (/^https?:\/\//i.test(value)) { return value; } if (value.startsWith("//")) { return `https:${value}`; } if (value.startsWith("/")) { return `${trimTrailingSlash(baseUrl)}${value}`; } return `${trimTrailingSlash(baseUrl)}/${trimLeadingSlash(value)}`; } function trimTrailingSlash(value: string): string { return value.replace(/\/+$/, ""); } function trimLeadingSlash(value: string): string { return value.replace(/^\/+/, ""); }