Beta phase (#801)

* beta host

* Refactor: url -> path (#757)

* refactor: url -> path

* clean up

* fix: json branch

* PagePlugin (#769)

* paginated novel support

* fix: truyenfull

* fix: tunovel, remove pageList

* parsePage support for webtest (#773)

* add parsePage api

* add parsePage UI

* add totalPages

* (FR src) Beta plugin & Added filters (#775)

* noveldeglace:
 - added filters
 - added latest
 - defaultCover fallback
 - change id to noveldeglace.com
 - added complementary infos in summary
 - added cover artist
 - chapters are now parts
 - show volume number for multi volume novels
 - better search
 - fix search page number
 - refactored for plugin beta
 - releaseDate as Date.toString()
 - separted parseNovels
 - separated getCheerio
 - loadedCheerio => $ for shorter lines & simpler test on web

* chireads:
 - fix different parsing for mobile version
 - added filters
 - added author
 - added status
 - added released date
 - refactored for plugin beta
 - separted parseNovels
 - separated getCheerio
 - loadedCheerio => $ for shorter lines & simpler test on web

* wpmangastream => lightnovelwp rework & new sources (#776)

* Added sources:
 - Knoxt (EN)
 - Baca Light Novel (ID)
 - AllNovelRead (ES)
 - DaoTranslate (EN)
 - جنة الروايات (AR)
 - Universal Novel (EN)
 - NovelTR (TR)
old sources auto-generated:
 - GenesisTls (EN)
 - NobleMTL (EN)
wpmangastream => lightnovelwp:
 - added doc
 - added filters in a separte file
 - semi-automatic filter generator
 - made it compatible with version 1.0.X and 1.1.X versions of the theme
 - loadedCheerio => $
 - icons in "/icons/lightnovel/id.png"
 - code cleanup

* removed auto-implemented sources

* Added README.md to lightnovelwp

* removed ai generated text for kolnovel

* added novelsknight

* added centralNovel

* pandamtl accual name

* adding folder plugin/arabic

* Fix: Vietnamese plugins (#777)

* fix: lightnovelvn

* add nettruyen

* add truyenchu

* fix: truyenconect

* Fix: Migrate plugins (#771)

* Add novel.ovh (#756)

* fix

* test

* fix

* date fix + master merge (#761)

* date fix

* Added Brazilian Portuguese E-Novel (#758)

* fixed single digit dates (#767)

Co-authored-by: NaddH1 <naderhorani@hotmail.com>

* fix

* test

* fix order

* Update renovels.ts

* require_chapters

* Delete plugins/english/genesistl.broken.ts

* Update novelTL.ts

---------

Co-authored-by: NaddH1 <naderhorani@hotmail.com>

* (src update) ENG (#772)

* allnovelfull

* bestlightnovel

* divinedaolibrary

* earlynovel

* lightnovelpub

* L

* M

* novelbin

* novelfull

* novelbuddy

* N S

* novel updates

* async sleep

* rename file

* pagePlugin

* Feat: minify js dir (#781)

* Multisrc: HotNovelPub (#784)

* HotNovelPub

* fix search

* Squashed commit of the following:

commit 3b759c68eddc06c0adfb959f775de069a85adca7
Author: nyagami <hoangquan05112002@gmail.com>
Date:   Sat Feb 17 20:33:47 2024 +0700

    Feat: minify js dir (#781)

* jsmin changed to terser

* test

* why I did it.

* test

* Update ranobelib.ts

* fix page

* Update ranobelib.ts

* updated modules

* Update terser.json

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

* Update scripts/multisrc/hotnovelpub/template.ts

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

* terser api

---------

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

* Added sources & fix sources (#787)

* lightnovelwp:
 - fix author name
 - added more localisation of strings
 - README typo
 - error on !r.ok new message

* noveldeglace:
 - fix chapterNumber for parts
 - better dates
 - better search

* Added sources:
 - White Moonlight Novels (EN)
 - System Translation (EN)

* Resized centralnovel.png

* Add Faqwiki.us source (#792)

* Add Faqwiki.us source (beta branch)

* Fix Path, Fix Chapter Parsing, Fix Novel Title

* search novel path fix

* fix chapter parsing. some chapter in this site store their whole text in 1-4 <p>,

* Add WTR-LAB Source (#797)

* Add WTR-LAB Source (Beta Branch)

* Add other language from WTR-LAB source

* change lang to sourceLang

* remove id es tr lang from WTR-LAB

* Update plugins/english/wtrlab.ts

agree

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

* Update plugins/english/wtrlab.ts

agree

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

---------

Co-authored-by: nyagami <hoangquan05112002@gmail.com>

* revert: scripts to master

---------

Co-authored-by: Justin COLLON <48163201+error7404@users.noreply.github.com>
Co-authored-by: Rider21 <58046032+Rider21@users.noreply.github.com>
Co-authored-by: NaddH1 <naderhorani@hotmail.com>
Co-authored-by: K1ngfish3r <trulyihu@gmail.com>
Co-authored-by: bregassa <bregas.sat1@gmail.com>
This commit is contained in:
nyagami
2024-02-25 14:52:37 +07:00
committed by GitHub
parent 2b9c8f7d2a
commit d818d1758f
147 changed files with 10278 additions and 5758 deletions
+99 -64
View File
@@ -5,12 +5,12 @@ import { NovelStatus } from "@libs/novelStatus";
import { load as parseHTML } from "cheerio";
import dayjs from "dayjs";
const statusKey = [
NovelStatus.Ongoing,
NovelStatus.Completed,
NovelStatus.OnHiatus,
NovelStatus.Cancelled,
];
const statusKey: { [key: number]: string } = {
1: NovelStatus.Ongoing,
2: NovelStatus.Completed,
3: NovelStatus.OnHiatus,
4: NovelStatus.Cancelled,
};
class RLIB implements Plugin.PluginBase {
id = "RLIB";
@@ -22,22 +22,26 @@ class RLIB implements Plugin.PluginBase {
async popularNovels(
pageNo: number,
{ showLatestNovels, filters }: Plugin.PopularNovelsOptions<typeof this.filters>,
{
showLatestNovels,
filters,
}: Plugin.PopularNovelsOptions<typeof this.filters>,
): Promise<Plugin.NovelItem[]> {
let url = this.site + "/manga-list?sort=";
url += showLatestNovels ? "last_chapter_at" : filters?.sort?.value || "rate";
url += "&dir=" + (filters?.order?.value || "desc");
url += "&chapters[min]=" + (filters?.require_chapters?.value ? "1" : "0");
Object.entries(filters || {}).forEach(([type, { value }]: any) => {
if (value instanceof Array && value.length) {
url += "&" + type + "[]=" + value.join("&" + type + "[]=");
}
if (value?.include instanceof Array && value.include.length) {
url += "&" + type + "[include][]=" +
url += "&" + type + "[include][]=" +
value.include.join("&" + type + "[include][]=");
}
}
if (value?.exclude instanceof Array && value.exclude.length) {
url += "&" + type + "[exclude][]=" +
url += "&" + type + "[exclude][]=" +
value.exclude.join("&" + type + "[exclude][]=");
}
});
@@ -51,27 +55,25 @@ class RLIB implements Plugin.PluginBase {
?.replace?.(/[^0-9]/g, "");
const novels: Plugin.NovelItem[] = [];
loadedCheerio(".media-card-wrap").each(function () {
const name = loadedCheerio(this).find(".media-card__title").text();
const cover = loadedCheerio(this).find("a.media-card").attr("data-src");
const url = loadedCheerio(this).find("a.media-card").attr("href");
loadedCheerio(".media-card-wrap").each((index, element) => {
const name = loadedCheerio(element).find(".media-card__title").text();
const cover = loadedCheerio(element).find("a.media-card").attr("data-src");
const url = loadedCheerio(element).find("a.media-card").attr("href");
if (!url) return;
novels.push({ name, cover, url });
novels.push({ name, cover, path: url.replace(this.site, "") });
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const body = await fetchApi(novelUrl).then((res) => res.text());
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
const body = await fetchApi(this.site + novelPath).then((res) => res.text());
const loadedCheerio = parseHTML(body);
const novel: Plugin.SourceNovel = {
url: novelUrl,
path: novelPath,
name: loadedCheerio(".media-name__main").text()?.trim?.() || "",
};
novel.name = loadedCheerio(".media-name__main").text().trim();
novel.cover = loadedCheerio(".container_responsive img").attr("src");
novel.summary = loadedCheerio(".media-description__text").text().trim();
@@ -102,45 +104,75 @@ class RLIB implements Plugin.PluginBase {
}
});
const chapters: Plugin.ChapterItem[] = [];
const chaptersRaw = body.match(/window\.__DATA__ = ({.*?});/);
if (chaptersRaw instanceof Array && chaptersRaw.length >= 2) {
const chaptersJson: responseBook = JSON.parse(chaptersRaw[1]);
let chaptersRaw: any = body.match(
/window.__DATA__ = [\s\S]*?window._SITE_COLOR_/gm,
);
if (!novel.name) {
novel.name =
chaptersJson.manga.rusName ||
chaptersJson.manga.engName ||
chaptersJson.manga.name;
}
novel.status = statusKey[chaptersJson.manga.status] || NovelStatus.Unknown;
this.ui = chaptersJson?.user?.id;
chaptersRaw = chaptersRaw?.[0]
?.replace("window.__DATA__ = ", "")
?.replace("window._SITE_COLOR_", "")
?.trim()
?.slice(0, -1);
if (!chaptersJson.chapters.list?.length) return novel;
const totalChapters = chaptersJson.chapters.list.length;
const chaptersJson: responseBook = JSON.parse(chaptersRaw);
const totalChapters = chaptersJson.chapters.list?.length || 0;
novel.status = statusKey[chaptersJson.manga.status - 1] || NovelStatus.Unknown;
this.ui = chaptersJson?.user?.id;
const customPage: { [key: number]: string } = {};
const customOrder: { [key: number]: number } = {};
if (chaptersJson.chapters.branches?.length && chaptersJson.chapters.branches.length > 1) {
//if the novel is being translated by more than one team
chaptersJson.chapters.branches.forEach(({ teams, id }) => {
if (teams?.length) {
customPage[id || 0] =
teams.find((team) => team.is_active)?.name || teams[0].name;
}
});
//fixes the chapter's position.
chaptersJson.chapters.list.forEach((chapter) => {
chapter.index = customOrder[chapter.branch_id || 0] || 1;
customOrder[chapter.branch_id || 0] =
(customOrder[chapter.branch_id || 0] || 1) + 1;
});
};
chaptersJson.chapters?.list?.forEach((chapter, chapterIndex) =>
chapters.push({
name:
"Том " + chapter.chapter_volume +
" Глава " + chapter.chapter_number +
(chapter.chapter_name ? " " + chapter.chapter_name.trim() : ""),
url:
this.site + "/" + chaptersJson.manga.slug +
"/v" + chapter.chapter_volume + "/c" + chapter.chapter_number +
"?bid=" + (chapter.branch_id || ""),
releaseTime: dayjs(chapter.chapter_created_at).format("LLL"),
chapterNumber: totalChapters - chapterIndex,
}),
);
novel.chapters = chapters.reverse();
const chapters: Plugin.ChapterItem[] = [];
chaptersJson.chapters.list.forEach((chapter, chapterIndex) =>
chapters.push({
name:
"Том " + chapter.chapter_volume +
" Глава " + chapter.chapter_number +
(chapter.chapter_name ? " " + chapter.chapter_name.trim() : ""),
path:
"/" + chaptersJson.manga.slug +
"/v" + chapter.chapter_volume +
"/c" + chapter.chapter_number +
"?bid=" + (chapter.branch_id || ""),
releaseTime: dayjs(chapter.chapter_created_at).format("LLL"),
chapterNumber:
customOrder[chapter.branch_id || 0] - (chapter.index || 0) ||
totalChapters - chapterIndex,
page: customPage[chapter.branch_id || 0] || "Основной перевод",
}),
);
novel.chapters =
chaptersJson.chapters.branches?.length &&
chaptersJson.chapters.branches.length > 1
? chapters.sort((a, b) => {
if ((a.page || 0) > (b.page || 0)) return 1;
if ((a.page || 0) < (b.page || 0)) return -1;
return (a.chapterNumber || 0) - (b.chapterNumber || 0);
})
: chapters.reverse();
}
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
async parseChapter(chapterPath: string): Promise<string> {
const result = await fetchApi(
chapterUrl + (this.ui ? "&ui=" + this.ui : ""),
this.site + chapterPath + (this.ui ? "&ui=" + this.ui : ""),
).then((res) => res.text());
const loadedCheerio = parseHTML(result);
@@ -160,21 +192,18 @@ class RLIB implements Plugin.PluginBase {
return chapterText || "";
}
async searchNovels(
searchTerm: string,
//pageNo: number | undefined = 1,
): Promise<Plugin.NovelItem[]> {
async searchNovels(searchTerm: string): Promise<Plugin.NovelItem[]> {
const result = await fetchApi(
`${this.site}/search?q=${searchTerm}&type=manga`,
this.site + "/search?q=" + searchTerm + "&type=manga",
);
const body = (await result.json()) as Manga[];
const novels: Plugin.NovelItem[] = [];
body.forEach((novel) =>
novels.push({
name: novel?.rus_name || novel.name,
cover: novel?.coverImage,
url: novel?.href || this.site + "/" + novel.slug,
name: novel.rus_name || novel.name,
cover: novel.coverImage,
path: "/" + novel.slug,
}),
);
@@ -396,6 +425,11 @@ class RLIB implements Plugin.PluginBase {
],
type: FilterTypes.ExcludableCheckboxGroup,
},
require_chapters: {
label: "Только проекты с главами",
value: true,
type: FilterTypes.Switch,
},
} satisfies Filters;
}
@@ -424,12 +458,13 @@ interface Manga {
href?: string;
}
interface Chapters {
list?: ListEntity[] | null;
teams?: TeamsEntity[] | null;
branches?: BranchesEntity[] | null;
is_paid?: null[] | null;
list?: ListEntity[];
teams?: TeamsEntity[];
branches?: BranchesEntity[];
is_paid?: string[] | null;
}
interface ListEntity {
index?: number; //crutch
chapter_id: number;
chapter_slug: string;
chapter_name: string;