import { Plugin } from "@typings/plugin"; import { fetchApi, fetchFile } from "@libs/fetch"; import { CheerioAPI, load as parseHTML } from "cheerio"; import { NovelStatus } from "@libs/novelStatus"; class FaqWikiUs implements Plugin.PluginBase { id = "FWK.US"; name = "Faq Wiki"; site = "https://faqwiki.us/"; version = "1.1.1"; icon = "src/en/faqwikius/icon.png"; parseNovels(loadedCheerio:CheerioAPI, searchTerm?: string) { let novels: Plugin.NovelItem[] = []; loadedCheerio("figure.wp-block-image").each((index, element) => { const name = loadedCheerio(element).text(); let cover = loadedCheerio(element).find("img").attr("data-ezsrc"); // Remove the appended query string if (cover) { cover = cover.replace(/\?ezimgfmt=.*$/, ''); // Regular expression magic! } else { cover = loadedCheerio(element).find("img").attr("src"); } const path = loadedCheerio(element).find("a").attr("href")?.replace('tp:', 'tps:')?.slice(this.site.length); if (!path) return; novels.push({ name, cover, path }); }) if (searchTerm) { novels = novels.filter((novel) => novel.name.toLowerCase().includes(searchTerm.toLowerCase()) ); } return novels; } async popularNovels( page: number, { showLatestNovels }: Plugin.PopularNovelsOptions, ): Promise { const body = await fetchApi(this.site).then((res) => res.text()); const loadedCheerio = parseHTML(body); return this.parseNovels(loadedCheerio); } async parseNovel(path: string): Promise { const body = await fetchApi(this.site + path).then((res) => res.text()); const loadedCheerio = parseHTML(body); const novel: Plugin.SourceNovel = { path, name: "" }; novel.name = loadedCheerio(".entry-title").text().replace("Novel – All Chapters", "").trim(); novel.cover = loadedCheerio(".wp-block-image") .find("img") .attr("data-ezsrc") ?.replace(/\?ezimgfmt=.*$/, ''); // Regular expression magic! const status = loadedCheerio("#lcp_instance_0 +:icontains('complete')").text(); novel.status = (status ? NovelStatus.Completed : NovelStatus.Ongoing) const div = loadedCheerio(".book-review-block__meta-item-value"); div.html(div.html()?.replace(/(?<=>)([^<]+)(?=)/g, '

$1

')!); loadedCheerio(".book-review-block__meta-item-value strong").each((i,el) => { const key = loadedCheerio(el).text().replace(':', '').trim().toLowerCase(); const value = loadedCheerio(el).next().text().replace(':', '').trim(); switch(key){ case "description": novel.summary = value; break; case "author(s)": novel.author = value; break; case "genre": novel.genres = value.split(' ').join(','); } }) const chapters: Plugin.ChapterItem[] = loadedCheerio(".lcp_catlist > li > a") .map((chapterIndex, element) => ({ name: loadedCheerio(element).text().replace(novel.name + "", "").replace("Novel" + "", "").trim(), path: ""+loadedCheerio(element).attr("href")?.slice(this.site.length), chapterNumber: chapterIndex + 1, })) .get(); novel.chapters = chapters; return novel; } async parseChapter(chapterPath: string): Promise { const body = await fetchApi(this.site + chapterPath).then((res) => res.text()); const loadedCheerio = parseHTML(body); loadedCheerio("span").remove(); const chapterParagraphs = loadedCheerio(".entry-content p"); let chapterContent; // Variable to store the result if (chapterParagraphs.length < 5) { //some chapter in this site store their whole text in 1-4

, chapterContent = chapterParagraphs.map((index, element) => { const text = loadedCheerio(element).html() return text; }).get().join('\n\n'); } else { // Multiple paragraphs case chapterContent = chapterParagraphs.map((index, element) => { const text = loadedCheerio(element).text().trim(); return `

${text}

`; }).get().join('\n\n'); } return chapterContent; } async searchNovels(searchTerm: string): Promise { const body = await fetchApi(this.site).then((res) => res.text()); const loadedCheerio = parseHTML(body); return this.parseNovels(loadedCheerio, searchTerm); } fetchImage = fetchFile; } export default new FaqWikiUs();