From 68454b3a22e9924fc617c170b101e75814c8449a Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:40:40 +0530 Subject: [PATCH 1/7] novelping --- plugins/multisrc/readnovelfull/sources.json | 6 +++--- plugins/multisrc/readnovelfull/template.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index fc093afaa..6874a3569 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -72,12 +72,12 @@ }, { "id": "novelbin", - "sourceSite": "https://novelbin.com/", + "sourceSite": "https://novelping.com/", "sourceName": "Novel Bin", "options": { - "latestPage": "sort/latest", + "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 1, + "versionIncrements": 2, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, diff --git a/plugins/multisrc/readnovelfull/template.ts b/plugins/multisrc/readnovelfull/template.ts index 17dce3c7b..188c918bc 100644 --- a/plugins/multisrc/readnovelfull/template.ts +++ b/plugins/multisrc/readnovelfull/template.ts @@ -692,9 +692,9 @@ export class ReadNovelFullPlugin implements Plugin.PluginBase { } if (chapterHref !== undefined) { - const path = chapterHref.startsWith('/') - ? chapterHref.slice(1) - : chapterHref.replace(this.site + '/', ''); + const path = new URL(chapterHref, this.site).pathname.substring( + 1, + ); tempAjaxChapter.path = path; tempAjaxChapter.name = initialName; } From 254c93b23c6bf642ec1d090c77a1b52b7415069b Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:42:20 +0530 Subject: [PATCH 2/7] novelping 2 --- plugins/multisrc/readnovelfull/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index 6874a3569..ebef5a28b 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -77,7 +77,7 @@ "options": { "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 2, + "versionIncrements": 3, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, From 8d62f0bd8f7dc6d683ddb6fa4729a0e90f40a1d8 Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:53:00 +0530 Subject: [PATCH 3/7] switched to multisrc --- plugins/english/novelarrow.ts | 196 -------------------- plugins/multisrc/readnovelfull/sources.json | 6 +- 2 files changed, 3 insertions(+), 199 deletions(-) delete mode 100644 plugins/english/novelarrow.ts diff --git a/plugins/english/novelarrow.ts b/plugins/english/novelarrow.ts deleted file mode 100644 index ac236a1b3..000000000 --- a/plugins/english/novelarrow.ts +++ /dev/null @@ -1,196 +0,0 @@ -import { load as parseHTML } from 'cheerio'; -import { fetchApi } from '@libs/fetch'; -import { Plugin } from '@/types/plugin'; -import { NovelStatus } from '@libs/novelStatus'; - -class NovelArrow implements Plugin.PluginBase { - id = 'novelarrow'; - name = 'Novel Arrow'; - icon = 'src/en/novelarrow/icon.png'; - site = 'https://novelarrow.com/'; - version = '1.0.1'; - - async popularNovels(page: number) { - const url = `${this.site}novels/latest?page=${page}`; - const result = await fetchApi(url).then(res => res.text()); - const $ = parseHTML(result); - const novels: Plugin.NovelItem[] = []; - - $('article').each((i, el) => { - const title = $(el).find('h2').text().trim(); - const cover = $(el).find('img').attr('src'); - const href = $(el).find('a').attr('href'); - - if (title && href) { - novels.push({ - name: title, - cover, - path: href.substring(1), // Result: "novel/slug" - }); - } - }); - - return novels; - } - - async parseNovel(novelPath: string) { - // Ensure no double slashes in the URL - const url = this.site + novelPath.replace(/^\//, ''); - const result = await fetchApi(url).then(res => res.text()); - const $ = parseHTML(result); - - const novelId = novelPath.replace('novel/', '').replace(/^\//, ''); - - // Collect genres - let genres = $('meta[name="og:novel:genre"], meta[property="og:novel:genre"]').attr('content'); - - if (!genres) { - const genreList: string[] = []; - $('meta[property="article:tag"]').each((i, el) => { - const tag = $(el).attr('content'); - if (tag) genreList.push(tag); - }); - genres = genreList.join(', '); - } - - // Get the full summary from the paragraphs inside class .site-reading-copy - const fullSummary = $('.site-reading-copy p') - .map((i, el) => $(el).text().trim()) - .get() - .join('\n\n') || $('.site-reading-copy').text().trim(); - - const novel: Plugin.SourceNovel = { - path: novelPath, - name: $('meta[name="og:novel:novel_name"]').attr('content') || $('h1').first().text().trim(), - cover: $('meta[property="og:image"]').attr('content'), - author: $('meta[name="og:novel:author"]').attr('content') || $('meta[name="author"]').attr('content'), - status: - $('meta[name="og:novel:status"]').attr('content') === 'Ongoing' - ? NovelStatus.Ongoing - : NovelStatus.Completed, - summary: fullSummary, - genres: genres, - chapters: [], - }; - - const chaptersUrl = `${this.site}api-web/novels/${novelId}/chapters?sort=asc`; - try { - const chaptersJson = await fetchApi(chaptersUrl, { - headers: { - 'Accept': 'application/json', - }, - }).then(res => res.json()); - - if (chaptersJson && chaptersJson.items) { - novel.chapters = chaptersJson.items.map( - (item: { chapter_name: string; chapter_id: string }) => ({ - name: item.chapter_name, - path: `chapter/${novelId}/${item.chapter_id}`, - releaseTime: null, - }), - ); - } - } catch (e) { - const chaptersMap = new Map(); - // Flexible Regex to handle JSON stream variations - const combinedRegex = - /\\?"chapter_id\\?":\\?"([^"]+)\\?",\\?"chapter_name\\?":\\?"([^"]+)\\?"/g; - let match; - while ((match = combinedRegex.exec(result)) !== null) { - const path = match[1]; - const name = match[2].replace(/\\"/g, '"'); - const fullPath = `chapter/${novelId}/${path}`; - if (!chaptersMap.has(fullPath)) { - chaptersMap.set(fullPath, { - name, - path: fullPath, - releaseTime: null, - }); - } - } - novel.chapters = Array.from(chaptersMap.values()); - } - - return novel; - } - - async parseChapter(chapterPath: string) { - const pathParts = chapterPath.replace('chapter/', '').split('/'); - const novelId = pathParts[0]; - const chapterId = pathParts[1]; - - const url = `${this.site}api-web/novels/${novelId}/chapters/${chapterId}`; - - try { - const json = await fetchApi(url, { - headers: { - 'Accept': 'application/json', - 'x-track-reading-progress': 'false', - }, - }).then(res => res.json()); - - if ( - json && - json.item && - json.item.chapterInfo && - json.item.chapterInfo.chapter_content - ) { - return json.item.chapterInfo.chapter_content; - } - } catch (e) { - const result = await fetchApi(`${this.site}${chapterPath}`).then(res => - res.text(), - ); - const contentRegex = /\\u003ch4\\u003e(.*)\\u003c\/p\\u003e/; - const match = result.match(contentRegex); - - if (match) { - let chapterHtml = match[0]; - chapterHtml = chapterHtml - .replace(/\\u003c/g, '<') - .replace(/\\u003e/g, '>') - .replace(/\\"/g, '"') - .replace(/\\n/g, '') - .replace(/\\t/g, '') - .replace(/\\r/g, '') - .replace(/\\\\/g, '\\'); - - const lastPTagIndex = chapterHtml.lastIndexOf('
'); - if (lastPTagIndex !== -1) { - chapterHtml = chapterHtml.substring(0, lastPTagIndex + 4); - } - return chapterHtml; - } - - const $ = parseHTML(result); - return $('.site-reading-copy').html() || 'Content not found or premium.'; - } - - return 'Content not found or premium.'; - } - - async searchNovels(searchTerm: string, page: number) { - const url = `${this.site}novels/search?keyword=${encodeURIComponent(searchTerm)}&page=${page}`; - const result = await fetchApi(url).then(res => res.text()); - const $ = parseHTML(result); - const novels: Plugin.NovelItem[] = []; - - $('article').each((i, el) => { - const title = $(el).find('h2').text().trim(); - const cover = $(el).find('img').attr('src'); - const href = $(el).find('a').attr('href'); - - if (title && href) { - novels.push({ - name: title, - cover, - path: href.substring(1), - }); - } - }); - - return novels; - } -} - -export default new NovelArrow(); diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index ebef5a28b..58da2ca25 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -71,13 +71,13 @@ } }, { - "id": "novelbin", + "id": "novelarrow", "sourceSite": "https://novelping.com/", - "sourceName": "Novel Bin", + "sourceName": "Novel Arrow", "options": { "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 3, + "versionIncrements": 1, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, From 3cf8c1cfc02a41f73cbabe80f13d02f75cd9e7c5 Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 14:57:26 +0530 Subject: [PATCH 4/7] clean up --- plugins/multisrc/readnovelfull/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index 58da2ca25..25bcc28f8 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -77,7 +77,7 @@ "options": { "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 1, + "versionIncrements": 0, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, From 0242d5c8eff20e2ae7399bf5c6323603ae70efad Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:01:51 +0530 Subject: [PATCH 5/7] moved logo --- .../en => multisrc/fictioneer}/novelarrow/icon.png | Bin 1 file changed, 0 insertions(+), 0 deletions(-) rename public/static/{src/en => multisrc/fictioneer}/novelarrow/icon.png (100%) diff --git a/public/static/src/en/novelarrow/icon.png b/public/static/multisrc/fictioneer/novelarrow/icon.png similarity index 100% rename from public/static/src/en/novelarrow/icon.png rename to public/static/multisrc/fictioneer/novelarrow/icon.png From 3da72b5f410b26b6b873de839d8d841299393e49 Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:08:44 +0530 Subject: [PATCH 6/7] version bump --- plugins/multisrc/readnovelfull/sources.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index 25bcc28f8..58da2ca25 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -77,7 +77,7 @@ "options": { "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 0, + "versionIncrements": 1, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, From afe131f06c91f30bba755768546c1c5d597efde6 Mon Sep 17 00:00:00 2001 From: D3ICIDE <183315953+D3ICIDE@users.noreply.github.com> Date: Thu, 1 Oct 2026 15:15:46 +0530 Subject: [PATCH 7/7] clean up --- plugins/multisrc/readnovelfull/sources.json | 2 +- .../novelarrow/icon.png | Bin .../multisrc/readnovelfull/novelbin/icon.png | Bin 626 -> 0 bytes 3 files changed, 1 insertion(+), 1 deletion(-) rename public/static/multisrc/{fictioneer => readnovelfull}/novelarrow/icon.png (100%) delete mode 100644 public/static/multisrc/readnovelfull/novelbin/icon.png diff --git a/plugins/multisrc/readnovelfull/sources.json b/plugins/multisrc/readnovelfull/sources.json index 58da2ca25..25bcc28f8 100644 --- a/plugins/multisrc/readnovelfull/sources.json +++ b/plugins/multisrc/readnovelfull/sources.json @@ -77,7 +77,7 @@ "options": { "latestPage": "sort/updates", "searchPage": "search", - "versionIncrements": 1, + "versionIncrements": 0, "customJs": "$('[class*=\"app-promo\"]').remove();" } }, diff --git a/public/static/multisrc/fictioneer/novelarrow/icon.png b/public/static/multisrc/readnovelfull/novelarrow/icon.png similarity index 100% rename from public/static/multisrc/fictioneer/novelarrow/icon.png rename to public/static/multisrc/readnovelfull/novelarrow/icon.png diff --git a/public/static/multisrc/readnovelfull/novelbin/icon.png b/public/static/multisrc/readnovelfull/novelbin/icon.png deleted file mode 100644 index 539ebb8df6e0a1b64415aed71a7c2f5c19fc93e4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 626 zcmV-&0*(ENP)