diff --git a/plugins/english/divinedaolibrary.ts b/plugins/english/divinedaolibrary.ts index d0f2c14..3a0fab5 100644 --- a/plugins/english/divinedaolibrary.ts +++ b/plugins/english/divinedaolibrary.ts @@ -1,6 +1,5 @@ import { CheerioAPI, load as parseHTML } from "cheerio"; import { fetchApi, fetchFile } from "@libs/fetch"; -import { FilterTypes, Filters } from "@libs/filterInputs"; import { Plugin } from "@typings/plugin"; import { defaultCover } from "@libs/defaultCover"; @@ -8,7 +7,7 @@ class DDLPlugin implements Plugin.PluginBase { id = "DDL.com"; name = "Divine Dao Library"; site = "https://www.divinedaolibrary.com/"; - version = "1.0.0"; + version = "1.0.1"; icon = "src/en/divinedaolibrary/icon.png"; filters?: undefined; @@ -20,7 +19,7 @@ class DDLPlugin implements Plugin.PluginBase { .each((i,el) => { const novelName = loadedCheerio(el).find("a").text(); const novelCover = defaultCover; - const novelUrl = loadedCheerio(el).find(" a").attr("href"); + const novelUrl = loadedCheerio(el).find("a").attr("href"); if (!novelUrl) return; @@ -135,4 +134,5 @@ class DDLPlugin implements Plugin.PluginBase { return await fetchFile(url); } } + export default new DDLPlugin(); \ No newline at end of file diff --git a/plugins/english/faqwikius.ts b/plugins/english/faqwikius.ts index 6fe8409..be9b4be 100644 --- a/plugins/english/faqwikius.ts +++ b/plugins/english/faqwikius.ts @@ -1,131 +1,115 @@ import { Plugin } from "@typings/plugin"; import { fetchApi, fetchFile } from "@libs/fetch"; -import { NovelStatus } from "@libs/novelStatus"; -import { load as parseHTML } from "cheerio"; +import { CheerioAPI, load as parseHTML } from "cheerio"; class FaqWikiUs implements Plugin.PluginBase { - id = "FWK.US"; - name = "Faq Wiki"; - site = "https://faqwiki.us/"; - version = "1.0.0"; - icon = "src/en/faqwikius/icon.png"; + id = "FWK.US"; + name = "Faq Wiki"; + site = "https://faqwiki.us/"; + version = "1.1.0"; + icon = "src/en/faqwikius/icon.png"; - async popularNovels( - page: number, - { showLatestNovels }: Plugin.PopularNovelsOptions, - ): Promise { - - const body = await fetchApi(this.site).then((res) => res.text()); - const loadedCheerio = parseHTML(body); - - const novels: Plugin.NovelItem[] = loadedCheerio(".wp-block-table > table > tbody > tr") - .map((index, element) => { - const name = loadedCheerio(element).find('a').text().replace(/–\s+Chapter\s+List\s+–.*$/i,''); - let cover = loadedCheerio(element).find("img").attr("data-ezsrc"); - - // Remove the appended query string - if (cover) { - cover = cover.replace(/\?ezimgfmt=.*$/, ''); // Regular expression magic! - } - - const path = "" + loadedCheerio(element).find("a").attr("href")?.toString().replace(this.site, "").trim(); - - - return { name, cover, path }; - }) - .get() - .filter((novel) => novel.name && novel.path); - - return novels; - } - - 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(); - - let cover = loadedCheerio(".wp-block-image").find("img").attr("data-ezsrc"); + 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! + cover = cover.replace(/\?ezimgfmt=.*$/, ''); // Regular expression magic! } - novel.cover = cover; - novel.summary = loadedCheerio(".book-review-block__meta-item-value").text().trim(); + const path = loadedCheerio(element).find("a").attr("href")?.slice(this.site.length); + if (!path) return; - 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")?.toString().replace(this.site, "").trim(), - releaseTime: null, - chapterNumber: chapterIndex + 1, - })) - .get(); + novels.push({ name, cover, path }); + }) - 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); - - const novels: Plugin.NovelItem[] = loadedCheerio(".wp-block-table > table > tbody > tr") - .map((index, element) => { - const name = loadedCheerio(element).find('a').text().replace(/–\s+Chapter\s+List\s+–.*$/i,''); - let cover = loadedCheerio(element).find("img").attr("data-ezsrc"); - - // Remove the appended query string - if (cover) { - cover = cover.replace(/\?ezimgfmt=.*$/, ''); // Regular expression magic! + if (searchTerm) { + novels = novels.filter((novel) => + novel.name.toLowerCase().includes(searchTerm.toLowerCase()) + ); } - const path = "" + loadedCheerio(element).find("a").attr("href")?.toString().replace(this.site, "").trim(); + return novels; + } - return { name, cover, path }; - }) - .get().filter((novel) => novel.name && novel.path); - const normalizedQuery = searchTerm.toLowerCase(); - return novels.filter(novel => novel.name.toLowerCase().includes(normalizedQuery)); + async popularNovels( + page: number, + { showLatestNovels }: Plugin.PopularNovelsOptions, + ): Promise { + + const body = await fetchApi(this.site).then((res) => res.text()); + const loadedCheerio = parseHTML(body); - return novels; - } + return this.parseNovels(loadedCheerio); + } - fetchImage = fetchFile; + 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("src"); + + novel.summary = loadedCheerio(".book-review-block__meta-item-value").text().trim(); + + 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(); diff --git a/plugins/english/lnmtl.ts b/plugins/english/lnmtl.ts index 15533ba..b257446 100644 --- a/plugins/english/lnmtl.ts +++ b/plugins/english/lnmtl.ts @@ -8,7 +8,7 @@ class LnMTLPlugin implements Plugin.PagePlugin { name = "LnMTL"; icon = "src/en/lnmtl/icon.png"; site = "https://lnmtl.com/"; - version = "1.0.0"; + version = "1.0.1"; async sleep (ms: number) { return new Promise(resolve => setTimeout(resolve, ms)) @@ -112,12 +112,6 @@ class LnMTLPlugin implements Plugin.PagePlugin { )[+page-1]; const chapter: Plugin.ChapterItem[] = []; - interface ChapterEntry { - number: number; - title: string; - slug: string; - created_at: string; - } await this.sleep(1000); const volumeData = await fetchApi( @@ -243,4 +237,11 @@ class LnMTLPlugin implements Plugin.PagePlugin { } satisfies Filters; } -export default new LnMTLPlugin(); \ No newline at end of file +export default new LnMTLPlugin(); + +interface ChapterEntry { + number: number; + title: string; + slug: string; + created_at: string; +} \ No newline at end of file diff --git a/plugins/english/royalroad.ts b/plugins/english/royalroad.ts index 09d2ad8..82d8caf 100644 --- a/plugins/english/royalroad.ts +++ b/plugins/english/royalroad.ts @@ -1,4 +1,4 @@ -import { CheerioAPI, load, load as parseHTML } from "cheerio"; +import { CheerioAPI, load as parseHTML } from "cheerio"; import { fetchApi, fetchFile } from "@libs/fetch"; import { Plugin } from "@typings/plugin"; import { Filters, FilterTypes } from "@libs/filterInputs"; @@ -6,7 +6,7 @@ import { Filters, FilterTypes } from "@libs/filterInputs"; class RoyalRoad implements Plugin.PluginBase { id = "royalroad"; name = "Royal Road"; - version = "1.0.0"; + version = "1.0.1"; icon = "src/en/royalroad/icon.png"; site = "https://www.royalroad.com/"; @@ -71,26 +71,28 @@ class RoyalRoad implements Plugin.PluginBase { .toArray() .join(","); - const chapterlisting = JSON.parse( - loadedCheerio('script:contains("window.chapters")') - .html() - ?.match(/window.chapters = \[(.*?)\]/)![0] - ?.replace("window.chapters = ", "") || "" + const chapterJson = JSON.parse(loadedCheerio('script:contains("window.chapters")') + .html() + ?.match(/window.chapters = (.+])(?=;)/)![1] || ""); + + const volumeJson = JSON.parse(loadedCheerio('script:contains("window.chapters")') + .html() + ?.match(/window.volumes = (.+])(?=;)/)![1] || ""); + + const chapter : Plugin.ChapterItem[] = chapterJson.map( + (chapter: ChapterEntry) => { + const matchingVolume = volumeJson.find( + (volume: VolumeEntry) => volume.id === chapter.volumeId); + return { + name: chapter.title, + path: chapter.url.slice(1), + releaseTime: chapter.date, + chapterNumber: chapter?.order, + page: matchingVolume ? matchingVolume.title : null, + }; + } ); - interface ChapterEntry { - title: string; - date: string; - url: string; - } - - const chapter : Plugin.ChapterItem[] = chapterlisting.map( - (chapter: ChapterEntry) => ({ - name: chapter.title, - path: chapter.url.slice(1), - releaseTime: chapter.date, - })) - novel.chapters = chapter; return novel; } @@ -164,4 +166,20 @@ class RoyalRoad implements Plugin.PluginBase { } satisfies Filters; } -export default new RoyalRoad(); \ No newline at end of file +export default new RoyalRoad(); + +interface ChapterEntry { + id: number; + volumeId: number; + title: string; + date: string; + order: number; + url: string; +} + +interface VolumeEntry { + id: number; + title: string; + cover: string; + order: number; +} \ No newline at end of file