fix: Bug Fixes and Feature Improvements to Linovelib Plugin (#1984)
* fix(linovelib): Searching not work * ci: fix branch cannot be correctly identified in forked environment * fix: BRANCH cannot be identified * fix(linovelib): correctly get cover image in redirect case of searching * fix: why we need a prefix slash here? remove it * chore(linovelib): update linovelib plugin version * fix: before LNReader puts its default UA to chrome, forcely set LNReader plugin's UA to Chrome's UA * refactor: intgrates FetchInit into plugin * feat: add chapter name transform * feat(linovelib): add decryptor for shuffle scramble of original html * feat(linovelib): use external server to extract shuffle coefficients * fix(linovelib): extract author name more precisely * fix(linovelib): set Referer header to bypass anti-leeching/hotlinking of image source Also, use LocalStorage to store coefficients and chapter.js version * refactor: delete FetchInit definition in this plugin * fix(linovelib): replace localStorage with storage utility for better data management * fix(linovelib): update storage import path to use the correct library * feat(linovelib): Implement chapter number * refactor(linovelib): as mobile site equipped with strong cloudflare challenge, move most of parsing logic to LDS server * fix(linovelib): update API calls to use query parameters instead of POST requests for novel, chapter, and search endpoints * fix(linovelib): add caching mechanism for novel and chapter parsing to reduce API calls * refactor(linovelib): refactor server URL handling to use class property for API requests * fix: apply changes pointed by review * docs(linovelib): make some comments
This commit is contained in:
Generated
+3
-2
@@ -4755,9 +4755,10 @@
|
|||||||
},
|
},
|
||||||
"node_modules/domhandler": {
|
"node_modules/domhandler": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
"license": "BSD-2-Clause",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"domelementtype": "^2.3.0"
|
"domelementtype": "^2.3.0"
|
||||||
},
|
},
|
||||||
@@ -12030,7 +12031,7 @@
|
|||||||
},
|
},
|
||||||
"domhandler": {
|
"domhandler": {
|
||||||
"version": "5.0.3",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
|
"resolved": "https://registry.npmmirror.com/domhandler/-/domhandler-5.0.3.tgz",
|
||||||
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
|||||||
+53
-463
@@ -1,15 +1,35 @@
|
|||||||
import { CheerioAPI, load as parseHTML } from 'cheerio';
|
import { load as parseHTML } from 'cheerio';
|
||||||
import { fetchText } from '@libs/fetch';
|
import { fetchText } from '@libs/fetch';
|
||||||
import { FilterTypes, Filters } from '@libs/filterInputs';
|
import { FilterTypes, Filters } from '@libs/filterInputs';
|
||||||
import { Plugin } from '@/types/plugin';
|
import { Plugin } from '@/types/plugin';
|
||||||
import { NovelStatus } from '@libs/novelStatus';
|
import { storage } from '@libs/storage';
|
||||||
|
|
||||||
class Linovelib implements Plugin.PluginBase {
|
class Linovelib implements Plugin.PluginBase {
|
||||||
id = 'linovelib';
|
id = 'linovelib';
|
||||||
name = 'Linovelib';
|
name = 'Linovelib';
|
||||||
icon = 'src/cn/linovelib/icon.png';
|
icon = 'src/cn/linovelib/icon.png';
|
||||||
site = 'https://www.bilinovel.com';
|
site = 'https://www.bilinovel.com';
|
||||||
version = '1.1.3';
|
version = '1.2.0';
|
||||||
|
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
|
||||||
|
method: 'GET',
|
||||||
|
headers: {
|
||||||
|
'User-Agent':
|
||||||
|
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 Edg/144.0.0.0',
|
||||||
|
'Referer': 'https://www.linovelib.com',
|
||||||
|
'Accept':
|
||||||
|
'image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
webStorageUtilized = true;
|
||||||
|
// The URL of the custom LDS (Linovelib Descramble Server) URL. Due to complex de-scrambling logic, an external LDS is required.
|
||||||
|
pluginSettings = {
|
||||||
|
host: {
|
||||||
|
value: 'http://example.com',
|
||||||
|
label: 'Custom LDS Host',
|
||||||
|
type: 'Text',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
serverUrl = storage.get('host') || 'http://localhost:5301';
|
||||||
|
|
||||||
async popularNovels(
|
async popularNovels(
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
@@ -34,7 +54,8 @@ class Linovelib implements Plugin.PluginBase {
|
|||||||
const novelName = loadedCheerio(el).find('.book-title').text();
|
const novelName = loadedCheerio(el).find('.book-title').text();
|
||||||
const novelCover = loadedCheerio(el)
|
const novelCover = loadedCheerio(el)
|
||||||
.find('div.book-cover > img')
|
.find('div.book-cover > img')
|
||||||
.attr('data-src');
|
.attr('data-src')
|
||||||
|
?.replace('/https', 'https');
|
||||||
if (!url) return;
|
if (!url) return;
|
||||||
|
|
||||||
const novel = {
|
const novel = {
|
||||||
@@ -50,476 +71,45 @@ class Linovelib implements Plugin.PluginBase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
||||||
const url = this.site + novelPath;
|
// move major logic to LDS
|
||||||
|
const res = await fetchText(
|
||||||
const body = await fetchText(url);
|
`${this.serverUrl}/api/novel?path=${novelPath}`,
|
||||||
if (body === '') throw Error('无法获取小说内容,请检查网络');
|
|
||||||
|
|
||||||
const loadedCheerio = parseHTML(body);
|
|
||||||
|
|
||||||
const novel: Plugin.SourceNovel = {
|
|
||||||
path: novelPath,
|
|
||||||
chapters: [],
|
|
||||||
name: loadedCheerio('#bookDetailWrapper .book-title').text(),
|
|
||||||
};
|
|
||||||
|
|
||||||
novel.cover = loadedCheerio('#bookDetailWrapper img.book-cover').attr(
|
|
||||||
'src',
|
|
||||||
);
|
);
|
||||||
|
const novel = JSON.parse(res) as Plugin.SourceNovel;
|
||||||
novel.summary = loadedCheerio('#bookSummary content').text();
|
|
||||||
|
|
||||||
novel.author = loadedCheerio('#bookDetailWrapper .book-rand-a a').text();
|
|
||||||
|
|
||||||
const meta = loadedCheerio('#bookDetailWrapper .book-meta').text();
|
|
||||||
novel.status = meta.includes('完结')
|
|
||||||
? NovelStatus.Completed
|
|
||||||
: NovelStatus.Ongoing;
|
|
||||||
|
|
||||||
novel.genres = loadedCheerio('.tag-small.red')
|
|
||||||
.children('a')
|
|
||||||
.map((i, el) => loadedCheerio(el).text())
|
|
||||||
.toArray()
|
|
||||||
.join(',');
|
|
||||||
|
|
||||||
// Table of Content is on a different page than the summary page
|
|
||||||
const chapter: Plugin.ChapterItem[] = [];
|
|
||||||
|
|
||||||
const idPattern = /\/(\d+)\.html/;
|
|
||||||
const novelId = url.match(idPattern)?.[1];
|
|
||||||
|
|
||||||
const chaptersUrl = this.site + loadedCheerio('#btnReadBook').attr('href');
|
|
||||||
const chaptersBody = await fetchText(chaptersUrl);
|
|
||||||
|
|
||||||
const chaptersLoadedCheerio = parseHTML(chaptersBody);
|
|
||||||
|
|
||||||
let volumeName: string, chapterId: number;
|
|
||||||
|
|
||||||
chaptersLoadedCheerio('#volumes .chapter-li:not(.volume-cover)').each(
|
|
||||||
(i, el) => {
|
|
||||||
if (chaptersLoadedCheerio(el).hasClass('chapter-bar')) {
|
|
||||||
volumeName = chaptersLoadedCheerio(el).text();
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
const urlPart = chaptersLoadedCheerio(el)
|
|
||||||
.find('.chapter-li-a')
|
|
||||||
.attr('href');
|
|
||||||
const chapterIdMatch = urlPart?.match(idPattern);
|
|
||||||
|
|
||||||
// Sometimes the href attribute does not contain the url, but javascript:cid(0).
|
|
||||||
// Increment the previous chapter ID should result in the right URL
|
|
||||||
if (chapterIdMatch) {
|
|
||||||
chapterId = +chapterIdMatch[1];
|
|
||||||
} else {
|
|
||||||
chapterId++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const chapterUrl = `/novel/${novelId}/${chapterId}.html`;
|
|
||||||
const chapterName =
|
|
||||||
volumeName +
|
|
||||||
' — ' +
|
|
||||||
chaptersLoadedCheerio(el).find('.chapter-index').text().trim();
|
|
||||||
const releaseDate = null;
|
|
||||||
|
|
||||||
if (!chapterId) return;
|
|
||||||
|
|
||||||
chapter.push({
|
|
||||||
name: chapterName,
|
|
||||||
releaseTime: releaseDate,
|
|
||||||
path: chapterUrl,
|
|
||||||
});
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
novel.chapters = chapter;
|
|
||||||
|
|
||||||
return novel;
|
return novel;
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseChapter(chapterPath: string): Promise<string> {
|
async parseChapter(chapterPath: string): Promise<string> {
|
||||||
let chapterName,
|
// move major logic to LDS
|
||||||
chapterText = '',
|
const lastFetchChapterTime =
|
||||||
hasNextPage,
|
storage.get('lastFetchChapterTime_' + chapterPath) || 0;
|
||||||
pageHasNextPage,
|
if (Date.now() - lastFetchChapterTime < 10000) {
|
||||||
pageText = '';
|
return storage.get('chapterContent_' + chapterPath) || '';
|
||||||
let pageNumber = 1;
|
}
|
||||||
|
const res = await fetchText(
|
||||||
/*
|
`${this.serverUrl}/api/chapter?path=${chapterPath}`,
|
||||||
* TODO: Maybe there are other ways to get the translation table
|
);
|
||||||
* It is embed and encrypted inside readtool.js
|
const resObj = JSON.parse(res);
|
||||||
* UPDATE: Decrypted, see skillgg
|
storage.set('lastFetchChapterTime_' + chapterPath, Date.now());
|
||||||
*/
|
storage.set('chapterContent_' + chapterPath, resObj.content);
|
||||||
// const mapping_dict = {
|
return resObj.content;
|
||||||
// '“': '「',
|
|
||||||
// '’': '』',
|
|
||||||
// '': '是',
|
|
||||||
// '': '不',
|
|
||||||
// '': '好',
|
|
||||||
// '': '个',
|
|
||||||
// '': '开',
|
|
||||||
// '': '样',
|
|
||||||
// '': '想',
|
|
||||||
// '': '说',
|
|
||||||
// '': '年',
|
|
||||||
// '': '那',
|
|
||||||
// '': '她',
|
|
||||||
// '': '美',
|
|
||||||
// '': '自',
|
|
||||||
// '': '家',
|
|
||||||
// '': '而',
|
|
||||||
// '': '去',
|
|
||||||
// '': '都',
|
|
||||||
// '': '于',
|
|
||||||
// '': '舔',
|
|
||||||
// '': '他',
|
|
||||||
// '': '只',
|
|
||||||
// '': '看',
|
|
||||||
// '': '来',
|
|
||||||
// '': '用',
|
|
||||||
// '': '道',
|
|
||||||
// '': '得',
|
|
||||||
// '': '乳',
|
|
||||||
// '': '茎',
|
|
||||||
// '': '肉',
|
|
||||||
// '': '胸',
|
|
||||||
// '': '淫',
|
|
||||||
// '': '性',
|
|
||||||
// '': '骚',
|
|
||||||
// '”': '」',
|
|
||||||
// '': '的',
|
|
||||||
// '': '当',
|
|
||||||
// '': '人',
|
|
||||||
// '': '有',
|
|
||||||
// '': '上',
|
|
||||||
// '': '到',
|
|
||||||
// '': '地',
|
|
||||||
// '': '中',
|
|
||||||
// '': '生',
|
|
||||||
// '': '着',
|
|
||||||
// '': '和',
|
|
||||||
// '': '起',
|
|
||||||
// '': '交',
|
|
||||||
// '': '以',
|
|
||||||
// '': '可',
|
|
||||||
// '': '过',
|
|
||||||
// '': '能',
|
|
||||||
// '': '多',
|
|
||||||
// '': '心',
|
|
||||||
// '': '小',
|
|
||||||
// '': '成',
|
|
||||||
// '': '了',
|
|
||||||
// '': '把',
|
|
||||||
// '': '发',
|
|
||||||
// '': '第',
|
|
||||||
// '': '子',
|
|
||||||
// '': '事',
|
|
||||||
// '': '阴',
|
|
||||||
// '': '欲',
|
|
||||||
// '': '里',
|
|
||||||
// '': '私',
|
|
||||||
// '': '臀',
|
|
||||||
// '': '脱',
|
|
||||||
// '': '唇',
|
|
||||||
// '‘': '『',
|
|
||||||
// '': '一',
|
|
||||||
// '': '我',
|
|
||||||
// '': '在',
|
|
||||||
// '': '这',
|
|
||||||
// '': '们',
|
|
||||||
// '': '时',
|
|
||||||
// '': '为',
|
|
||||||
// '': '你',
|
|
||||||
// '': '国',
|
|
||||||
// '': '就',
|
|
||||||
// '': '要',
|
|
||||||
// '': '也',
|
|
||||||
// '': '后',
|
|
||||||
// '': '没',
|
|
||||||
// '': '下',
|
|
||||||
// '': '天',
|
|
||||||
// '': '对',
|
|
||||||
// '': '然',
|
|
||||||
// '': '学',
|
|
||||||
// '': '之',
|
|
||||||
// '': '出',
|
|
||||||
// '': '没',
|
|
||||||
// '': '如',
|
|
||||||
// '': '还',
|
|
||||||
// '': '大',
|
|
||||||
// '': '作',
|
|
||||||
// '': '种',
|
|
||||||
// '': '液',
|
|
||||||
// '': '呻',
|
|
||||||
// '': '射',
|
|
||||||
// '': '穴',
|
|
||||||
// '': '么',
|
|
||||||
// '': '裸',
|
|
||||||
// };
|
|
||||||
const skillgg: Record<string, string> = {
|
|
||||||
'\u201c': '\u300c',
|
|
||||||
'\u201d': '\u300d',
|
|
||||||
'\u2018': '\u300e',
|
|
||||||
'\u2019': '\u300f',
|
|
||||||
'\ue82c': '\u7684',
|
|
||||||
'\ue852': '\u4e00',
|
|
||||||
'\ue82d': '\u662f',
|
|
||||||
'\ue819': '\u4e86',
|
|
||||||
'\ue856': '\u6211',
|
|
||||||
'\ue857': '\u4e0d',
|
|
||||||
'\ue816': '\u4eba',
|
|
||||||
'\ue83c': '\u5728',
|
|
||||||
'\ue830': '\u4ed6',
|
|
||||||
'\ue82e': '\u6709',
|
|
||||||
'\ue836': '\u8fd9',
|
|
||||||
'\ue859': '\u4e2a',
|
|
||||||
'\ue80a': '\u4e0a',
|
|
||||||
'\ue855': '\u4eec',
|
|
||||||
'\ue842': '\u6765',
|
|
||||||
'\ue858': '\u5230',
|
|
||||||
'\ue80b': '\u65f6',
|
|
||||||
'\ue81f': '\u5927',
|
|
||||||
'\ue84a': '\u5730',
|
|
||||||
'\ue853': '\u4e3a',
|
|
||||||
'\ue81e': '\u5b50',
|
|
||||||
'\ue822': '\u4e2d',
|
|
||||||
'\ue813': '\u4f60',
|
|
||||||
'\ue85b': '\u8bf4',
|
|
||||||
'\ue807': '\u751f',
|
|
||||||
'\ue818': '\u56fd',
|
|
||||||
'\ue810': '\u5e74',
|
|
||||||
'\ue812': '\u7740',
|
|
||||||
'\ue851': '\u5c31',
|
|
||||||
'\ue801': '\u90a3',
|
|
||||||
'\ue80c': '\u548c',
|
|
||||||
'\ue815': '\u8981',
|
|
||||||
'\ue84c': '\u5979',
|
|
||||||
'\ue840': '\u51fa',
|
|
||||||
'\ue848': '\u4e5f',
|
|
||||||
'\ue835': '\u5f97',
|
|
||||||
'\ue800': '\u91cc',
|
|
||||||
'\ue826': '\u540e',
|
|
||||||
'\ue863': '\u81ea',
|
|
||||||
'\ue861': '\u4ee5',
|
|
||||||
'\ue854': '\u4f1a',
|
|
||||||
'\ue827': '\u5bb6',
|
|
||||||
'\ue83b': '\u53ef',
|
|
||||||
'\ue85d': '\u4e0b',
|
|
||||||
'\ue84d': '\u800c',
|
|
||||||
'\ue862': '\u8fc7',
|
|
||||||
'\ue81c': '\u5929',
|
|
||||||
'\ue81d': '\u53bb',
|
|
||||||
'\ue860': '\u80fd',
|
|
||||||
'\ue843': '\u5bf9',
|
|
||||||
'\ue82f': '\u5c0f',
|
|
||||||
'\ue802': '\u591a',
|
|
||||||
'\ue831': '\u7136',
|
|
||||||
'\ue84b': '\u4e8e',
|
|
||||||
'\ue837': '\u5fc3',
|
|
||||||
'\ue829': '\u5b66',
|
|
||||||
'\ue85e': '\u4e48',
|
|
||||||
'\ue83a': '\u4e4b',
|
|
||||||
'\ue832': '\u90fd',
|
|
||||||
'\ue808': '\u597d',
|
|
||||||
'\ue841': '\u770b',
|
|
||||||
'\ue821': '\u8d77',
|
|
||||||
'\ue845': '\u53d1',
|
|
||||||
'\ue803': '\u5f53',
|
|
||||||
'\ue828': '\u6ca1',
|
|
||||||
'\ue81b': '\u6210',
|
|
||||||
'\ue83e': '\u53ea',
|
|
||||||
'\ue820': '\u5982',
|
|
||||||
'\ue84e': '\u4e8b',
|
|
||||||
'\ue85a': '\u628a',
|
|
||||||
'\ue806': '\u8fd8',
|
|
||||||
'\ue83f': '\u7528',
|
|
||||||
'\ue833': '\u7b2c',
|
|
||||||
'\ue811': '\u6837',
|
|
||||||
'\ue804': '\u9053',
|
|
||||||
'\ue814': '\u60f3',
|
|
||||||
'\ue80f': '\u4f5c',
|
|
||||||
'\ue84f': '\u79cd',
|
|
||||||
'\ue80e': '\u5f00',
|
|
||||||
'\ue823': '\u7f8e',
|
|
||||||
'\ue849': '\u4e73',
|
|
||||||
'\ue805': '\u9634',
|
|
||||||
'\ue809': '\u6db2',
|
|
||||||
'\ue81a': '\u830e',
|
|
||||||
'\ue844': '\u6b32',
|
|
||||||
'\ue847': '\u547b',
|
|
||||||
'\ue850': '\u8089',
|
|
||||||
'\ue824': '\u4ea4',
|
|
||||||
'\ue85f': '\u6027',
|
|
||||||
'\ue817': '\u80f8',
|
|
||||||
'\ue85c': '\u79c1',
|
|
||||||
'\ue838': '\u7a74',
|
|
||||||
'\ue82a': '\u6deb',
|
|
||||||
'\ue83d': '\u81c0',
|
|
||||||
'\ue82b': '\u8214',
|
|
||||||
'\ue80d': '\u5c04',
|
|
||||||
'\ue839': '\u8131',
|
|
||||||
'\ue834': '\u88f8',
|
|
||||||
'\ue846': '\u9a9a',
|
|
||||||
'\ue825': '\u5507',
|
|
||||||
};
|
|
||||||
const addPage = async (pageCheerio: CheerioAPI) => {
|
|
||||||
const formatPage = async () => {
|
|
||||||
// Remove JS and notice of the website
|
|
||||||
pageCheerio(
|
|
||||||
'#acontent .adsbygoogle, #acontent script, center',
|
|
||||||
).remove();
|
|
||||||
|
|
||||||
// Load lazyloaded images
|
|
||||||
pageCheerio('#acontent img.imagecontent').each((i, el) => {
|
|
||||||
// Sometimes images are either in data-src or src
|
|
||||||
const imgSrc =
|
|
||||||
pageCheerio(el).attr('data-src') || pageCheerio(el).attr('src');
|
|
||||||
if (imgSrc) {
|
|
||||||
// Clean up img element
|
|
||||||
pageCheerio(el)
|
|
||||||
.attr('src', imgSrc)
|
|
||||||
.removeAttr('data-src')
|
|
||||||
.removeClass('lazyload');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Recover the original character
|
|
||||||
pageText = pageCheerio('#acontent').html() || '';
|
|
||||||
pageText = pageText.replace(/./g, char => skillgg[char] || char);
|
|
||||||
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
await formatPage();
|
|
||||||
chapterName =
|
|
||||||
pageCheerio('#atitle + h3').text() +
|
|
||||||
' — ' +
|
|
||||||
pageCheerio('#atitle').text();
|
|
||||||
if (chapterText === '') {
|
|
||||||
chapterText = '<h2>' + chapterName + '</h2>';
|
|
||||||
}
|
|
||||||
chapterText += pageText;
|
|
||||||
};
|
|
||||||
|
|
||||||
const loadPage = async (url: string) => {
|
|
||||||
const headers = {
|
|
||||||
'Accept':
|
|
||||||
'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
|
|
||||||
'Accept-Language':
|
|
||||||
'zh-CN,zh;q=0.9,zh-TW;q=0.8,zh-HK;q=0.7,en;q=0.6,en-GB;q=0.5,en-US;q=0.4',
|
|
||||||
'Cache-Control': 'no-cache',
|
|
||||||
};
|
|
||||||
|
|
||||||
const body = await fetchText(url, { headers });
|
|
||||||
const pageCheerio = parseHTML(body);
|
|
||||||
await addPage(pageCheerio);
|
|
||||||
pageHasNextPage =
|
|
||||||
pageCheerio('#footlink a:last').text() === '下一页' ||
|
|
||||||
pageCheerio('#footlink a:last').text() === '下一頁'
|
|
||||||
? true
|
|
||||||
: false;
|
|
||||||
return { pageCheerio, pageHasNextPage };
|
|
||||||
};
|
|
||||||
|
|
||||||
let url = this.site + chapterPath;
|
|
||||||
const baseUrl = url;
|
|
||||||
do {
|
|
||||||
const page = await loadPage(url);
|
|
||||||
hasNextPage = page.pageHasNextPage;
|
|
||||||
if (hasNextPage === true) {
|
|
||||||
pageNumber++;
|
|
||||||
url = baseUrl.replace(/\.html/gi, `_${pageNumber}` + '.html');
|
|
||||||
}
|
|
||||||
} while (hasNextPage === true);
|
|
||||||
return chapterText;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchNovels(
|
async searchNovels(
|
||||||
searchTerm: string,
|
searchTerm: string,
|
||||||
pageNo: number,
|
pageNo: number,
|
||||||
): Promise<Plugin.NovelItem[]> {
|
): Promise<Plugin.NovelItem[]> {
|
||||||
const url = `${this.site}/search/${encodeURI(searchTerm)}_${pageNo}.html`;
|
// move major logic to LDS
|
||||||
|
const lastSearchTime = storage.get('lastSearchTime_' + this.id) || 0;
|
||||||
const body = await fetchText(url);
|
if (Date.now() - lastSearchTime < 5000) {
|
||||||
if (body === '') throw Error('无法获取搜索结果,请检查网络');
|
return [];
|
||||||
|
}
|
||||||
const pageCheerio = parseHTML(body);
|
const res = await fetchText(
|
||||||
|
`${this.serverUrl}/api/search?keyword=${encodeURIComponent(searchTerm)}`,
|
||||||
const novels: Plugin.NovelItem[] = [];
|
);
|
||||||
|
const novelsData = JSON.parse(res).results as Plugin.NovelItem[];
|
||||||
// const addPage = async (pageCheerio: CheerioAPI, redirect: string) => {
|
storage.set('lastSearchTime_' + this.id, Date.now());
|
||||||
// const loadSearchResults = () => {
|
return novelsData;
|
||||||
// pageCheerio(".book-ol .book-layout").each((i, el) => {
|
|
||||||
// let nUrl = pageCheerio(el).attr("href");
|
|
||||||
|
|
||||||
// const novelName = pageCheerio(el)
|
|
||||||
// .find(".book-title")
|
|
||||||
// .text();
|
|
||||||
// const novelCover = pageCheerio(el)
|
|
||||||
// .find("div.book-cover > img")
|
|
||||||
// .attr("data-src");
|
|
||||||
// const novelUrl = this.site + nUrl;
|
|
||||||
|
|
||||||
// if (!nUrl) return;
|
|
||||||
|
|
||||||
// novels.push({
|
|
||||||
// name: novelName,
|
|
||||||
// url: novelUrl,
|
|
||||||
// cover: novelCover,
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// };
|
|
||||||
|
|
||||||
// const novelResults = pageCheerio(".book-ol a.book-layout");
|
|
||||||
// if (novelResults.length === 0) {
|
|
||||||
// } else {
|
|
||||||
// loadSearchResults();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (redirect.length) {
|
|
||||||
// novels.length = 0;
|
|
||||||
// const novelName = pageCheerio(
|
|
||||||
// "#bookDetailWrapper .book-title"
|
|
||||||
// ).text();
|
|
||||||
|
|
||||||
// const novelCover = pageCheerio(
|
|
||||||
// "#bookDetailWrapper div.book-cover > img"
|
|
||||||
// ).attr("src");
|
|
||||||
// const novelUrl =
|
|
||||||
// this.site +
|
|
||||||
// pageCheerio("#btnReadBook").attr("href")?.slice(0, -8) +
|
|
||||||
// ".html";
|
|
||||||
// novels.push({
|
|
||||||
// name: novelName,
|
|
||||||
// url: novelUrl,
|
|
||||||
// cover: novelCover,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
// };
|
|
||||||
|
|
||||||
// NOTE: don't know redirect is for what, comment out for now
|
|
||||||
|
|
||||||
// const redirect = pageCheerio("div.book-layout").text();
|
|
||||||
// await addPage(pageCheerio, redirect);
|
|
||||||
|
|
||||||
pageCheerio('.book-ol .book-layout').each((i, el) => {
|
|
||||||
const nUrl = pageCheerio(el).attr('href');
|
|
||||||
|
|
||||||
const novelName = pageCheerio(el).find('.book-title').text();
|
|
||||||
const novelCover = pageCheerio(el)
|
|
||||||
.find('div.book-cover > img')
|
|
||||||
.attr('data-src');
|
|
||||||
|
|
||||||
if (!nUrl) return;
|
|
||||||
|
|
||||||
novels.push({
|
|
||||||
name: novelName,
|
|
||||||
path: nUrl,
|
|
||||||
cover: novelCover,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
return novels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
filters = {
|
filters = {
|
||||||
|
|||||||
+228
-262
@@ -1,255 +1,238 @@
|
|||||||
import { Plugin } from '@/types/plugin';
|
import { Plugin } from '@/types/plugin';
|
||||||
import p_0 from '@plugins/arabic/ArNovel[madara]';
|
import p_0 from '@plugins/arabic/ArNovel[madara]';
|
||||||
import p_1 from '@plugins/arabic/Azora[madara]';
|
import p_1 from '@plugins/arabic/Azora[madara]';
|
||||||
import p_2 from '@plugins/arabic/FreeKolNovel[lightnovelwp]';
|
import p_2 from '@plugins/arabic/dilartube';
|
||||||
import p_3 from '@plugins/arabic/HizoManga[madara]';
|
import p_3 from '@plugins/arabic/FreeKolNovel[lightnovelwp]';
|
||||||
import p_4 from '@plugins/arabic/KolNovel[lightnovelwp]';
|
import p_4 from '@plugins/arabic/HizoManga[madara]';
|
||||||
import p_5 from '@plugins/arabic/Novel4Up[madara]';
|
import p_5 from '@plugins/arabic/KolNovel[lightnovelwp]';
|
||||||
import p_6 from '@plugins/arabic/NovelsParadise[lightnovelwp]';
|
import p_6 from '@plugins/arabic/Novel4Up[madara]';
|
||||||
import p_7 from '@plugins/arabic/Olaoecyou[madara]';
|
import p_7 from '@plugins/arabic/NovelsParadise[lightnovelwp]';
|
||||||
import p_8 from '@plugins/arabic/Riwyat[madara]';
|
import p_8 from '@plugins/arabic/Olaoecyou[madara]';
|
||||||
import p_9 from '@plugins/arabic/dilartube';
|
import p_9 from '@plugins/arabic/rewayatclub';
|
||||||
import p_10 from '@plugins/arabic/rewayatclub';
|
import p_10 from '@plugins/arabic/Riwyat[madara]';
|
||||||
import p_11 from '@plugins/arabic/sunovels';
|
import p_11 from '@plugins/arabic/sunovels';
|
||||||
import p_12 from '@plugins/chinese/69shu';
|
import p_12 from '@plugins/chinese/69shu';
|
||||||
import p_13 from '@plugins/chinese/Quanben';
|
import p_13 from '@plugins/chinese/ixdzs8';
|
||||||
import p_14 from '@plugins/chinese/ixdzs8';
|
import p_14 from '@plugins/chinese/linovel';
|
||||||
import p_15 from '@plugins/chinese/linovel';
|
import p_15 from '@plugins/chinese/linovelib';
|
||||||
import p_16 from '@plugins/chinese/linovelib';
|
import p_16 from '@plugins/chinese/linovelib_tw';
|
||||||
import p_17 from '@plugins/chinese/linovelib_tw';
|
import p_17 from '@plugins/chinese/novel543';
|
||||||
import p_18 from '@plugins/chinese/novel543';
|
import p_18 from '@plugins/chinese/Quanben';
|
||||||
import p_19 from '@plugins/english/AllNovelFull[readnovelfull]';
|
import p_19 from '@plugins/english/AllNovelFull[readnovelfull]';
|
||||||
import p_20 from '@plugins/english/AllNovel[readnovelfull]';
|
import p_20 from '@plugins/english/AllNovel[readnovelfull]';
|
||||||
import p_21 from '@plugins/english/ArcaneTranslations[lightnovelwp]';
|
import p_21 from '@plugins/english/ao3';
|
||||||
import p_22 from '@plugins/english/BelleReservoir[madara]';
|
import p_22 from '@plugins/english/ArcaneTranslations[lightnovelwp]';
|
||||||
import p_23 from '@plugins/english/BoxNovel[readnovelfull]';
|
import p_23 from '@plugins/english/BelleReservoir[madara]';
|
||||||
import p_24 from '@plugins/english/CPUnovel[lightnovelwp]';
|
import p_24 from '@plugins/english/BoxNovel[readnovelfull]';
|
||||||
import p_25 from '@plugins/english/CitrusAurora[madara]';
|
import p_25 from '@plugins/english/chrysanthemumgarden';
|
||||||
import p_26 from '@plugins/english/CoralBoutique[madara]';
|
import p_26 from '@plugins/english/CitrusAurora[madara]';
|
||||||
import p_27 from '@plugins/english/DaoNovel[madara]';
|
import p_27 from '@plugins/english/CoralBoutique[madara]';
|
||||||
import p_28 from '@plugins/english/DaoTranslate[lightnovelwp]';
|
import p_28 from '@plugins/english/CPUnovel[lightnovelwp]';
|
||||||
import p_29 from '@plugins/english/DaoistQuest[fictioneer]';
|
import p_29 from '@plugins/english/crimsonscrolls';
|
||||||
import p_30 from '@plugins/english/DearestRosalie[fictioneer]';
|
import p_30 from '@plugins/english/DaoistQuest[fictioneer]';
|
||||||
import p_31 from '@plugins/english/DragonTea[madara]';
|
import p_31 from '@plugins/english/DaoNovel[madara]';
|
||||||
import p_32 from '@plugins/english/Dragonholic[madara]';
|
import p_32 from '@plugins/english/DaoTranslate[lightnovelwp]';
|
||||||
import p_33 from '@plugins/english/DuskBlossoms[madara]';
|
import p_33 from '@plugins/english/DearestRosalie[fictioneer]';
|
||||||
import p_34 from '@plugins/english/ElloTL[lightnovelwp]';
|
import p_34 from '@plugins/english/divinedaolibrary';
|
||||||
import p_35 from '@plugins/english/Eternalune[madara]';
|
import p_35 from '@plugins/english/Dragonholic[madara]';
|
||||||
import p_36 from '@plugins/english/EtudeTranslations[madara]';
|
import p_36 from '@plugins/english/DragonTea[madara]';
|
||||||
import p_37 from '@plugins/english/FanNovel[readwn]';
|
import p_37 from '@plugins/english/dreambigtl';
|
||||||
import p_38 from '@plugins/english/FansMTL[readwn]';
|
import p_38 from '@plugins/english/DuskBlossoms[madara]';
|
||||||
import p_39 from '@plugins/english/FansTranslations[madara]';
|
import p_39 from '@plugins/english/ElloTL[lightnovelwp]';
|
||||||
import p_40 from '@plugins/english/FirstKissNovel[madara]';
|
import p_40 from '@plugins/english/Eternalune[madara]';
|
||||||
import p_41 from '@plugins/english/Foxaholic[madara]';
|
import p_41 from '@plugins/english/EtudeTranslations[madara]';
|
||||||
import p_42 from '@plugins/english/FreeWebNovel[readnovelfull]';
|
import p_42 from '@plugins/english/FanNovel[readwn]';
|
||||||
import p_43 from '@plugins/english/GalaxyTranslations[madara]';
|
import p_43 from '@plugins/english/FansMTL[readwn]';
|
||||||
import p_44 from '@plugins/english/Guavaread[madara]';
|
import p_44 from '@plugins/english/FansTranslations[madara]';
|
||||||
import p_45 from '@plugins/english/HiraethTranslation[madara]';
|
import p_45 from '@plugins/english/faqwikius';
|
||||||
import p_46 from '@plugins/english/HotNovelPub[hotnovelpub]';
|
import p_46 from '@plugins/english/fenrirrealm';
|
||||||
import p_47 from '@plugins/english/Ippotranslations[lightnovelwp]';
|
import p_47 from '@plugins/english/fictionzone';
|
||||||
import p_48 from '@plugins/english/KeopiTranslations[lightnovelwp]';
|
import p_48 from '@plugins/english/FirstKissNovel[madara]';
|
||||||
import p_49 from '@plugins/english/KnoxT[lightnovelwp]';
|
import p_49 from '@plugins/english/Foxaholic[madara]';
|
||||||
import p_50 from '@plugins/english/LazyGirlTranslations[lightnovelwp]';
|
import p_50 from '@plugins/english/foxteller';
|
||||||
import p_51 from '@plugins/english/LibRead[readnovelfull]';
|
import p_51 from '@plugins/english/FreeWebNovel[readnovelfull]';
|
||||||
import p_52 from '@plugins/english/LightNovelCave[lightnovelworld]';
|
import p_52 from '@plugins/english/GalaxyTranslations[madara]';
|
||||||
import p_53 from '@plugins/english/LightNovelHeaven[madara]';
|
import p_53 from '@plugins/english/genesis';
|
||||||
import p_54 from '@plugins/english/LightNovelPlus[readnovelfull]';
|
import p_54 from '@plugins/english/Guavaread[madara]';
|
||||||
import p_55 from '@plugins/english/LightNovelPubVip[lightnovelworld]';
|
import p_55 from '@plugins/english/HiraethTranslation[madara]';
|
||||||
import p_56 from '@plugins/english/LightNovelUpdates[madara]';
|
import p_56 from '@plugins/english/HotNovelPub[hotnovelpub]';
|
||||||
import p_57 from '@plugins/english/LightNovelWord[lightnovelworld]';
|
import p_57 from '@plugins/english/inkitt';
|
||||||
import p_58 from '@plugins/english/LilyontheValley[fictioneer]';
|
import p_58 from '@plugins/english/Ippotranslations[lightnovelwp]';
|
||||||
import p_59 from '@plugins/english/Ltnovel[readwn]';
|
import p_59 from '@plugins/english/KDTNovels[lightnovelwp]';
|
||||||
import p_60 from '@plugins/english/LunarLetters[madara]';
|
import p_60 from '@plugins/english/KeopiTranslations[lightnovelwp]';
|
||||||
import p_61 from '@plugins/english/MTLNovel[madara]';
|
import p_61 from '@plugins/english/KnoxT[lightnovelwp]';
|
||||||
import p_62 from '@plugins/english/MTLNovel[mtlnovel]';
|
import p_62 from '@plugins/english/LazyGirlTranslations[lightnovelwp]';
|
||||||
import p_63 from '@plugins/english/Meownovel[madara]';
|
import p_63 from '@plugins/english/leafstudio';
|
||||||
import p_64 from '@plugins/english/MoonlightNovels[lightnovelwp]';
|
import p_64 from '@plugins/english/LibRead[readnovelfull]';
|
||||||
import p_65 from '@plugins/english/MostNovel[madara]';
|
import p_65 from '@plugins/english/LightNovelCave[lightnovelworld]';
|
||||||
import p_66 from '@plugins/english/MysticalSeries[madara]';
|
import p_66 from '@plugins/english/LightNovelHeaven[madara]';
|
||||||
import p_67 from '@plugins/english/NeoSekaiTranslations[madara]';
|
import p_67 from '@plugins/english/LightNovelPlus[readnovelfull]';
|
||||||
import p_68 from '@plugins/english/NitroManga[madara]';
|
import p_68 from '@plugins/english/LightNovelPubVip[lightnovelworld]';
|
||||||
import p_69 from '@plugins/english/NobleMTL[lightnovelwp]';
|
import p_69 from '@plugins/english/lightnoveltranslation';
|
||||||
import p_70 from '@plugins/english/NoiceTranslations[madara]';
|
import p_70 from '@plugins/english/LightNovelUpdates[madara]';
|
||||||
import p_71 from '@plugins/english/NovelBin[readnovelfull]';
|
import p_71 from '@plugins/english/LilyontheValley[fictioneer]';
|
||||||
import p_72 from '@plugins/english/NovelCool[novelcool]';
|
import p_72 from '@plugins/english/lnmtl';
|
||||||
import p_73 from '@plugins/english/NovelFull[readnovelfull]';
|
import p_73 from '@plugins/english/Ltnovel[readwn]';
|
||||||
import p_74 from '@plugins/english/NovelLib[fictioneer]';
|
import p_74 from '@plugins/english/LunarLetters[madara]';
|
||||||
import p_75 from '@plugins/english/NovelMultiverse[madara]';
|
import p_75 from '@plugins/english/Meownovel[madara]';
|
||||||
import p_76 from '@plugins/english/NovelOnline';
|
import p_76 from '@plugins/english/MoonlightNovels[lightnovelwp]';
|
||||||
import p_77 from '@plugins/english/NovelTranslate[madara]';
|
import p_77 from '@plugins/english/MostNovel[madara]';
|
||||||
import p_78 from '@plugins/english/NovelsKnight[lightnovelwp]';
|
import p_78 from '@plugins/english/MTLNovel[madara]';
|
||||||
import p_79 from '@plugins/english/PandaMachineTranslations[lightnovelwp]';
|
import p_79 from '@plugins/english/MTLNovel[mtlnovel]';
|
||||||
import p_80 from '@plugins/english/PastelTales[madara]';
|
import p_80 from '@plugins/english/mtlreader';
|
||||||
import p_81 from '@plugins/english/PenguinSquad[fictioneer]';
|
import p_81 from '@plugins/english/mvlempyr';
|
||||||
import p_82 from '@plugins/english/Prizma[fictioneer]';
|
import p_82 from '@plugins/english/MysticalSeries[madara]';
|
||||||
import p_83 from '@plugins/english/Ranobes[ranobes]';
|
import p_83 from '@plugins/english/NeoSekaiTranslations[madara]';
|
||||||
import p_84 from '@plugins/english/Ranovel[madara]';
|
import p_84 from '@plugins/english/NitroManga[madara]';
|
||||||
import p_85 from '@plugins/english/ReadFanfic[madara]';
|
import p_85 from '@plugins/english/NobleMTL[lightnovelwp]';
|
||||||
import p_86 from '@plugins/english/ReadNovelFull[readnovelfull]';
|
import p_86 from '@plugins/english/NoiceTranslations[madara]';
|
||||||
import p_87 from '@plugins/english/RequiemTranslations[lightnovelwp]';
|
import p_87 from '@plugins/english/NovelBin[readnovelfull]';
|
||||||
import p_88 from '@plugins/english/SalmonLatte[madara]';
|
import p_88 from '@plugins/english/novelbuddy';
|
||||||
import p_89 from '@plugins/english/SleepyTranslations[madara]';
|
import p_89 from '@plugins/english/NovelCool[novelcool]';
|
||||||
import p_90 from '@plugins/english/SonicMTL[madara]';
|
import p_90 from '@plugins/english/novelfire';
|
||||||
import p_91 from '@plugins/english/SrankManga[madara]';
|
import p_91 from '@plugins/english/NovelFull[readnovelfull]';
|
||||||
import p_92 from '@plugins/english/StorySeedling';
|
import p_92 from '@plugins/english/novelhall';
|
||||||
import p_93 from '@plugins/english/SweetEscape[madara]';
|
import p_93 from '@plugins/english/novelight';
|
||||||
import p_94 from '@plugins/english/SystemTranslation[lightnovelwp]';
|
import p_94 from '@plugins/english/NovelLib[fictioneer]';
|
||||||
import p_95 from '@plugins/english/TranslatinOtaku[madara]';
|
import p_95 from '@plugins/english/NovelMultiverse[madara]';
|
||||||
import p_96 from '@plugins/english/TranslationWeaver[lightnovelwp]';
|
import p_96 from '@plugins/english/NovelOnline';
|
||||||
import p_97 from '@plugins/english/UniversalNovel[lightnovelwp]';
|
import p_97 from '@plugins/english/NovelsKnight[lightnovelwp]';
|
||||||
import p_98 from '@plugins/english/VandyTranslate[lightnovelwp]';
|
import p_98 from '@plugins/english/NovelTranslate[madara]';
|
||||||
import p_99 from '@plugins/english/VioletLily[madara]';
|
import p_99 from '@plugins/english/novelupdates';
|
||||||
import p_100 from '@plugins/english/WebNovelLover[madara]';
|
import p_100 from '@plugins/english/PandaMachineTranslations[lightnovelwp]';
|
||||||
import p_101 from '@plugins/english/WebNovelPub[lightnovelworld]';
|
import p_101 from '@plugins/english/PastelTales[madara]';
|
||||||
import p_102 from '@plugins/english/WebNovelTranslation[madara]';
|
import p_102 from '@plugins/english/pawread';
|
||||||
import p_103 from '@plugins/english/WhiteMoonlightNovels[lightnovelwp]';
|
import p_103 from '@plugins/english/PenguinSquad[fictioneer]';
|
||||||
import p_104 from '@plugins/english/WooksTeahouse[madara]';
|
import p_104 from '@plugins/english/Prizma[fictioneer]';
|
||||||
import p_105 from '@plugins/english/WordExcerpt[madara]';
|
import p_105 from '@plugins/english/rainofsnow';
|
||||||
import p_106 from '@plugins/english/WuxiaSpace[readwn]';
|
import p_106 from '@plugins/english/Ranobes[ranobes]';
|
||||||
import p_107 from '@plugins/english/WuxiaV[readwn]';
|
import p_107 from '@plugins/english/Ranovel[madara]';
|
||||||
import p_108 from '@plugins/english/WuxiaWorldSite[madara]';
|
import p_108 from '@plugins/english/ReadFanfic[madara]';
|
||||||
import p_109 from '@plugins/english/Wuxiabox[readwn]';
|
import p_109 from '@plugins/english/readfrom';
|
||||||
import p_110 from '@plugins/english/Wuxiafox[readwn]';
|
import p_110 from '@plugins/english/ReadNovelFull[readnovelfull]';
|
||||||
import p_111 from '@plugins/english/ZetroTranslation[madara]';
|
import p_111 from '@plugins/english/relibrary';
|
||||||
import p_112 from '@plugins/english/ao3';
|
import p_112 from '@plugins/english/RequiemTranslations[lightnovelwp]';
|
||||||
import p_113 from '@plugins/english/bestlightnovel';
|
import p_113 from '@plugins/english/royalroad';
|
||||||
import p_114 from '@plugins/english/chrysanthemumgarden';
|
import p_114 from '@plugins/english/SalmonLatte[madara]';
|
||||||
import p_115 from '@plugins/english/crimsonscrolls';
|
import p_115 from '@plugins/english/scribblehub';
|
||||||
import p_116 from '@plugins/english/divinedaolibrary';
|
import p_116 from '@plugins/english/SleepyTranslations[madara]';
|
||||||
import p_117 from '@plugins/english/dreambigtl';
|
import p_117 from '@plugins/english/SonicMTL[madara]';
|
||||||
import p_118 from '@plugins/english/earlynovel';
|
import p_118 from '@plugins/english/SrankManga[madara]';
|
||||||
import p_119 from '@plugins/english/faqwikius';
|
import p_119 from '@plugins/english/StorySeedling';
|
||||||
import p_120 from '@plugins/english/fenrirrealm';
|
import p_120 from '@plugins/english/SweetEscape[madara]';
|
||||||
import p_121 from '@plugins/english/fictionzone';
|
import p_121 from '@plugins/english/SystemTranslation[lightnovelwp]';
|
||||||
import p_122 from '@plugins/english/foxteller';
|
import p_122 from '@plugins/english/TranslatinOtaku[madara]';
|
||||||
import p_123 from '@plugins/english/genesis';
|
import p_123 from '@plugins/english/TranslationWeaver[lightnovelwp]';
|
||||||
import p_124 from '@plugins/english/inkitt';
|
import p_124 from '@plugins/english/UniversalNovel[lightnovelwp]';
|
||||||
import p_125 from '@plugins/english/kdtnovels';
|
import p_125 from '@plugins/english/VandyTranslate[lightnovelwp]';
|
||||||
import p_126 from '@plugins/english/leafstudio';
|
import p_126 from '@plugins/english/VioletLily[madara]';
|
||||||
import p_127 from '@plugins/english/lightnovelpub';
|
import p_127 from '@plugins/english/vynovel';
|
||||||
import p_128 from '@plugins/english/lightnoveltranslation';
|
import p_128 from '@plugins/english/webnovel';
|
||||||
import p_129 from '@plugins/english/lnmtl';
|
import p_129 from '@plugins/english/WebNovelLover[madara]';
|
||||||
import p_130 from '@plugins/english/mtlreader';
|
import p_130 from '@plugins/english/WebNovelPub[lightnovelworld]';
|
||||||
import p_131 from '@plugins/english/mvlempyr';
|
import p_131 from '@plugins/english/WebNovelTranslation[madara]';
|
||||||
import p_132 from '@plugins/english/novelbuddy';
|
import p_132 from '@plugins/english/WhiteMoonlightNovels[lightnovelwp]';
|
||||||
import p_133 from '@plugins/english/novelfire.paged';
|
import p_133 from '@plugins/english/WooksTeahouse[madara]';
|
||||||
import p_134 from '@plugins/english/novelfire';
|
import p_134 from '@plugins/english/WordExcerpt[madara]';
|
||||||
import p_135 from '@plugins/english/novelhall';
|
import p_135 from '@plugins/english/wtrlab';
|
||||||
import p_136 from '@plugins/english/novelight';
|
import p_136 from '@plugins/english/Wuxiabox[readwn]';
|
||||||
import p_137 from '@plugins/english/novelupdates';
|
import p_137 from '@plugins/english/Wuxiafox[readwn]';
|
||||||
import p_138 from '@plugins/english/pawread';
|
import p_138 from '@plugins/english/WuxiaSpace[readwn]';
|
||||||
import p_139 from '@plugins/english/rainofsnow';
|
import p_139 from '@plugins/english/WuxiaV[readwn]';
|
||||||
import p_140 from '@plugins/english/readfrom';
|
import p_140 from '@plugins/english/wuxiaworld';
|
||||||
import p_141 from '@plugins/english/readlitenovel';
|
import p_141 from '@plugins/english/WuxiaWorldSite[madara]';
|
||||||
import p_142 from '@plugins/english/reaperscans';
|
import p_142 from '@plugins/english/ZetroTranslation[madara]';
|
||||||
import p_143 from '@plugins/english/relibrary';
|
import p_143 from '@plugins/french/chireads';
|
||||||
import p_144 from '@plugins/english/royalroad';
|
import p_144 from '@plugins/french/harkeneliwood';
|
||||||
import p_145 from '@plugins/english/scribblehub';
|
import p_145 from '@plugins/french/kisswood';
|
||||||
import p_146 from '@plugins/english/vynovel';
|
import p_146 from '@plugins/french/LighNovelFR[lightnovelwp]';
|
||||||
import p_147 from '@plugins/english/webnovel';
|
import p_147 from '@plugins/french/MassNovel[madara]';
|
||||||
import p_148 from '@plugins/english/wtrlab';
|
import p_148 from '@plugins/french/MTLNovel(FR)[mtlnovel]';
|
||||||
import p_149 from '@plugins/english/wuxiaworld';
|
import p_149 from '@plugins/french/noveldeglace';
|
||||||
import p_150 from '@plugins/french/LighNovelFR[lightnovelwp]';
|
import p_150 from '@plugins/french/novhell';
|
||||||
import p_151 from '@plugins/french/MTLNovel(FR)[mtlnovel]';
|
import p_151 from '@plugins/french/warriorlegendtrad';
|
||||||
import p_152 from '@plugins/french/MassNovel[madara]';
|
import p_152 from '@plugins/french/WorldNovel[madara]';
|
||||||
import p_153 from '@plugins/french/WorldNovel[madara]';
|
import p_153 from '@plugins/french/wuxialnscantrad';
|
||||||
import p_154 from '@plugins/french/chireads';
|
import p_154 from '@plugins/french/xiaowaz';
|
||||||
import p_155 from '@plugins/french/harkeneliwood';
|
import p_155 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]';
|
||||||
import p_156 from '@plugins/french/kisswood';
|
import p_156 from '@plugins/indonesian/indowebnovel';
|
||||||
import p_157 from '@plugins/french/noveldeglace';
|
import p_157 from '@plugins/indonesian/MeioNovel[madara]';
|
||||||
import p_158 from '@plugins/french/novhell';
|
import p_158 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]';
|
||||||
import p_159 from '@plugins/french/phenixscans';
|
import p_159 from '@plugins/indonesian/NovelBookID[madara]';
|
||||||
import p_160 from '@plugins/french/warriorlegendtrad';
|
import p_160 from '@plugins/indonesian/sakuranovel';
|
||||||
import p_161 from '@plugins/french/wuxialnscantrad';
|
import p_161 from '@plugins/indonesian/SekteNovel[lightnovelwp]';
|
||||||
import p_162 from '@plugins/french/xiaowaz';
|
import p_162 from '@plugins/indonesian/Vanovel[madara]';
|
||||||
import p_163 from '@plugins/indonesian/BacaLightNovel[lightnovelwp]';
|
import p_163 from '@plugins/indonesian/WBNovel[madara]';
|
||||||
import p_164 from '@plugins/indonesian/MTLNovel(ID)[mtlnovel]';
|
import p_164 from '@plugins/japanese/kakuyomu';
|
||||||
import p_165 from '@plugins/indonesian/MeioNovel[madara]';
|
import p_165 from '@plugins/japanese/Syosetu';
|
||||||
import p_166 from '@plugins/indonesian/NovelBookID[madara]';
|
import p_166 from '@plugins/korean/Agitoon';
|
||||||
import p_167 from '@plugins/indonesian/Risenovel[madara]';
|
import p_167 from '@plugins/korean/FortuneEternal[madara]';
|
||||||
import p_168 from '@plugins/indonesian/SekteNovel[lightnovelwp]';
|
import p_168 from '@plugins/multi/komga';
|
||||||
import p_169 from '@plugins/indonesian/Vanovel[madara]';
|
import p_169 from '@plugins/polish/novelki';
|
||||||
import p_170 from '@plugins/indonesian/WBNovel[madara]';
|
import p_170 from '@plugins/portuguese/BetterNovels[lightnovelwp]';
|
||||||
import p_171 from '@plugins/indonesian/indowebnovel';
|
import p_171 from '@plugins/portuguese/blogdoamonnovels';
|
||||||
import p_172 from '@plugins/indonesian/novelringan';
|
import p_172 from '@plugins/portuguese/CentralNovel[lightnovelwp]';
|
||||||
import p_173 from '@plugins/indonesian/sakuranovel';
|
import p_173 from '@plugins/portuguese/Kiniga[madara]';
|
||||||
import p_174 from '@plugins/japanese/Syosetu';
|
import p_174 from '@plugins/portuguese/LaNovels[hotnovelpub]';
|
||||||
import p_175 from '@plugins/japanese/kakuyomu';
|
import p_175 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]';
|
||||||
import p_176 from '@plugins/korean/Agitoon';
|
import p_176 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]';
|
||||||
import p_177 from '@plugins/korean/FortuneEternal[madara]';
|
import p_177 from '@plugins/portuguese/novelmania';
|
||||||
import p_178 from '@plugins/multi/komga';
|
import p_178 from '@plugins/portuguese/tsundoku';
|
||||||
import p_179 from '@plugins/polish/novelki';
|
import p_179 from '@plugins/russian/authortoday';
|
||||||
import p_180 from '@plugins/portuguese/BetterNovels[lightnovelwp]';
|
import p_180 from '@plugins/russian/Bookhamster[ifreedom]';
|
||||||
import p_181 from '@plugins/portuguese/CentralNovel[lightnovelwp]';
|
import p_181 from '@plugins/russian/bookriver';
|
||||||
import p_182 from '@plugins/portuguese/Kiniga[madara]';
|
import p_182 from '@plugins/russian/Erolate[rulate]';
|
||||||
import p_183 from '@plugins/portuguese/LaNovels[hotnovelpub]';
|
import p_183 from '@plugins/russian/EzNovels[hotnovelpub]';
|
||||||
import p_184 from '@plugins/portuguese/LightNovelBrasil[lightnovelwp]';
|
import p_184 from '@plugins/russian/ficbook';
|
||||||
import p_185 from '@plugins/portuguese/MTLNovel(PT)[mtlnovel]';
|
import p_185 from '@plugins/russian/jaomix';
|
||||||
import p_186 from '@plugins/portuguese/blogdoamonnovels';
|
import p_186 from '@plugins/russian/MTLNovel(RU)[mtlnovel]';
|
||||||
import p_187 from '@plugins/portuguese/novelmania';
|
import p_187 from '@plugins/russian/neobook';
|
||||||
import p_188 from '@plugins/portuguese/tsundoku';
|
import p_188 from '@plugins/russian/NovelCool(RU)[novelcool]';
|
||||||
import p_189 from '@plugins/russian/Bookhamster[ifreedom]';
|
import p_189 from '@plugins/russian/novelTL';
|
||||||
import p_190 from '@plugins/russian/Erolate[rulate]';
|
import p_190 from '@plugins/russian/ranobehub';
|
||||||
import p_191 from '@plugins/russian/EzNovels[hotnovelpub]';
|
import p_191 from '@plugins/russian/ranobelib';
|
||||||
import p_192 from '@plugins/russian/LitSpace';
|
import p_192 from '@plugins/russian/ranoberf';
|
||||||
import p_193 from '@plugins/russian/MTLNovel(RU)[mtlnovel]';
|
import p_193 from '@plugins/russian/Ranobes(RU)[ranobes]';
|
||||||
import p_194 from '@plugins/russian/NovelCool(RU)[novelcool]';
|
import p_194 from '@plugins/russian/renovels';
|
||||||
import p_195 from '@plugins/russian/Ranobes(RU)[ranobes]';
|
import p_195 from '@plugins/russian/Rulate[rulate]';
|
||||||
import p_196 from '@plugins/russian/Rulate[rulate]';
|
import p_196 from '@plugins/russian/topliba';
|
||||||
import p_197 from '@plugins/russian/authortoday';
|
import p_197 from '@plugins/russian/zelluloza';
|
||||||
import p_198 from '@plugins/russian/bookriver';
|
import p_198 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]';
|
||||||
import p_199 from '@plugins/russian/ficbook';
|
import p_199 from '@plugins/spanish/AllNovelRead[lightnovelwp]';
|
||||||
import p_200 from '@plugins/russian/jaomix';
|
import p_200 from '@plugins/spanish/AnimesHoy12[madara]';
|
||||||
import p_201 from '@plugins/russian/neobook';
|
import p_201 from '@plugins/spanish/hasutl';
|
||||||
import p_202 from '@plugins/russian/novelOvh';
|
import p_202 from '@plugins/spanish/LightNovelDaily[hotnovelpub]';
|
||||||
import p_203 from '@plugins/russian/novelTL';
|
import p_203 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]';
|
||||||
import p_204 from '@plugins/russian/ranobehub';
|
import p_204 from '@plugins/spanish/novelasligera';
|
||||||
import p_205 from '@plugins/russian/ranobelib';
|
import p_205 from '@plugins/spanish/novelawuxia';
|
||||||
import p_206 from '@plugins/russian/ranoberf';
|
import p_206 from '@plugins/spanish/oasistranslations';
|
||||||
import p_207 from '@plugins/russian/renovels';
|
import p_207 from '@plugins/spanish/PanchoTranslations[madara]';
|
||||||
import p_208 from '@plugins/russian/ruvers';
|
import p_208 from '@plugins/spanish/skynovels';
|
||||||
import p_209 from '@plugins/russian/topliba';
|
import p_209 from '@plugins/spanish/TC&Sega[lightnovelwp]';
|
||||||
import p_210 from '@plugins/russian/zelluloza';
|
import p_210 from '@plugins/spanish/TraduccionesAmistosas[madara]';
|
||||||
import p_211 from '@plugins/russian/СвободныйМирРанобэ[ifreedom]';
|
import p_211 from '@plugins/spanish/tunovelaligera';
|
||||||
import p_212 from '@plugins/spanish/AllNovelRead[lightnovelwp]';
|
import p_212 from '@plugins/spanish/yukitls';
|
||||||
import p_213 from '@plugins/spanish/AnimesHoy12[madara]';
|
import p_213 from '@plugins/thai/NovelLucky[madara]';
|
||||||
import p_214 from '@plugins/spanish/LightNovelDaily[hotnovelpub]';
|
import p_214 from '@plugins/thai/NovelPDF[madara]';
|
||||||
import p_215 from '@plugins/spanish/MTLNovel(ES)[mtlnovel]';
|
import p_215 from '@plugins/turkish/ArazNovel[madara]';
|
||||||
import p_216 from '@plugins/spanish/PanchoTranslations[madara]';
|
import p_216 from '@plugins/turkish/EKTAPLAR[madara]';
|
||||||
import p_217 from '@plugins/spanish/TC&Sega[lightnovelwp]';
|
import p_217 from '@plugins/turkish/epiknovel';
|
||||||
import p_218 from '@plugins/spanish/TraduccionesAmistosas[madara]';
|
import p_218 from '@plugins/turkish/kakikata[madara]';
|
||||||
import p_219 from '@plugins/spanish/hasutl';
|
import p_219 from '@plugins/turkish/KodeksLibrary[lightnovelwp]';
|
||||||
import p_220 from '@plugins/spanish/novelasligera';
|
import p_220 from '@plugins/turkish/MangaTR';
|
||||||
import p_221 from '@plugins/spanish/novelawuxia';
|
import p_221 from '@plugins/turkish/NABSCANS[madara]';
|
||||||
import p_222 from '@plugins/spanish/oasistranslations';
|
import p_222 from '@plugins/turkish/Namevt[lightnovelwp]';
|
||||||
import p_223 from '@plugins/spanish/skynovels';
|
import p_223 from '@plugins/turkish/Noveloku[madara]';
|
||||||
import p_224 from '@plugins/spanish/tunovelaligera';
|
import p_224 from '@plugins/turkish/NovelTR[lightnovelwp]';
|
||||||
import p_225 from '@plugins/spanish/yukitls';
|
import p_225 from '@plugins/turkish/RagnarScans[madara]';
|
||||||
import p_226 from '@plugins/thai/NovelLucky[madara]';
|
import p_226 from '@plugins/turkish/ThNovels[hotnovelpub]';
|
||||||
import p_227 from '@plugins/thai/NovelPDF[madara]';
|
import p_227 from '@plugins/turkish/TurkceLightNovels[madara]';
|
||||||
import p_228 from '@plugins/turkish/ArazNovel[madara]';
|
import p_228 from '@plugins/turkish/WebNovelOku[madara]';
|
||||||
import p_229 from '@plugins/turkish/EKTAPLAR[madara]';
|
import p_229 from '@plugins/ukrainian/bakainua';
|
||||||
import p_230 from '@plugins/turkish/KodeksLibrary[lightnovelwp]';
|
import p_230 from '@plugins/ukrainian/smakolykytl';
|
||||||
import p_231 from '@plugins/turkish/MangaTR';
|
import p_231 from '@plugins/vietnamese/lightnovelvn';
|
||||||
import p_232 from '@plugins/turkish/NABSCANS[madara]';
|
import p_232 from '@plugins/vietnamese/LNHako';
|
||||||
import p_233 from '@plugins/turkish/Namevt[lightnovelwp]';
|
import p_233 from '@plugins/vietnamese/nettruyen';
|
||||||
import p_234 from '@plugins/turkish/NovelTR[lightnovelwp]';
|
|
||||||
import p_235 from '@plugins/turkish/Noveloku[madara]';
|
|
||||||
import p_236 from '@plugins/turkish/RagnarScans[madara]';
|
|
||||||
import p_237 from '@plugins/turkish/ThNovels[hotnovelpub]';
|
|
||||||
import p_238 from '@plugins/turkish/TurkceLightNovels[madara]';
|
|
||||||
import p_239 from '@plugins/turkish/WebNovelOku[madara]';
|
|
||||||
import p_240 from '@plugins/turkish/epiknovel';
|
|
||||||
import p_241 from '@plugins/turkish/kakikata[madara]';
|
|
||||||
import p_242 from '@plugins/ukrainian/bakainua';
|
|
||||||
import p_243 from '@plugins/ukrainian/smakolykytl';
|
|
||||||
import p_244 from '@plugins/ukrainian/uaranobeclub';
|
|
||||||
import p_245 from '@plugins/vietnamese/LNHako';
|
|
||||||
import p_246 from '@plugins/vietnamese/Truyenconect';
|
|
||||||
import p_247 from '@plugins/vietnamese/lightnovelvn';
|
|
||||||
import p_248 from '@plugins/vietnamese/nettruyen';
|
|
||||||
import p_249 from '@plugins/vietnamese/truyenchu';
|
|
||||||
import p_250 from '@plugins/vietnamese/truyenfull';
|
|
||||||
|
|
||||||
const PLUGINS: Plugin.PluginBase[] = [
|
const PLUGINS: Plugin.PluginBase[] = [
|
||||||
p_0,
|
p_0,
|
||||||
@@ -486,22 +469,5 @@ const PLUGINS: Plugin.PluginBase[] = [
|
|||||||
p_231,
|
p_231,
|
||||||
p_232,
|
p_232,
|
||||||
p_233,
|
p_233,
|
||||||
p_234,
|
|
||||||
p_235,
|
|
||||||
p_236,
|
|
||||||
p_237,
|
|
||||||
p_238,
|
|
||||||
p_239,
|
|
||||||
p_240,
|
|
||||||
p_241,
|
|
||||||
p_242,
|
|
||||||
p_243,
|
|
||||||
p_244,
|
|
||||||
p_245,
|
|
||||||
p_246,
|
|
||||||
p_247,
|
|
||||||
p_248,
|
|
||||||
p_249,
|
|
||||||
p_250,
|
|
||||||
];
|
];
|
||||||
export default PLUGINS;
|
export default PLUGINS;
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ const proxyHandlerMiddle: Connect.NextHandleFunction = (req, res) => {
|
|||||||
}
|
}
|
||||||
res.setHeader('Access-Control-Allow-Origin', settings.CLIENT_HOST);
|
res.setHeader('Access-Control-Allow-Origin', settings.CLIENT_HOST);
|
||||||
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
res.setHeader('Access-Control-Allow-Credentials', 'true');
|
||||||
|
req.headers.referer = rawUrl;
|
||||||
if (req.method === 'OPTIONS') {
|
if (req.method === 'OPTIONS') {
|
||||||
res.statusCode = 200;
|
res.statusCode = 200;
|
||||||
res.end();
|
res.end();
|
||||||
|
|||||||
@@ -10,13 +10,14 @@ const REMOTE = execSync('git remote get-url origin')
|
|||||||
const CURRENT_BRANCH = execSync('git branch --show-current')
|
const CURRENT_BRANCH = execSync('git branch --show-current')
|
||||||
.toString()
|
.toString()
|
||||||
.replace(/[\s\n]/g, '');
|
.replace(/[\s\n]/g, '');
|
||||||
|
const BRANCH = process.env.BRANCH ? process.env.BRANCH : CURRENT_BRANCH;
|
||||||
const matched = REMOTE.match(/([^:/]+?)\/([^/.]+)(\.git)?$/);
|
const matched = REMOTE.match(/([^:/]+?)\/([^/.]+)(\.git)?$/);
|
||||||
if (!matched) throw Error('Cant parse git url');
|
if (!matched) throw Error('Cant parse git url');
|
||||||
const USERNAME = matched[1];
|
const USERNAME = matched[1];
|
||||||
const REPO = matched[2];
|
const REPO = matched[2];
|
||||||
const USER_CONTENT_LINK = process.env.USER_CONTENT_BASE
|
const USER_CONTENT_LINK = process.env.USER_CONTENT_BASE
|
||||||
? process.env.USER_CONTENT_BASE
|
? process.env.USER_CONTENT_BASE
|
||||||
: `https://raw.githubusercontent.com/${USERNAME}/${REPO}/${CURRENT_BRANCH}`;
|
: `https://raw.githubusercontent.com/${USERNAME}/${REPO}/${BRANCH}`;
|
||||||
|
|
||||||
const STATIC_LINK = `${USER_CONTENT_LINK}/public/static`;
|
const STATIC_LINK = `${USER_CONTENT_LINK}/public/static`;
|
||||||
// Use legacy .js/src/plugins path for backward compatibility
|
// Use legacy .js/src/plugins path for backward compatibility
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ if [[ "$1" == "--all-branches" ]]; then
|
|||||||
echo "Compiling TypeScript..."
|
echo "Compiling TypeScript..."
|
||||||
npx tsc --project tsconfig.production.json
|
npx tsc --project tsconfig.production.json
|
||||||
echo "# $branch" >> $GITHUB_STEP_SUMMARY
|
echo "# $branch" >> $GITHUB_STEP_SUMMARY
|
||||||
npm run build:manifest -- --only-new 2>> $GITHUB_STEP_SUMMARY
|
BRANCH=$dist npm run build:manifest -- --only-new 2>> $GITHUB_STEP_SUMMARY
|
||||||
if [ ! -d ".dist" ] || [ -z "$(ls -A .dist)" ]; then
|
if [ ! -d ".dist" ] || [ -z "$(ls -A .dist)" ]; then
|
||||||
echo "❌ ERROR: Manifest generation failed - .dist is missing or empty"
|
echo "❌ ERROR: Manifest generation failed - .dist is missing or empty"
|
||||||
exit 1
|
exit 1
|
||||||
|
|||||||
@@ -25,10 +25,7 @@ export function NovelCard({ novel, onParse }: NovelCardProps) {
|
|||||||
<div className="group cursor-pointer flex flex-col h-full">
|
<div className="group cursor-pointer flex flex-col h-full">
|
||||||
<div className="relative mb-2 overflow-hidden rounded-lg bg-muted aspect-[3/4]">
|
<div className="relative mb-2 overflow-hidden rounded-lg bg-muted aspect-[3/4]">
|
||||||
<img
|
<img
|
||||||
src={
|
src={novel.cover || '/static/coverNotAvailable.webp'}
|
||||||
(novel.cover ? '/' : '') + novel.cover ||
|
|
||||||
'/static/coverNotAvailable.webp'
|
|
||||||
}
|
|
||||||
alt={novel.name}
|
alt={novel.name}
|
||||||
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-300"
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user