import { FilterToValues, Filters } from "@libs/filterInputs"; import { languages } from "@libs/languages"; export namespace Plugin { export interface ChapterItem { name: string; url: string; /** * ```js * Timestamp or string in ISO format * e.g: `1699792274365` or `2023-11-12T12:31:14.365Z` or `2030-11-12` * or whatever you can create a Date object by new Date(releaseTime) or dayjs(releaseTime) * ``` */ releaseTime?: string | number | null; chapterNumber?: number; } export interface NovelItem { name: string; url: string; cover?: string; } export interface SourceNovel { url: string; name?: string; /** Novel cover absolute URL */ cover?: string; /** Comma separated genre list */ genres?: string; summary?: string; author?: string; artist?: string; status?: string; chapters?: ChapterItem[]; } export interface PopularNovelsOptions< Q extends Filters | undefined = Filters | undefined > { showLatestNovels?: boolean; filters: Q extends undefined ? undefined : FilterToValues; } export interface PluginItem { id: string; name: string; lang: (typeof languages)[keyof typeof languages]; version: string; requirePath: string; icon: string; } export interface PluginBase { id: string; name: string; /** * Relative path without icon. E.g: * ```js * "src/vi/hakolightnovel/icon.png" * ``` */ icon: string; site: string; filters?: Filters; version: string; popularNovels( pageNo: number, options: PopularNovelsOptions ): Promise; parseNovelAndChapters(novelUrl: string): Promise; parseChapter(chapterUrl: string): Promise; searchNovels(searchTerm: string, pageNo: number): Promise; /** * * @param url Image url * @returns {Promise} Base64 of image * @example * ```ts * const headers = { * Referer: "https://ln.hako.vn", * }; * return await fetchFile(url, { headers: headers }); * ``` */ fetchImage(url: string): Promise; } } export const isPlugin = (p: any): p is Plugin.PluginBase => { const pl = p as Plugin.PluginBase; const errorOut = (key: string) => { console.error(`Plugin ${pl.name} doesn't have ${key}!`); return false; }; const required_funcs: (keyof Plugin.PluginBase)[] = [ "popularNovels", "parseNovelAndChapters", "parseChapter", "searchNovels", "fetchImage", ]; for (let i = 0; i < required_funcs.length; i++) { const key = required_funcs[i]; if (!pl[key] || typeof pl[key] !== "function") return errorOut(key); } const requireds_fields: (keyof Plugin.PluginBase)[] = [ "id", "name", "version", "icon", "site", ]; for (let i = 0; i < requireds_fields.length; i++) { const key = requireds_fields[i]; if (pl[key] === undefined) return errorOut(key); } return true; };