Fix: non-english broken plugins (#701)

* fix epiknovel

* fix: hasutl

* fix: Novelas Ligera

* fix: ReinoWuxia

* fix: Oasis

* fix: json script

* fix: Skynovels

* fix: Yuuki Tls

* fix: Agitoon

* fix: Syosetu

* fix: IndoWebNovel

* fix: Novel Ringan

* fix: Sakura Novel

* fix: Hako

* minor: type checking when PRing
This commit is contained in:
nyagami
2024-01-20 21:20:28 +07:00
committed by GitHub
parent ba718784a5
commit 65ae9ba112
45 changed files with 5606 additions and 1998 deletions
-142
View File
@@ -1,142 +0,0 @@
import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
export const id = "HasuTL";
export const name = "Hasu Translations";
export const site = "https://hasutl.wordpress.com/";
export const version = "1.0.0";
export const icon = "src/es/hasutl/icon.png";
const baseUrl = site;
export const popularNovels: Plugin.popularNovels = async function (page) {
let url = baseUrl + "light-novels-activas/";
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio("div.wp-block-columns").each(function () {
const novelName = loadedCheerio(this).find(".wp-block-button").text();
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this)
.find(".wp-block-button > a")
.attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novelUrl) {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Novel.instance = {
url,
};
novel.url = novelUrl;
novel.name = loadedCheerio(".post-header").text();
novel.cover = loadedCheerio(".featured-media > img").attr("src");
let novelSummary = loadedCheerio(".post-content").find("p").html()!;
novel.summary = novelSummary;
let novelChapters: Chapter.Item[] = [];
loadedCheerio(".wp-block-media-text__content")
.find("a")
.each(function () {
const chapterName = loadedCheerio(this).text().trim();
const releaseDate = null;
let chapterUrl = loadedCheerio(this).attr("href");
if (!chapterUrl) return;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
});
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".post-content").html();
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
const url = `${baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".post-container ").each(function () {
const novelName = loadedCheerio(this).find(".post-header").text();
if (
!novelName.includes("Cap") &&
!novelName.includes("Vol") &&
!novelName.includes("Light Novels")
) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
};
export const fetchImage: Plugin.fetchImage = fetchFile;
+145
View File
@@ -0,0 +1,145 @@
import { load as parseHTML } from "cheerio";
import { fetchFile } from "@libs/fetch";
import { Plugin } from "@typings/plugin";
import { Filters } from "@libs/filterInputs";
class HasulTL implements Plugin.PluginBase {
id = "HasuTL";
name = "Hasu Translations";
icon = "src/es/hasutl/icon.png";
site = "https://hasutl.wordpress.com/";
filters?: Filters | undefined;
version = "1.0.0";
baseUrl = this.site
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
let url = this.baseUrl + "light-novels-activas/";
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio("div.wp-block-columns").each(function () {
const novelName = loadedCheerio(this).find(".wp-block-button").text();
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this)
.find(".wp-block-button > a")
.attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const url = novelUrl;
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Plugin.SourceNovel = {
url,
};
novel.url = novelUrl;
novel.name = loadedCheerio(".post-header").text();
novel.cover = loadedCheerio(".featured-media > img").attr("src");
let novelSummary = loadedCheerio(".post-content").find("p").html()!;
novel.summary = novelSummary;
let novelChapters: Plugin.ChapterItem[] = [];
loadedCheerio(".wp-block-media-text__content")
.find("a")
.each(function () {
const chapterName = loadedCheerio(this).text().trim();
const releaseDate = null;
let chapterUrl = loadedCheerio(this).attr("href");
if (!chapterUrl) return;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
});
novel.chapters = novelChapters;
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
const url = chapterUrl;
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".post-content").html() || '';
return chapterText;
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
const url = `${this.baseUrl}?s=${searchTerm}&post_type=wp-manga`;
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".post-container").each(function () {
const novelName = loadedCheerio(this).find(".post-header").text();
if (
!novelName.includes("Cap") &&
!novelName.includes("Vol") &&
!novelName.includes("Light Novels")
) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
}
async fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export default new HasulTL();
-177
View File
@@ -1,177 +0,0 @@
import { load as parseHTML } from "cheerio";
import { fetchApi, fetchFile } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
export const id = "ligera.com";
export const name = "Novelas Ligera";
export const site = "https://novelasligera.com/";
export const version = "1.0.0";
export const icon = "src/es/novelasligera/icon.png";
const baseUrl = site;
export const popularNovels: Plugin.popularNovels = async function (page) {
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".elementor-column").each(function () {
const novelName = loadedCheerio(this)
.find(".widget-image-caption.wp-caption-text")
.text();
if (novelName) {
const novelCover = loadedCheerio(this)
.find("a > img")
.attr("data-lazy-src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novelUrl) {
const url = baseUrl + "novela/" + novelUrl;
// console.log(url);
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Novel.instance = { url };
novel.name = loadedCheerio("h1").text();
novel.cover = loadedCheerio(".elementor-widget-container")
.find("img")
.attr("src");
loadedCheerio(".elementor-row")
.find("p")
.each(function () {
if (loadedCheerio(this).text().includes("Autor:")) {
novel.author = loadedCheerio(this)
.text()
.replace("Autor:", "")
.trim();
}
if (loadedCheerio(this).text().includes("Estado:")) {
novel.status = loadedCheerio(this)
.text()
.replace("Estado: ", "")
.trim();
}
if (loadedCheerio(this).text().includes("Género:")) {
loadedCheerio(this).find("span").remove();
novel.genres = loadedCheerio(this)
.text()
.replace(/,\s/g, ",");
}
});
novel.summary = loadedCheerio(
".elementor-text-editor.elementor-clearfix"
).text();
let novelChapters: Chapter.Item[] = [];
loadedCheerio(".elementor-accordion-item").remove();
loadedCheerio(".elementor-tab-content")
.find("li")
.each(function () {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapterUrl = loadedCheerio(this).find("a").attr("href");
if (!chapterUrl) return;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
});
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
const url = chapterUrl;
// console.log(url);
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
loadedCheerio(".osny-nightmode.osny-nightmode--left").remove();
loadedCheerio(".code-block.code-block-1").remove();
loadedCheerio(".adsb30").remove();
loadedCheerio(".saboxplugin-wrap").remove();
loadedCheerio(".wp-post-navigation").remove();
let chapterText = loadedCheerio(".entry-content").html();
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
const url = baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
// console.log(url);
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".inside-article").each(function () {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
let novelName;
if (novelUrl) {
novelName = novelUrl.replace(/-/g, " ").replace(/^./, function (x) {
return x.toUpperCase();
});
}
novelUrl += "/";
if (!novelName || !novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
novels = [{ ...novels[1] }];
return novels;
};
export const fetchImage: Plugin.fetchImage = fetchFile;
+180
View File
@@ -0,0 +1,180 @@
import { load as parseHTML } from "cheerio";
import { fetchFile } from "@libs/fetch";
import { Plugin } from "@typings/plugin";
import { Filters } from "@libs/filterInputs";
class Ligera implements Plugin.PluginBase {
id = "ligera.com";
name = "Novelas Ligera";
icon = "src/es/novelasligera/icon.png";
site = "https://novelasligera.com/";
filters?: Filters | undefined;
version = "1.0.0";
baseUrl = this.site;
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
let url = this.baseUrl;
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".elementor-column").each(function () {
const novelName = loadedCheerio(this)
.find(".widget-image-caption.wp-caption-text")
.text();
if (novelName) {
const novelCover = loadedCheerio(this)
.find("a > img")
.attr("data-lazy-src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const url = this.baseUrl + "novela/" + novelUrl;
// console.log(url);
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Plugin.SourceNovel = { url };
novel.name = loadedCheerio("h1").text();
novel.cover = loadedCheerio(".elementor-widget-container")
.find("img")
.attr("src");
loadedCheerio(".elementor-row")
.find("p")
.each(function () {
if (loadedCheerio(this).text().includes("Autor:")) {
novel.author = loadedCheerio(this)
.text()
.replace("Autor:", "")
.trim();
}
if (loadedCheerio(this).text().includes("Estado:")) {
novel.status = loadedCheerio(this)
.text()
.replace("Estado: ", "")
.trim();
}
if (loadedCheerio(this).text().includes("Género:")) {
loadedCheerio(this).find("span").remove();
novel.genres = loadedCheerio(this)
.text()
.replace(/,\s/g, ",");
}
});
novel.summary = loadedCheerio(
".elementor-text-editor.elementor-clearfix"
).text();
let novelChapters: Plugin.ChapterItem[] = [];
loadedCheerio(".elementor-accordion-item").remove();
loadedCheerio(".elementor-tab-content")
.find("li")
.each(function () {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapterUrl = loadedCheerio(this).find("a").attr("href");
if (!chapterUrl) return;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
});
novel.chapters = novelChapters;
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
const url = chapterUrl;
// console.log(url);
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
loadedCheerio(".osny-nightmode.osny-nightmode--left").remove();
loadedCheerio(".code-block.code-block-1").remove();
loadedCheerio(".adsb30").remove();
loadedCheerio(".saboxplugin-wrap").remove();
loadedCheerio(".wp-post-navigation").remove();
let chapterText = loadedCheerio(".entry-content").html() || '';
return chapterText;
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
const url = this.baseUrl + "?s=" + searchTerm + "&post_type=wp-manga";
// console.log(url);
const result = await fetch(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".inside-article").each(function () {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
let novelName;
if (novelUrl) {
novelName = novelUrl.replace(/-/g, " ").replace(/^./, function (x) {
return x.toUpperCase();
});
}
novelUrl += "/";
if (!novelName || !novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
novels = [{ ...novels[1] }];
return novels;
}
async fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export default new Ligera();
-214
View File
@@ -1,214 +0,0 @@
import { fetchApi, fetchFile } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
import { defaultCover } from "@libs/defaultCover";
const pluginId = "awuxia.com";
const baseUrl = "http://www.reinowuxia.com/";
function getNovelName(y: string | undefined) {
return y?.replace(/-/g, " ").replace(/(?:^|\s)\S/g, (a) => a.toUpperCase());
}
export const popularNovels: Plugin.popularNovels = async function (page) {
let url = baseUrl + "p/todas-las-novelas.html";
let headers = {
"User-Agent":
"'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36",
};
const result = await fetchApi(url, {
method: "GET",
headers: headers,
});
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".post-body.entry-content")
.find("a")
.each(function () {
let novelName = loadedCheerio(this)
.attr("href")
?.split("/")
.pop()
?.replace(".html", "");
novelName = getNovelName(novelName);
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).attr("href");
if (!novelName || !novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novelUrl) {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Novel.instance = { url };
novel.name = loadedCheerio("h1.post-title").text().trim();
novel.cover = loadedCheerio("div.separator").find("a").attr("href");
novel.status = "";
loadedCheerio("div > b").each(function () {
const detailName = loadedCheerio(this).text();
let detail = loadedCheerio(this)[0].nextSibling;
if (detailName && detail) {
detail = detail.nodeValue;
if (detailName.includes("Autor")) {
novel.author = detail.replace("Autor:", "");
}
if (detailName.includes("Estatus")) {
novel.status = detail.replace("Estatus: ", "");
}
if (detailName.includes("Géneros:")) {
novel.genres = detail
.replace("Géneros: ", "")
.replace(/,\s/g, ",");
}
}
});
let novelChapters: Chapter.Item[] = [];
loadedCheerio("div").each(function () {
const detailName = loadedCheerio(this).text();
if (detailName.includes("Sinopsis")) {
novel.summary =
loadedCheerio(this).next().text() !== ""
? loadedCheerio(this)
.next()
.text()
.replace("Sinopsis", "")
.trim()
: loadedCheerio(this)
.next()
.next()
.text()
.replace("Sinopsis", "")
.trim();
}
if (detailName.includes("Lista de Capítulos")) {
loadedCheerio(this)
.find("a")
.each(function (res) {
const chapterName = loadedCheerio(this).text();
let chapterUrl = loadedCheerio(this).attr("href");
const releaseDate = null;
if (
chapterName &&
chapterUrl &&
!novelChapters.some(
(chap) => chap.name === chapterName
)
) {
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
}
});
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".post-body.entry-content").html();
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async (searchTerm) => {
const url = `${baseUrl}search?q=${searchTerm}`;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".date-outer").each(function () {
let novelName = loadedCheerio(this)
.find("a")
.attr("href")
?.split("/")
.pop()
?.replace(/-capitulo(.*?).html/, "");
const novelUrl = novelName + ".html/";
novelName = getNovelName(novelName);
const exists = novels.some((novel) => novel.name === novelName);
if (!exists) {
const novelCover = defaultCover;
if (!novelUrl || !novelName) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
};
module.exports = {
id: pluginId,
name: "ReinoWuxia",
site: baseUrl,
version: "1.0.0",
icon: "src/es/novelawuxia/icon.png",
popularNovels,
parseNovelAndChapters,
parseChapter,
searchNovels,
fetchImage: fetchFile,
};
+203
View File
@@ -0,0 +1,203 @@
import { fetchApi, fetchFile } from "@libs/fetch";
import { Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
import { defaultCover } from "@libs/defaultCover";
import { Filters } from "@libs/filterInputs";
class ReinoWuxia implements Plugin.PluginBase {
id = "awuxia.com";
name = "ReinoWuxia";
icon = "src/es/novelawuxia/icon.png";
filters?: Filters | undefined;
version = "1.0.0";
site = "http://www.reinowuxia.com/"
baseUrl = this.site;
getNovelName(y: string | undefined) {
return y?.replace(/-/g, " ").replace(/(?:^|\s)\S/g, (a) => a.toUpperCase());
}
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
let url = this.baseUrl + "p/todas-las-novelas.html";
const result = await fetchApi(url, {
method: "GET",
});
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".post-body.entry-content")
.find("a")
.each( (idx, ele) => {
let novelName = loadedCheerio(ele)
.attr("href")
?.split("/")
.pop()
?.replace(".html", "");
novelName = this.getNovelName(novelName);
const novelCover = loadedCheerio(ele).find("img").attr("src");
let novelUrl = loadedCheerio(ele).attr("href");
if (!novelName || !novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Plugin.SourceNovel = { url };
novel.name = loadedCheerio("h1.post-title").text().trim();
novel.cover = loadedCheerio("div.separator").find("a").attr("href");
novel.status = "";
loadedCheerio("div > b").each(function () {
const detailName = loadedCheerio(this).text();
let detail = loadedCheerio(this)[0].nextSibling;
if (detailName && detail) {
const text = loadedCheerio(detail).text();
if (detailName.includes("Autor")) {
novel.author = text.replace("Autor:", "");
}
if (detailName.includes("Estatus")) {
novel.status = text.replace("Estatus: ", "");
}
if (detailName.includes("Géneros:")) {
novel.genres = text
.replace("Géneros: ", "")
.replace(/,\s/g, ",");
}
}
});
let novelChapters: Plugin.ChapterItem[] = [];
loadedCheerio("div").each(function () {
const detailName = loadedCheerio(this).text();
if (detailName.includes("Sinopsis")) {
novel.summary =
loadedCheerio(this).next().text() !== ""
? loadedCheerio(this)
.next()
.text()
.replace("Sinopsis", "")
.trim()
: loadedCheerio(this)
.next()
.next()
.text()
.replace("Sinopsis", "")
.trim();
}
if (detailName.includes("Lista de Capítulos")) {
loadedCheerio(this)
.find("a")
.each(function (res) {
const chapterName = loadedCheerio(this).text();
let chapterUrl = loadedCheerio(this).attr("href");
const releaseDate = null;
if (
chapterName &&
chapterUrl &&
!novelChapters.some(
(chap) => chap.name === chapterName
)
) {
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
}
});
novel.chapters = novelChapters;
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".post-body.entry-content").html() || '';
return chapterText;
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
const url = `${this.baseUrl}search?q=${searchTerm}`;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".date-outer").each((idx, ele) => {
let novelName = loadedCheerio(ele)
.find("a")
.attr("href")
?.split("/")
.pop()
?.replace(/-capitulo(.*?).html/, "");
const novelUrl = novelName + ".html/";
novelName = this.getNovelName(novelName);
const exists = novels.some((novel) => novel.name === novelName);
if (!exists) {
const novelCover = defaultCover;
if (!novelUrl || !novelName) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
}
async fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export default new ReinoWuxia();
-164
View File
@@ -1,164 +0,0 @@
import { fetchFile, fetchApi } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
export const id = "oasisTL.wp";
export const name = "Oasis Translations";
export const site = "https://oasistranslations.wordpress.com/";
export const version = "1.0.0";
export const icon = "src/es/oasistranslations/icon.png";
const baseUrl = site;
export const popularNovels: Plugin.popularNovels = async function (page) {
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".menu-item-1819")
.find(".sub-menu > li")
.each(function () {
const novelName = loadedCheerio(this).text();
if (!novelName.match(/Activas|Finalizadas|Dropeadas/)) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novelUrl) {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Novel.instance = { url };
novel.name = loadedCheerio("h1.entry-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.cover = loadedCheerio('img[loading="lazy"]').attr("src");
loadedCheerio(".entry-content > p").each(function (res) {
if (loadedCheerio(this).text().includes("Autor")) {
let details = loadedCheerio(this).html()!;
details = details.match(/<\/strong>(.|\n)*?<br>/g);
details = details.map((detail) =>
detail.replace(/<strong>|<\/strong>|<br>|:\s/g, "")
);
novel.genres = "";
novel.author = details[2];
novel.genres = details[4].replace(/\s|&nbsp;/g, "");
}
});
// let novelSummary = $(this).next().html();
novel.summary = "";
let novelChapters: Chapter.Item[] = [];
// if ($(".entry-content").find("li").length) {
loadedCheerio(".entry-content")
.find("a")
.each(function () {
let chapterUrl = loadedCheerio(this).attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
loadedCheerio("div#jp-post-flair").remove();
let chapterText = loadedCheerio(".entry-content").html();
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
searchTerm = searchTerm.toLowerCase();
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".menu-item-1819")
.find(".sub-menu > li")
.each(function () {
const novelName = loadedCheerio(this).text();
if (!novelName.match(/Activas|Finalizadas|Dropeadas/)) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
novels = novels.filter((novel) =>
novel.name.toLowerCase().includes(searchTerm)
);
return novels;
};
export const fetchImage: Plugin.fetchImage = fetchFile;
+171
View File
@@ -0,0 +1,171 @@
import { fetchFile, fetchApi } from "@libs/fetch";
import { Filters } from "@libs/filterInputs";
import { Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
export const id = "oasisTL.wp";
export const name = "Oasis Translations";
export const site = "https://oasistranslations.wordpress.com/";
export const version = "1.0.0";
export const icon = "src/es/oasistranslations/icon.png";
const baseUrl = site;
class Oasis implements Plugin.PluginBase {
id = "oasisTL.wp";
name = "Oasis Translations";
site = "https://oasistranslations.wordpress.com/";
version = "1.0.0";
filters?: Filters | undefined;
icon = "src/es/oasistranslations/icon.png";
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".menu-item-1819")
.find(".sub-menu > li")
.each(function () {
const novelName = loadedCheerio(this).text();
if (!novelName.match(/Activas|Finalizadas|Dropeadas/)) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Plugin.SourceNovel = { url };
novel.name = loadedCheerio("h1.entry-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.cover = loadedCheerio('img[loading="lazy"]').attr("src");
loadedCheerio(".entry-content > p").each(function (res) {
if (loadedCheerio(this).text().includes("Autor")) {
const details = loadedCheerio(this).html()?.match(/<\/strong>(.|\n)*?<br>/g)?.
map((detail) => detail.replace(/<strong>|<\/strong>|<br>|:\s/g, ""));
novel.genres = "";
if (details){
novel.author = details[2];
novel.genres = details[4].replace(/\s|&nbsp;/g, "");
}
}
});
// let novelSummary = $(this).next().html();
novel.summary = "";
let novelChapters: Plugin.ChapterItem[] = [];
// if ($(".entry-content").find("li").length) {
loadedCheerio(".entry-content")
.find("a")
.each(function () {
let chapterUrl = loadedCheerio(this).attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
novel.chapters = novelChapters;
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
loadedCheerio("div#jp-post-flair").remove();
let chapterText = loadedCheerio(".entry-content").html() || '';
return chapterText;
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
searchTerm = searchTerm.toLowerCase();
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".menu-item-1819")
.find(".sub-menu > li")
.each(function () {
const novelName = loadedCheerio(this).text();
if (!novelName.match(/Activas|Finalizadas|Dropeadas/)) {
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
}
});
novels = novels.filter((novel) =>
novel.name.toLowerCase().includes(searchTerm)
);
return novels;
}
async fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export default new Oasis();
@@ -1,21 +1,22 @@
import { fetchApi, fetchFile } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
import { Filters } from "@libs/filterInputs";
import { Plugin } from "@typings/plugin";
export const id = "skynovels.net";
export const name = "SkyNovels";
export const site = "https://www.skynovels.net/";
export const version = "1.0.0";
export const icon = "src/es/skynovels/icon.png";
class SkyNovels implements Plugin.PluginBase {
id = "skynovels.net";
name = "SkyNovels";
site = "https://www.skynovels.net/";
version = "1.0.0";
icon = "src/es/skynovels/icon.png";
baseUrl = this.site;
const baseUrl = site;
export const popularNovels: Plugin.popularNovels = async function (page) {
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
const url = "https://api.skynovels.net/api/novels?&q";
const result = await fetchApi(url);
const body = await result.json() as response;
const novels: Novel.Item[] = [];
const novels: Plugin.NovelItem[] = [];
body.novels?.forEach((res) => {
const novelName = res.nvl_title;
@@ -24,7 +25,7 @@ export const popularNovels: Plugin.popularNovels = async function (page) {
res.image +
"/novels/false";
const novelUrl =
baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
this.baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
const novel = { name: novelName, url: novelUrl, cover: novelCover };
@@ -32,11 +33,9 @@ export const popularNovels: Plugin.popularNovels = async function (page) {
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novUrl) {
const novelId = novUrl.split("/")[4];
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const novelId = novelUrl.split("/")[4];
const url =
"https://api.skynovels.net/api/novel/" + novelId + "/reading?&q";
@@ -45,7 +44,7 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
const item = body?.novel?.[0];
let novel: Novel.instance = { url: novUrl };
let novel: Plugin.SourceNovel = { url: novelUrl };
novel.name = item?.nvl_title;
@@ -61,13 +60,13 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.summary = item?.nvl_content;
novel.status = item?.nvl_status;
let novelChapters: Chapter.Item[] = [];
let novelChapters: Plugin.ChapterItem[] = [];
item?.volumes?.forEach((volume) => {
volume?.chapters?.forEach((chapter) => {
const chapterName = chapter.chp_index_title;
const releaseDate = new Date(chapter.createdAt).toDateString();
const chapterUrl = novUrl + chapter.id + "/" + chapter.chp_name;
const chapterUrl = novelUrl + chapter.id + "/" + chapter.chp_name;
const chap = {
name: chapterName,
@@ -82,10 +81,9 @@ export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapUrl) {
let chapterId: string = chapUrl.split("/")[6];
}
async parseChapter(chapterUrl: string): Promise<string> {
let chapterId: string = chapterUrl.split("/")[6];
const url = `https://api.skynovels.net/api/novel-chapter/${chapterId}`;
const result = await fetchApi(url);
@@ -96,9 +94,8 @@ export const parseChapter: Plugin.parseChapter = async function (chapUrl) {
let chapterText = item?.chp_content || '404';
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
searchTerm = searchTerm.toLowerCase();
const url = "https://api.skynovels.net/api/novels?&q";
@@ -109,7 +106,7 @@ export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
novel.nvl_title.toLowerCase().includes(searchTerm)
);
const novels: Novel.Item[] = [];
const novels: Plugin.NovelItem[] = [];
results?.forEach((res) => {
const novelName = res.nvl_title;
@@ -118,7 +115,7 @@ export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
res.image +
"/novels/false";
const novelUrl =
baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
this.baseUrl + "novelas/" + res.id + "/" + res.nvl_name + "/";
const novel = { name: novelName, url: novelUrl, cover: novelCover };
@@ -126,9 +123,13 @@ export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
});
return novels;
};
}
async fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export const fetchImage: Plugin.fetchImage = fetchFile;
export default new SkyNovels();
interface response {
novels?: (NovelsEntity)[] | null;
-180
View File
@@ -1,180 +0,0 @@
import { fetchApi, fetchFile } from "@libs/fetch";
import { Chapter, Novel, Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
export const id = "yuukitls.com";
export const name = "Yuuki Tls";
export const site = "https://yuukitls.com/";
export const version = "1.0.0";
export const icon = "src/es/yuukitls/icon.png";
const baseUrl = site;
export const popularNovels: Plugin.popularNovels = async function (page) {
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".quadmenu-navbar-collapse ul li:nth-child(2)")
.find("li")
.each(function () {
const novelName = loadedCheerio(this)
.text()
.replace(/[\s\n]+/g, " ");
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
};
export const parseNovelAndChapters: Plugin.parseNovelAndChapters =
async function (novelUrl) {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Novel.instance = {
url,
};
novel.name = loadedCheerio("h1.entry-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.cover = loadedCheerio('img[loading="lazy"]').attr("src");
loadedCheerio(".entry-content")
.find("div")
.each(function () {
if (loadedCheerio(this).text().includes("Escritor:")) {
novel.author = loadedCheerio(this)
.text()
.replace("Escritor: ", "")
.trim();
}
if (loadedCheerio(this).text().includes("Género:")) {
novel.genres = loadedCheerio(this)
.text()
.replace(/Género: |\s/g, "");
}
if (loadedCheerio(this).text().includes("Sinopsis:")) {
novel.summary = loadedCheerio(this).next().text();
}
});
let novelChapters: Chapter.Item[] = [];
if (loadedCheerio(".entry-content").find("li").length) {
loadedCheerio(".entry-content")
.find("li")
.each(function () {
let chapterUrl = loadedCheerio(this).find("a").attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
} else {
loadedCheerio(".entry-content")
.find("p")
.each(function () {
let chapterUrl = loadedCheerio(this).find("a").attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
}
novel.chapters = novelChapters;
return novel;
};
export const parseChapter: Plugin.parseChapter = async function (chapterUrl) {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".entry-content").html();
return chapterText;
};
export const searchNovels: Plugin.searchNovels = async function (searchTerm) {
searchTerm = searchTerm.toLowerCase();
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Novel.Item[] = [];
loadedCheerio(".menu-item-2869")
.find(".menu-item.menu-item-type-post_type.menu-item-object-post")
.each(function () {
const novelName = loadedCheerio(this).text();
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
novels = novels.filter((novel) =>
novel.name.toLowerCase().includes(searchTerm)
);
return novels;
};
export const fetchImage: Plugin.fetchImage = fetchFile;
+192
View File
@@ -0,0 +1,192 @@
import { fetchApi, fetchFile } from "@libs/fetch";
import { Filters } from "@libs/filterInputs";
import { Plugin } from "@typings/plugin";
import { load as parseHTML } from "cheerio";
export const id = "yuukitls.com";
export const name = "Yuuki Tls";
export const site = "https://yuukitls.com/";
export const version = "1.0.0";
export const icon = "src/es/yuukitls/icon.png";
const baseUrl = site;
class Yuuki implements Plugin.PluginBase {
id = "yuukitls.com";
name = "Yuuki Tls";
icon = "src/es/yuukitls/icon.png";
site = "https://yuukitls.com/";
filters?: Filters | undefined;
version = "1.0.0";
baseUrl = this.site;
async popularNovels(pageNo: number, options: Plugin.PopularNovelsOptions<Filters>): Promise<Plugin.NovelItem[]> {
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".quadmenu-navbar-collapse ul li:nth-child(2)")
.find("li")
.each(function () {
const novelName = loadedCheerio(this)
.text()
.replace(/[\s\n]+/g, " ");
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
return novels;
}
async parseNovelAndChapters(novelUrl: string): Promise<Plugin.SourceNovel> {
const url = novelUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novel: Plugin.SourceNovel = {
url,
};
novel.name = loadedCheerio("h1.entry-title")
.text()
.replace(/[\t\n]/g, "")
.trim();
novel.cover = loadedCheerio('img[loading="lazy"]').attr("src");
loadedCheerio(".entry-content")
.find("div")
.each(function () {
if (loadedCheerio(this).text().includes("Escritor:")) {
novel.author = loadedCheerio(this)
.text()
.replace("Escritor: ", "")
.trim();
}
if (loadedCheerio(this).text().includes("Género:")) {
novel.genres = loadedCheerio(this)
.text()
.replace(/Género: |\s/g, "");
}
if (loadedCheerio(this).text().includes("Sinopsis:")) {
novel.summary = loadedCheerio(this).next().text();
}
});
let novelChapters: Plugin.ChapterItem[] = [];
if (loadedCheerio(".entry-content").find("li").length) {
loadedCheerio(".entry-content")
.find("li")
.each(function () {
let chapterUrl = loadedCheerio(this).find("a").attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
} else {
loadedCheerio(".entry-content")
.find("p")
.each(function () {
let chapterUrl = loadedCheerio(this).find("a").attr("href");
if (chapterUrl && chapterUrl.includes(baseUrl)) {
const chapterName = loadedCheerio(this).text();
const releaseDate = null;
const chapter = {
name: chapterName,
releaseTime: releaseDate,
url: chapterUrl,
};
novelChapters.push(chapter);
}
});
}
novel.chapters = novelChapters;
return novel;
}
async parseChapter(chapterUrl: string): Promise<string> {
const url = chapterUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let chapterText = loadedCheerio(".entry-content").html() || '';
return chapterText;
}
async searchNovels(searchTerm: string, pageNo: number): Promise<Plugin.NovelItem[]> {
searchTerm = searchTerm.toLowerCase();
let url = baseUrl;
const result = await fetchApi(url);
const body = await result.text();
let loadedCheerio = parseHTML(body);
let novels: Plugin.NovelItem[] = [];
loadedCheerio(".menu-item-2869")
.find(".menu-item.menu-item-type-post_type.menu-item-object-post")
.each(function () {
const novelName = loadedCheerio(this).text();
const novelCover = loadedCheerio(this).find("img").attr("src");
let novelUrl = loadedCheerio(this).find("a").attr("href");
if (!novelUrl) return;
const novel = {
name: novelName,
cover: novelCover,
url: novelUrl,
};
novels.push(novel);
});
novels = novels.filter((novel) =>
novel.name.toLowerCase().includes(searchTerm)
);
return novels;
}
fetchImage(url: string): Promise<string | undefined> {
return fetchFile(url);
}
}
export default new Yuuki();