Feat: ImageRequestInit (#979)
* add ImageRequestInit & fix Hako * remove multisrc fetchFile * remove plugins fetchFile * update docs and template file
This commit is contained in:
+21
-38
@@ -29,12 +29,12 @@ class ExamplePlugin implements Plugin.PluginBase {}
|
||||
| [icon](#pluginbasename) | yes | Plugin Icon |
|
||||
| [site](#pluginbasesite) | yes | Plugin site link |
|
||||
| [version](#pluginbaseversion) | yes | Plugin version |
|
||||
| [imageRequestInit](#pluginbaseimagerequestinit) | no | Plugin Image Request Init |
|
||||
| [filters](#pluginbasefilters) | no | [Filter definition](#filter-definition-object) object |
|
||||
| [popularNovels(page, options)](#pluginbasepopularnovels) | yes | Novel list getter |
|
||||
| [parseNovelAndChapters(url)](#pluginbaseparsenovelandchapters) | yes | Novel info and chapter list getter |
|
||||
| [parseChapter(url)](#pluginbaseparsechapter) | yes | Chapter text getter |
|
||||
| [searchNovels(searchTerm, page)](#pluginbasesearchnovels) | yes | Novel searching getter |
|
||||
| [fetchImage(url)](#pluginbasefetchimage) | yes | Customizable function for fetching images |
|
||||
|
||||
#### PluginBase::id
|
||||
|
||||
@@ -109,6 +109,26 @@ class ExamplePlugin implements Plugin.PluginBase {
|
||||
}
|
||||
```
|
||||
|
||||
#### PluginBase::imageRequestInit
|
||||
|
||||
The init for request to obtain images
|
||||
|
||||
Used if images failed to load due to site's protection
|
||||
|
||||
###### Example
|
||||
|
||||
```ts
|
||||
class ExamplePlugin implements Plugin.PluginBase {
|
||||
...
|
||||
imageRequestInit: Plugin.ImageRequestInit = {
|
||||
headers: {
|
||||
Referer: 'https://example.com',
|
||||
},
|
||||
};
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
#### PluginBase::filters
|
||||
|
||||
A [Filter definition]() object that holds filters used in [popularNovels](#pluginbasepopularnovels) function
|
||||
@@ -312,43 +332,6 @@ class ExamplePlugin implements Plugin.PluginBase {
|
||||
}
|
||||
```
|
||||
|
||||
#### PluginBase::fetchImage
|
||||
|
||||
Function used if images failed to load due to site's protection
|
||||
|
||||
```ts
|
||||
async fetchImage(url: string): Promise<string | undefined>
|
||||
```
|
||||
|
||||
See [Fetch functions]() for detailed list of fetch functions provided by us to help with fetching data
|
||||
|
||||
###### Parameter
|
||||
|
||||
- `url` Image's url to fetch
|
||||
|
||||
###### Returns
|
||||
|
||||
- `string` base64 representation of the image
|
||||
|
||||
or
|
||||
|
||||
- `undefined` on error
|
||||
|
||||
###### Example
|
||||
|
||||
```ts
|
||||
class ExamplePlugin implements Plugin.PluginBase {
|
||||
...
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
const headers = {
|
||||
Referer: "https://ln.hako.vn",
|
||||
};
|
||||
return await fetchFile(url, { headers: headers });
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### NovelItem
|
||||
|
||||
@@ -14,6 +14,7 @@ class TemplatePlugin implements Plugin.PluginBase {
|
||||
site = 'https://example.com';
|
||||
version = '1.0.0';
|
||||
filters: Filters | undefined = undefined;
|
||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
||||
|
||||
async popularNovels(
|
||||
pageNo: number,
|
||||
@@ -80,11 +81,6 @@ class TemplatePlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TemplatePlugin();
|
||||
|
||||
@@ -180,8 +180,6 @@ class Shu69 implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
rank: {
|
||||
label: '排行榜',
|
||||
|
||||
@@ -181,8 +181,6 @@ class XinShu69 implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
class: {
|
||||
label: '分类',
|
||||
|
||||
@@ -521,13 +521,6 @@ class Linovelib implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
const headers = new Headers({
|
||||
'Referer': `${this.site}/`,
|
||||
});
|
||||
return await fetchFile(url, { headers });
|
||||
}
|
||||
|
||||
filters = {
|
||||
rank: {
|
||||
label: '排行榜',
|
||||
|
||||
@@ -148,8 +148,6 @@ class LibReadPlugin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
type_genre: {
|
||||
type: FilterTypes.Picker,
|
||||
|
||||
@@ -146,10 +146,6 @@ class NovelsOnline implements Plugin.PluginBase {
|
||||
.filter(sr => sr !== null);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
value: 'top_rated',
|
||||
|
||||
@@ -156,9 +156,6 @@ class StorySeedlingPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new StorySeedlingPlugin();
|
||||
|
||||
@@ -148,10 +148,6 @@ class AllNovelFullPlugin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: '/most-popular',
|
||||
|
||||
@@ -169,10 +169,6 @@ class BLN implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
status: {
|
||||
label: 'Status',
|
||||
|
||||
@@ -157,10 +157,6 @@ class ComradeMaoPlugin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
category: {
|
||||
value: '',
|
||||
|
||||
@@ -128,10 +128,6 @@ class DDLPlugin implements Plugin.PluginBase {
|
||||
const loadedCheerio = parseHTML(body);
|
||||
return this.parseNovels(loadedCheerio, searchTerm);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new DDLPlugin();
|
||||
|
||||
@@ -139,10 +139,6 @@ class EarlyNovelPlugin implements Plugin.PagePlugin {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: '/most-popular',
|
||||
|
||||
@@ -161,8 +161,6 @@ class FaqWikiUs implements Plugin.PluginBase {
|
||||
|
||||
return this.parseNovels(loadedCheerio, searchTerm);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
export default new FaqWikiUs();
|
||||
|
||||
@@ -144,8 +144,6 @@ class FreeWebNovel implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
genres: {
|
||||
type: FilterTypes.Picker,
|
||||
|
||||
+110
-108
@@ -19,33 +19,33 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
const novels: Plugin.NovelItem[] = [];
|
||||
let tempNovel = {} as Plugin.NovelItem;
|
||||
let isParsingNovel = false;
|
||||
const parser = new Parser ({
|
||||
onopentag(name, attribs){
|
||||
if (isParsingNovel){
|
||||
if (name === 'a'){
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (isParsingNovel) {
|
||||
if (name === 'a') {
|
||||
tempNovel.path = attribs['href'].slice(1);
|
||||
tempNovel.name = attribs['title'];
|
||||
}
|
||||
if (name === 'img'){
|
||||
if (name === 'img') {
|
||||
tempNovel.cover = attribs['data-src'] || attribs['src'];
|
||||
}
|
||||
if (tempNovel.path && tempNovel.cover){
|
||||
if (tempNovel.path && tempNovel.cover) {
|
||||
novels.push(tempNovel);
|
||||
tempNovel = {} as Plugin.NovelItem;
|
||||
}
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'class' && value === 'novel-item'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'novel-item') {
|
||||
isParsingNovel = true;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'li'){
|
||||
onclosetag(name) {
|
||||
if (name === 'li') {
|
||||
isParsingNovel = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
return novels;
|
||||
@@ -76,7 +76,7 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
summary: '',
|
||||
totalPages: 1,
|
||||
chapters: [],
|
||||
}
|
||||
};
|
||||
let isHeaderStats = false;
|
||||
let isStatus = false;
|
||||
let isTotalChapters = false;
|
||||
@@ -85,95 +85,95 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
let isSummary = false;
|
||||
let isGenres = false;
|
||||
let isTags = false;
|
||||
let genreArray: string[] = []
|
||||
let genreArray: string[] = [];
|
||||
let isCover = false;
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs){
|
||||
if(name === 'h1' && attribs['class']?.includes('novel-title')){
|
||||
onopentag(name, attribs) {
|
||||
if (name === 'h1' && attribs['class']?.includes('novel-title')) {
|
||||
isNovelName = true;
|
||||
}
|
||||
if(name === 'div' && attribs['class']?.includes('content')){
|
||||
if (name === 'div' && attribs['class']?.includes('content')) {
|
||||
isSummary = true;
|
||||
}
|
||||
if(name === 'figure' && attribs['class'] === 'cover'){
|
||||
if (name === 'figure' && attribs['class'] === 'cover') {
|
||||
isCover = true;
|
||||
}
|
||||
if(isCover){
|
||||
if(name === 'img'){
|
||||
if (isCover) {
|
||||
if (name === 'img') {
|
||||
novel.cover = attribs['data-src'] || attribs['src'];
|
||||
}
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (isHeaderStats && name === 'strong'){
|
||||
onopentagname(name) {
|
||||
if (isHeaderStats && name === 'strong') {
|
||||
isStatus = true;
|
||||
}
|
||||
if (isSummary && name === 'br'){
|
||||
if (isSummary && name === 'br') {
|
||||
novel.summary += '\n';
|
||||
}
|
||||
if (isGenres && name === 'a'){
|
||||
if (isGenres && name === 'a') {
|
||||
isTags = true;
|
||||
}
|
||||
},
|
||||
onattribute(name,value){
|
||||
if (name === 'class' && value === 'header-stats'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'header-stats') {
|
||||
isTotalChapters = true;
|
||||
isHeaderStats = true;
|
||||
}
|
||||
if (name === 'itemprop' && value === 'author'){
|
||||
if (name === 'itemprop' && value === 'author') {
|
||||
isAuthorName = true;
|
||||
}
|
||||
if (name === 'class' && value === 'categories'){
|
||||
if (name === 'class' && value === 'categories') {
|
||||
isGenres = true;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isTotalChapters){
|
||||
ontext(data) {
|
||||
if (isTotalChapters) {
|
||||
novel.totalPages = Math.ceil(parseInt(data, 10) / 100);
|
||||
}
|
||||
if(isStatus){
|
||||
if (isStatus) {
|
||||
novel.status = data.trim();
|
||||
}
|
||||
if(isNovelName){
|
||||
if (isNovelName) {
|
||||
novel.name += data.trim();
|
||||
}
|
||||
if(isAuthorName){
|
||||
if (isAuthorName) {
|
||||
novel.author = data;
|
||||
}
|
||||
if(isSummary){
|
||||
if (isSummary) {
|
||||
novel.summary += data;
|
||||
}
|
||||
if(isTags){
|
||||
if (isTags) {
|
||||
genreArray.push(data);
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'strong'){
|
||||
onclosetag(name) {
|
||||
if (name === 'strong') {
|
||||
isTotalChapters = false;
|
||||
isStatus = false;
|
||||
}
|
||||
if(name === 'i'){
|
||||
if (name === 'i') {
|
||||
isStatus = false;
|
||||
}
|
||||
if(name === 'h1'){
|
||||
if (name === 'h1') {
|
||||
isNovelName = false;
|
||||
}
|
||||
if(name === 'span'){
|
||||
if (name === 'span') {
|
||||
isAuthorName = false;
|
||||
}
|
||||
if(name === 'div'){
|
||||
if (name === 'div') {
|
||||
isHeaderStats = false;
|
||||
isSummary = false;
|
||||
isGenres = false;
|
||||
}
|
||||
if(name === 'a'){
|
||||
if (name === 'a') {
|
||||
isTags = false;
|
||||
}
|
||||
if(name === 'figure'){
|
||||
if (name === 'figure') {
|
||||
isCover = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(body);
|
||||
parser.end();
|
||||
novel.genres = genreArray.join(', ');
|
||||
@@ -184,48 +184,51 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
const url = this.site + novelPath + '/chapters/page-' + page;
|
||||
const body = await fetchApi(url).then(res => res.text());
|
||||
const chapter: Plugin.ChapterItem[] = [];
|
||||
let tempChapter = {} as Plugin.ChapterItem;
|
||||
let tempChapter = {} as Plugin.ChapterItem;
|
||||
let isChapterItem = false;
|
||||
let isChapterList = false;
|
||||
const parser = new Parser ({
|
||||
onopentag(name, attribs){
|
||||
if(isChapterList){
|
||||
if (name === 'li'){
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (isChapterList) {
|
||||
if (name === 'li') {
|
||||
isChapterItem = true;
|
||||
tempChapter.chapterNumber = Number(attribs['data-orderno']);
|
||||
}
|
||||
if (isChapterItem){
|
||||
if (name === 'a'){
|
||||
if (isChapterItem) {
|
||||
if (name === 'a') {
|
||||
tempChapter.name = attribs['title'];
|
||||
tempChapter.path = attribs['href'].slice(1);
|
||||
}
|
||||
if (name === 'time'){
|
||||
tempChapter.releaseTime = dayjs(attribs['datetime']).toISOString();
|
||||
if (name === 'time') {
|
||||
tempChapter.releaseTime = dayjs(
|
||||
attribs['datetime'],
|
||||
).toISOString();
|
||||
}
|
||||
if (
|
||||
tempChapter.chapterNumber &&
|
||||
tempChapter.path &&
|
||||
tempChapter.releaseTime){
|
||||
chapter.push(tempChapter);
|
||||
tempChapter = {} as Plugin.ChapterItem;
|
||||
tempChapter.chapterNumber &&
|
||||
tempChapter.path &&
|
||||
tempChapter.releaseTime
|
||||
) {
|
||||
chapter.push(tempChapter);
|
||||
tempChapter = {} as Plugin.ChapterItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'class' && value === 'chapter-list'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'chapter-list') {
|
||||
isChapterList = true;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'a'){
|
||||
onclosetag(name) {
|
||||
if (name === 'a') {
|
||||
isChapterItem = false;
|
||||
}
|
||||
if (name === 'ul'){
|
||||
if (name === 'ul') {
|
||||
isChapterList = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(body);
|
||||
parser.end();
|
||||
const chapters = chapter;
|
||||
@@ -240,92 +243,92 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
let isPtag = false;
|
||||
let isStyleText = false;
|
||||
const parser = new Parser({
|
||||
onopentag(name,attribs){
|
||||
if (isChapter && name === 'div'){
|
||||
let stylediv = attribs['style']
|
||||
if(stylediv){
|
||||
chapterText += `<div style="${stylediv}">`
|
||||
onopentag(name, attribs) {
|
||||
if (isChapter && name === 'div') {
|
||||
let stylediv = attribs['style'];
|
||||
if (stylediv) {
|
||||
chapterText += `<div style="${stylediv}">`;
|
||||
isStyleText = true;
|
||||
} else {
|
||||
chapterText += `<div>`
|
||||
chapterText += `<div>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
let w = attribs['width'];
|
||||
if(w) {
|
||||
if (w) {
|
||||
chapterText += `<table width="${w}">`;
|
||||
} else {
|
||||
chapterText += `<table>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `<tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `<tr>`;
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
let w1 = attribs['width'];
|
||||
if(w1) {
|
||||
if (w1) {
|
||||
chapterText += `<td width="${w1}">`;
|
||||
} else {
|
||||
chapterText += `<td>`;
|
||||
}
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'id' && value === 'chapter-container'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'id' && value === 'chapter-container') {
|
||||
isChapter = true;
|
||||
}
|
||||
if (name === 'class' && value?.includes('chapternav')){
|
||||
if (name === 'class' && value?.includes('chapternav')) {
|
||||
isChapter = false;
|
||||
isPtag = false;
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (isChapter && name === 'p'){
|
||||
onopentagname(name) {
|
||||
if (isChapter && name === 'p') {
|
||||
chapterText += '<p>';
|
||||
isPtag = true;
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
isStyleText = false;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'br'){
|
||||
if (isChapter && name === 'br') {
|
||||
chapterText += `<br>`;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isPtag){
|
||||
ontext(data) {
|
||||
if (isPtag) {
|
||||
chapterText += data;
|
||||
}
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
chapterText += data;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'p'){
|
||||
onclosetag(name) {
|
||||
if (name === 'p') {
|
||||
isPtag = false;
|
||||
chapterText += '</p>'
|
||||
chapterText += '</p>';
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
chapterText += `</td>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `</tr>`;
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `</tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
chapterText += `</table>`;
|
||||
}
|
||||
if (isChapter && name === 'div'){
|
||||
if (isChapter && name === 'div') {
|
||||
isStyleText = false;
|
||||
chapterText += `</div>`
|
||||
chapterText += `</div>`;
|
||||
}
|
||||
}
|
||||
})
|
||||
parser.write(body)
|
||||
},
|
||||
});
|
||||
parser.write(body);
|
||||
parser.end();
|
||||
|
||||
return chapterText;
|
||||
@@ -339,13 +342,16 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
const link = `${this.site}search`;
|
||||
const response = await fetchApi(link).then(r => r.text());
|
||||
let verifytoken = '';
|
||||
const parser = new Parser ({
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (name === 'input' && attribs['name']?.includes('LNRequestVerifyToken')){
|
||||
if (
|
||||
name === 'input' &&
|
||||
attribs['name']?.includes('LNRequestVerifyToken')
|
||||
) {
|
||||
verifytoken = attribs['value'];
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
parser.write(response);
|
||||
parser.end();
|
||||
|
||||
@@ -358,11 +364,7 @@ class LightNovelPub implements Plugin.PagePlugin {
|
||||
body: formData,
|
||||
}).then(r => r.json());
|
||||
|
||||
return this.parseNovels(body.resultview)
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url, { headers: this.headers });
|
||||
return this.parseNovels(body.resultview);
|
||||
}
|
||||
|
||||
filters = {
|
||||
|
||||
+70
-71
@@ -28,15 +28,15 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
const html = await body.text();
|
||||
const baseUrl = this.site;
|
||||
let isParsingNovel = false;
|
||||
let tempNovel = {} as Plugin.NovelItem;
|
||||
let tempNovel = {} as Plugin.NovelItem;
|
||||
const novels: Plugin.NovelItem[] = [];
|
||||
const parser = new Parser ({
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (attribs['class']?.includes('media-left')) {
|
||||
isParsingNovel = true;
|
||||
}
|
||||
if (isParsingNovel) {
|
||||
switch (name){
|
||||
switch (name) {
|
||||
case 'a':
|
||||
tempNovel.path = attribs['href'].slice(baseUrl.length);
|
||||
break;
|
||||
@@ -45,14 +45,14 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
tempNovel.cover = attribs['src'];
|
||||
break;
|
||||
}
|
||||
if (tempNovel.path && tempNovel.name){
|
||||
if (tempNovel.path && tempNovel.name) {
|
||||
novels.push(tempNovel);
|
||||
tempNovel = {} as Plugin.NovelItem;
|
||||
}
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'div'){
|
||||
onclosetag(name) {
|
||||
if (name === 'div') {
|
||||
isParsingNovel = false;
|
||||
}
|
||||
},
|
||||
@@ -83,59 +83,59 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
let isSource = false;
|
||||
let isPanelKey = false;
|
||||
let isPanelValue = 0;
|
||||
let isAuthorKey = false
|
||||
let isStatusKey = false
|
||||
let isAuthorKey = false;
|
||||
let isStatusKey = false;
|
||||
let isList = 0;
|
||||
let isGenres = false;
|
||||
let genreArray: string[] = []
|
||||
let genreArray: string[] = [];
|
||||
const parser = new Parser({
|
||||
onopentag(name,attribs) {
|
||||
if (name === 'img' && attribs['class']?.includes('img-rounded')){
|
||||
onopentag(name, attribs) {
|
||||
if (name === 'img' && attribs['class']?.includes('img-rounded')) {
|
||||
novel.name = attribs['title'];
|
||||
novel.cover = attribs['src'];
|
||||
}
|
||||
if (name === 'ul' && attribs['class']?.includes('list-inline')){
|
||||
if (name === 'ul' && attribs['class']?.includes('list-inline')) {
|
||||
isList++;
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (name === 'dt'){
|
||||
onopentagname(name) {
|
||||
if (name === 'dt') {
|
||||
isPanelKey = true;
|
||||
}
|
||||
if (name === 'dd'){
|
||||
if (name === 'dd') {
|
||||
isPanelValue++;
|
||||
}
|
||||
if (isList === 1 && name === 'li'){
|
||||
if (isList === 1 && name === 'li') {
|
||||
isGenres = true;
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'class' && value === 'description'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'description') {
|
||||
isDescription = true;
|
||||
}
|
||||
if (name === 'class' && value === 'source'){
|
||||
if (name === 'class' && value === 'source') {
|
||||
isDescription = false;
|
||||
isSource = true;
|
||||
}
|
||||
if (name === 'class' && value === 'progress'){
|
||||
if (name === 'class' && value === 'progress') {
|
||||
isSource = false;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isScript){
|
||||
ontext(data) {
|
||||
if (isScript) {
|
||||
const volume = JSON.parse(
|
||||
data.match(/lnmtl.volumes = (.+])(?=;)/)![1] || ''
|
||||
data.match(/lnmtl.volumes = (.+])(?=;)/)![1] || '',
|
||||
);
|
||||
novel.totalPages = volume.length;
|
||||
}
|
||||
if(isDescription){
|
||||
if (isDescription) {
|
||||
novel.summary += data.trim() + '\n\n';
|
||||
}
|
||||
if(isSource){
|
||||
if (isSource) {
|
||||
novel.summary += data;
|
||||
}
|
||||
if(isPanelKey){
|
||||
switch(data){
|
||||
if (isPanelKey) {
|
||||
switch (data) {
|
||||
case 'Authors':
|
||||
isAuthorKey = true;
|
||||
break;
|
||||
@@ -144,32 +144,32 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(isAuthorKey && isPanelValue === 1){
|
||||
if (isAuthorKey && isPanelValue === 1) {
|
||||
novel.author += data.trim();
|
||||
isAuthorKey = false;
|
||||
}
|
||||
if(isStatusKey && isPanelValue === 2){
|
||||
if (isStatusKey && isPanelValue === 2) {
|
||||
novel.status += data.trim();
|
||||
isStatusKey = false;
|
||||
}
|
||||
if(isGenres){
|
||||
if (isGenres) {
|
||||
genreArray.push(data.trim());
|
||||
novel.genres = genreArray.join(', ');
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'ul'){
|
||||
onclosetag(name) {
|
||||
if (name === 'ul') {
|
||||
isGenres = false;
|
||||
}
|
||||
if(name === 'main'){
|
||||
if (name === 'main') {
|
||||
isPanelKey = false;
|
||||
isScript = true;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
return novel;
|
||||
@@ -182,25 +182,25 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
let volume: VolumeEntry = {
|
||||
id: '',
|
||||
title: '',
|
||||
}
|
||||
};
|
||||
const parser = new Parser({
|
||||
ontext(data){
|
||||
if(isScript){
|
||||
ontext(data) {
|
||||
if (isScript) {
|
||||
const volumes = JSON.parse(
|
||||
data.match(/lnmtl.volumes = (.+])(?=;)/)![1] || ''
|
||||
data.match(/lnmtl.volumes = (.+])(?=;)/)![1] || '',
|
||||
);
|
||||
volume = volumes[+page-1]
|
||||
volume = volumes[+page - 1];
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'main'){
|
||||
onclosetag(name) {
|
||||
if (name === 'main') {
|
||||
isScript = true;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
@@ -243,29 +243,29 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
let isText = false;
|
||||
let chapterText = '';
|
||||
const parser = new Parser({
|
||||
onopentag(name,attribs){
|
||||
if(name === 'sentence' && attribs['class']?.includes('translated')){
|
||||
onopentag(name, attribs) {
|
||||
if (name === 'sentence' && attribs['class']?.includes('translated')) {
|
||||
isText = true;
|
||||
chapterText += '<p>'
|
||||
chapterText += '<p>';
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if(name === 'nav'){
|
||||
onopentagname(name) {
|
||||
if (name === 'nav') {
|
||||
isText = false;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isText){
|
||||
ontext(data) {
|
||||
if (isText) {
|
||||
chapterText += data;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'sentence'){
|
||||
chapterText += '</p>'
|
||||
onclosetag(name) {
|
||||
if (name === 'sentence') {
|
||||
chapterText += '</p>';
|
||||
isText = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
@@ -281,31 +281,34 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
.then(r => r.replace(/>\s+</g, '><'));
|
||||
let isScript = false;
|
||||
let isFooter = false;
|
||||
let list = ''
|
||||
let list = '';
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if(isFooter && name === 'script' &&
|
||||
attribs['type']?.includes('application/javascript')){
|
||||
if (
|
||||
isFooter &&
|
||||
name === 'script' &&
|
||||
attribs['type']?.includes('application/javascript')
|
||||
) {
|
||||
isScript = true;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if (isScript){
|
||||
ontext(data) {
|
||||
if (isScript) {
|
||||
list = data.match(/prefetch: '\/(.*json)/)![1];
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'footer'){
|
||||
onclosetag(name) {
|
||||
if (name === 'footer') {
|
||||
isFooter = true;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
if (name === 'body'){
|
||||
if (name === 'body') {
|
||||
isFooter = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
@@ -332,10 +335,6 @@ class LnMTLPlugin implements Plugin.PagePlugin {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: 'favourites',
|
||||
|
||||
@@ -145,11 +145,6 @@ class MTLNovel implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
const headers = new Headers();
|
||||
headers.append('Alt-Used', 'www.mtlnovel.com');
|
||||
return fetchFile(url, { headers });
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
|
||||
@@ -103,9 +103,5 @@ class MTLReader implements Plugin.PluginBase {
|
||||
const loadedCheerio = parseHTML(seacrhBody);
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
export default new MTLReader();
|
||||
|
||||
@@ -9,6 +9,11 @@ class NovelBin implements Plugin.PluginBase {
|
||||
icon = 'src/en/novelbin/icon.png';
|
||||
site = 'https://binnovel.com/';
|
||||
version = '1.0.1';
|
||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
|
||||
headers: {
|
||||
'referrer': this.site,
|
||||
},
|
||||
};
|
||||
parseNovels(loadedCheerio: CheerioAPI) {
|
||||
const novels: Plugin.NovelItem[] = [];
|
||||
|
||||
@@ -143,14 +148,6 @@ class NovelBin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url, {
|
||||
headers: {
|
||||
'referrer': this.site,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
value: 'popular-novels',
|
||||
|
||||
@@ -169,10 +169,6 @@ class NovelBuddy implements Plugin.PluginBase {
|
||||
const loadedCheerio = parseHTML(body);
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new NovelBuddy();
|
||||
|
||||
@@ -135,10 +135,6 @@ class NovelFull implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
value: 'most-popular',
|
||||
|
||||
@@ -126,9 +126,6 @@ class NovelHall implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new NovelHall();
|
||||
|
||||
@@ -713,10 +713,6 @@ class NovelUpdates implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Sort Results By',
|
||||
|
||||
@@ -137,10 +137,6 @@ class PawRead implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
status: {
|
||||
value: '',
|
||||
|
||||
+108
-119
@@ -19,49 +19,51 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
const novels: Plugin.NovelItem[] = [];
|
||||
let tempNovel = {} as Plugin.NovelItem;
|
||||
tempNovel.name = '';
|
||||
const baseUrl = this.site
|
||||
const baseUrl = this.site;
|
||||
let isParsingNovel = false;
|
||||
let isTitleTag = false;
|
||||
let isNovelName = false;
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (attribs['class']?.includes('short-cont')){
|
||||
if (attribs['class']?.includes('short-cont')) {
|
||||
isParsingNovel = true;
|
||||
}
|
||||
if (isParsingNovel){
|
||||
if (name === 'h2' && attribs['class']?.includes('title')){
|
||||
if (isParsingNovel) {
|
||||
if (name === 'h2' && attribs['class']?.includes('title')) {
|
||||
isTitleTag = true;
|
||||
}
|
||||
if (isTitleTag && name === 'a'){
|
||||
if (isTitleTag && name === 'a') {
|
||||
tempNovel.path = attribs['href'].slice(baseUrl.length);
|
||||
isNovelName = true;
|
||||
}
|
||||
if (name === 'figure'){
|
||||
tempNovel.cover = attribs['style']
|
||||
.replace(/.*url\((.*?)\)./g, '$1');
|
||||
if (name === 'figure') {
|
||||
tempNovel.cover = attribs['style'].replace(
|
||||
/.*url\((.*?)\)./g,
|
||||
'$1',
|
||||
);
|
||||
}
|
||||
if (tempNovel.path && tempNovel.cover){
|
||||
if (tempNovel.path && tempNovel.cover) {
|
||||
novels.push(tempNovel);
|
||||
tempNovel = {} as Plugin.NovelItem;
|
||||
tempNovel.name = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isNovelName){
|
||||
ontext(data) {
|
||||
if (isNovelName) {
|
||||
tempNovel.name += data;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'h2'){
|
||||
onclosetag(name) {
|
||||
if (name === 'h2') {
|
||||
isNovelName = false;
|
||||
isTitleTag = false;
|
||||
}
|
||||
if(name === 'figure'){
|
||||
if (name === 'figure') {
|
||||
isParsingNovel = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
return novels;
|
||||
@@ -104,7 +106,7 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
summary: '',
|
||||
chapters: [],
|
||||
totalPages: 1,
|
||||
}
|
||||
};
|
||||
let baseUrl = this.site;
|
||||
let isCover = false;
|
||||
let isAuthor = false;
|
||||
@@ -113,108 +115,102 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
let isStatusText = false;
|
||||
let isGenres = false;
|
||||
let isGenresText = false;
|
||||
let genreArray: string[] = []
|
||||
let genreArray: string[] = [];
|
||||
let novelId = '';
|
||||
const parser = new Parser ({
|
||||
onopentag(name,attribs){
|
||||
if (attribs['class'] === 'poster'){
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (attribs['class'] === 'poster') {
|
||||
isCover = true;
|
||||
}
|
||||
if (isCover && name === 'img'){
|
||||
if (isCover && name === 'img') {
|
||||
novel.name = attribs['alt'];
|
||||
novel.cover = baseUrl + attribs['src'];
|
||||
}
|
||||
if (name === 'div' && attribs['class'] === 'moreless'){
|
||||
if (name === 'div' && attribs['class'] === 'moreless') {
|
||||
isSummary = true;
|
||||
}
|
||||
if (name === 'li' && attribs['title']?.includes('Original status')){
|
||||
if (name === 'li' && attribs['title']?.includes('Original status')) {
|
||||
isStatus = true;
|
||||
}
|
||||
if (name === 'input' && attribs['name'] === 'newsid'){
|
||||
novelId = attribs['value']
|
||||
if (name === 'input' && attribs['name'] === 'newsid') {
|
||||
novelId = attribs['value'];
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (isSummary && name === 'br'){
|
||||
onopentagname(name) {
|
||||
if (isSummary && name === 'br') {
|
||||
novel.summary += `/n`;
|
||||
}
|
||||
if (isStatus && name === 'a'){
|
||||
if (isStatus && name === 'a') {
|
||||
isStatusText = true;
|
||||
}
|
||||
if (isGenres && name === 'a'){
|
||||
if (isGenres && name === 'a') {
|
||||
isGenresText = true;
|
||||
}
|
||||
},
|
||||
onattribute(name,value){
|
||||
if (name === 'itemprop' && value === 'creator'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'itemprop' && value === 'creator') {
|
||||
isAuthor = true;
|
||||
}
|
||||
if (name === 'id' && value === 'mc-fs-genre'){
|
||||
if (name === 'id' && value === 'mc-fs-genre') {
|
||||
isGenres = true;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isAuthor){
|
||||
ontext(data) {
|
||||
if (isAuthor) {
|
||||
novel.author = data;
|
||||
}
|
||||
if(isSummary){
|
||||
if (isSummary) {
|
||||
novel.summary += data;
|
||||
}
|
||||
if(isStatusText){
|
||||
novel.status = data === 'Ongoing'
|
||||
? 'Ongoing'
|
||||
: 'Completed';
|
||||
if (isStatusText) {
|
||||
novel.status = data === 'Ongoing' ? 'Ongoing' : 'Completed';
|
||||
}
|
||||
if(isGenresText){
|
||||
if (isGenresText) {
|
||||
genreArray.push(data);
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'a'){
|
||||
onclosetag(name) {
|
||||
if (name === 'a') {
|
||||
isCover = false;
|
||||
isAuthor = false;
|
||||
isStatusText = false;
|
||||
isGenresText = false;
|
||||
isStatus = false;
|
||||
}
|
||||
if(name === 'div'){
|
||||
if (name === 'div') {
|
||||
isSummary = false;
|
||||
isGenres = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
novel.genres = genreArray.join(', ');
|
||||
|
||||
const chapterListUrl = this.site + '/chapters/' + novelId + '/';
|
||||
const chaptersHtml = await fetchApi(chapterListUrl).then(r =>
|
||||
r.text(),
|
||||
);
|
||||
let dataJson: {
|
||||
pages_count: string,
|
||||
chapters: ChapterEntry[]
|
||||
} = { pages_count: '', chapters : [] };
|
||||
const chaptersHtml = await fetchApi(chapterListUrl).then(r => r.text());
|
||||
let dataJson: {
|
||||
pages_count: string;
|
||||
chapters: ChapterEntry[];
|
||||
} = { pages_count: '', chapters: [] };
|
||||
let isScript = false;
|
||||
const parser2 = new Parser ({
|
||||
ontext(data){
|
||||
if(isScript){
|
||||
if (data.includes('window.__DATA__ =')){
|
||||
dataJson = JSON.parse(
|
||||
data.replace('window.__DATA__ =', '')
|
||||
);
|
||||
const parser2 = new Parser({
|
||||
ontext(data) {
|
||||
if (isScript) {
|
||||
if (data.includes('window.__DATA__ =')) {
|
||||
dataJson = JSON.parse(data.replace('window.__DATA__ =', ''));
|
||||
}
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'main'){
|
||||
onclosetag(name) {
|
||||
if (name === 'main') {
|
||||
isScript = true;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
},
|
||||
})
|
||||
});
|
||||
parser2.write(chaptersHtml);
|
||||
parser2.end();
|
||||
|
||||
@@ -241,29 +237,27 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
const pageUrl = firstUrl + '/page/' + page;
|
||||
const pageBody = await fetchApi(pageUrl).then(r => r.text());
|
||||
let isScript = false;
|
||||
let dataJson: {
|
||||
pages_count: string,
|
||||
chapters: ChapterEntry[]
|
||||
} = { pages_count: '', chapters : [] };
|
||||
let dataJson: {
|
||||
pages_count: string;
|
||||
chapters: ChapterEntry[];
|
||||
} = { pages_count: '', chapters: [] };
|
||||
const parser = new Parser({
|
||||
ontext(data){
|
||||
if(isScript){
|
||||
if (data.includes('window.__DATA__ =')){
|
||||
dataJson = JSON.parse(
|
||||
data.replace('window.__DATA__ =', '')
|
||||
);
|
||||
ontext(data) {
|
||||
if (isScript) {
|
||||
if (data.includes('window.__DATA__ =')) {
|
||||
dataJson = JSON.parse(data.replace('window.__DATA__ =', ''));
|
||||
}
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'main'){
|
||||
onclosetag(name) {
|
||||
if (name === 'main') {
|
||||
isScript = true;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(pageBody);
|
||||
parser.end();
|
||||
const chapters = this.parseChapters(dataJson);
|
||||
@@ -280,92 +274,92 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
let isPtag = false;
|
||||
let isStyleText = false;
|
||||
const parser = new Parser({
|
||||
onopentag(name,attribs){
|
||||
if (isChapter && name === 'div'){
|
||||
let stylediv = attribs['style']
|
||||
if(stylediv){
|
||||
chapterText += `<div style="${stylediv}">`
|
||||
onopentag(name, attribs) {
|
||||
if (isChapter && name === 'div') {
|
||||
let stylediv = attribs['style'];
|
||||
if (stylediv) {
|
||||
chapterText += `<div style="${stylediv}">`;
|
||||
isStyleText = true;
|
||||
} else {
|
||||
chapterText += `<div>`
|
||||
chapterText += `<div>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
let w = attribs['width'];
|
||||
if(w) {
|
||||
if (w) {
|
||||
chapterText += `<table width="${w}">`;
|
||||
} else {
|
||||
chapterText += `<table>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `<tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `<tr>`;
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
let w1 = attribs['width'];
|
||||
if(w1) {
|
||||
if (w1) {
|
||||
chapterText += `<td width="${w1}">`;
|
||||
} else {
|
||||
chapterText += `<td>`;
|
||||
}
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'id' && value === 'arrticle'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'id' && value === 'arrticle') {
|
||||
isChapter = true;
|
||||
}
|
||||
if (name === 'class' && value === 'category grey ellipses'){
|
||||
if (name === 'class' && value === 'category grey ellipses') {
|
||||
isChapter = false;
|
||||
isPtag = false;
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (isChapter && name === 'p'){
|
||||
onopentagname(name) {
|
||||
if (isChapter && name === 'p') {
|
||||
chapterText += '<p>';
|
||||
isPtag = true;
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
isStyleText = false;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'br'){
|
||||
if (isChapter && name === 'br') {
|
||||
chapterText += `<br>`;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isPtag){
|
||||
ontext(data) {
|
||||
if (isPtag) {
|
||||
chapterText += data;
|
||||
}
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
chapterText += data;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'p'){
|
||||
onclosetag(name) {
|
||||
if (name === 'p') {
|
||||
isPtag = false;
|
||||
chapterText += '</p>'
|
||||
chapterText += '</p>';
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
chapterText += `</td>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `</tr>`;
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `</tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
chapterText += `</table>`;
|
||||
}
|
||||
if (isChapter && name === 'div'){
|
||||
if (isChapter && name === 'div') {
|
||||
isStyleText = false;
|
||||
chapterText += `</div>`
|
||||
chapterText += `</div>`;
|
||||
}
|
||||
}
|
||||
})
|
||||
parser.write(html)
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
return chapterText;
|
||||
@@ -380,11 +374,6 @@ class RanobesPlugin implements Plugin.PagePlugin {
|
||||
|
||||
return this.parseNovels(body);
|
||||
}
|
||||
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
}
|
||||
export default new RanobesPlugin();
|
||||
|
||||
@@ -393,4 +382,4 @@ interface ChapterEntry {
|
||||
title: string;
|
||||
date: string;
|
||||
link: string;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -174,10 +174,6 @@ class ReadLiteNovel implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: 'top-rated',
|
||||
|
||||
@@ -382,10 +382,6 @@ class ReLibraryPlugin implements Plugin.PluginBase {
|
||||
this.searchFunc.setHaystack(novels);
|
||||
return this.searchFunc.search(searchTerm);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url, { headers: { referer: this.site } });
|
||||
}
|
||||
}
|
||||
|
||||
export default new ReLibraryPlugin();
|
||||
|
||||
@@ -18,37 +18,37 @@ class RoyalRoad implements Plugin.PluginBase {
|
||||
let isParsingNovel = false;
|
||||
let isNovelName = false;
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs){
|
||||
if (attribs['class']?.includes('fiction-list-item')){
|
||||
onopentag(name, attribs) {
|
||||
if (attribs['class']?.includes('fiction-list-item')) {
|
||||
isParsingNovel = true;
|
||||
}
|
||||
if (isParsingNovel){
|
||||
if (name === 'a' && attribs['class']?.includes('bold')){
|
||||
if (isParsingNovel) {
|
||||
if (name === 'a' && attribs['class']?.includes('bold')) {
|
||||
tempNovel.path = attribs['href'].slice(1);
|
||||
isNovelName = true;
|
||||
}
|
||||
if (name === 'img'){
|
||||
if (name === 'img') {
|
||||
tempNovel.cover = attribs['src'];
|
||||
}
|
||||
if (tempNovel.path && tempNovel.name){
|
||||
if (tempNovel.path && tempNovel.name) {
|
||||
novels.push(tempNovel);
|
||||
tempNovel = {} as Plugin.NovelItem;
|
||||
tempNovel.name = '';
|
||||
}
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isNovelName){
|
||||
ontext(data) {
|
||||
if (isNovelName) {
|
||||
tempNovel.name += data;
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if(name === 'h2'){
|
||||
onclosetag(name) {
|
||||
if (name === 'h2') {
|
||||
isNovelName = false;
|
||||
isParsingNovel = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
return novels;
|
||||
@@ -64,9 +64,9 @@ class RoyalRoad implements Plugin.PluginBase {
|
||||
link += `?page=${page}`;
|
||||
|
||||
if (filters.genre.value !== '') link += `&genre=${filters.genre.value}`;
|
||||
|
||||
|
||||
const body = await fetchApi(link).then(r => r.text());
|
||||
|
||||
|
||||
return this.parseNovels(body);
|
||||
}
|
||||
|
||||
@@ -78,110 +78,110 @@ class RoyalRoad implements Plugin.PluginBase {
|
||||
name: '',
|
||||
summary: '',
|
||||
chapters: [],
|
||||
}
|
||||
};
|
||||
let isNovelName = false;
|
||||
let isAuthorName = false;
|
||||
let isDescription = false;
|
||||
let isH4 = false;
|
||||
let isSpan = 0
|
||||
let isSpan = 0;
|
||||
let isTags = false;
|
||||
let isGenres = false;
|
||||
let genreArray: string[] = []
|
||||
let genreArray: string[] = [];
|
||||
let isFooter = false;
|
||||
let isScript = false;
|
||||
let chapterJson: ChapterEntry[] = [];
|
||||
let volumeJson: VolumeEntry[] = [];
|
||||
const parser = new Parser ({
|
||||
onopentag(name,attribs){
|
||||
if (name === 'img' && attribs['class']?.includes('thumbnail')){
|
||||
const parser = new Parser({
|
||||
onopentag(name, attribs) {
|
||||
if (name === 'img' && attribs['class']?.includes('thumbnail')) {
|
||||
novel.cover = attribs['src'];
|
||||
}
|
||||
if (name === 'span' && attribs['class']?.includes('label-sm')){
|
||||
if (name === 'span' && attribs['class']?.includes('label-sm')) {
|
||||
isSpan++;
|
||||
}
|
||||
if (name === 'span' && attribs['class']?.includes('tags')){
|
||||
if (name === 'span' && attribs['class']?.includes('tags')) {
|
||||
isTags = true;
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (name === 'h1'){
|
||||
onopentagname(name) {
|
||||
if (name === 'h1') {
|
||||
isNovelName = true;
|
||||
}
|
||||
if (isH4 && name === 'a'){
|
||||
if (isH4 && name === 'a') {
|
||||
isAuthorName = true;
|
||||
}
|
||||
if(isTags && name === 'a'){
|
||||
if (isTags && name === 'a') {
|
||||
isGenres = true;
|
||||
}
|
||||
if (name === 'label'){
|
||||
if (name === 'label') {
|
||||
isDescription = false;
|
||||
isTags = false;
|
||||
}
|
||||
if (isFooter && name === 'script'){
|
||||
if (isFooter && name === 'script') {
|
||||
isScript = true;
|
||||
}
|
||||
},
|
||||
onattribute(name,value){
|
||||
if (name === 'class' && value === 'description'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'description') {
|
||||
isDescription = true;
|
||||
}
|
||||
if (name === 'class' && value === 'page-footer footer'){
|
||||
if (name === 'class' && value === 'page-footer footer') {
|
||||
isFooter = true;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if (isNovelName){
|
||||
ontext(data) {
|
||||
if (isNovelName) {
|
||||
novel.name = data;
|
||||
}
|
||||
if (isAuthorName){
|
||||
if (isAuthorName) {
|
||||
novel.author = data;
|
||||
isAuthorName = false;
|
||||
}
|
||||
if (isDescription){
|
||||
if (isDescription) {
|
||||
novel.summary += data;
|
||||
}
|
||||
if (isSpan === 2){
|
||||
if (isSpan === 2) {
|
||||
novel.status = data.trim();
|
||||
isSpan++;
|
||||
}
|
||||
if (isGenres){
|
||||
if (isGenres) {
|
||||
genreArray.push(data);
|
||||
}
|
||||
if (isScript){
|
||||
if (data.includes('window.chapters =')){
|
||||
if (isScript) {
|
||||
if (data.includes('window.chapters =')) {
|
||||
chapterJson = JSON.parse(
|
||||
data.match(/window.chapters = (.+])(?=;)/)![1]
|
||||
)
|
||||
data.match(/window.chapters = (.+])(?=;)/)![1],
|
||||
);
|
||||
volumeJson = JSON.parse(
|
||||
data.match(/window.volumes = (.+])(?=;)/)![1]
|
||||
)
|
||||
data.match(/window.volumes = (.+])(?=;)/)![1],
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'h1'){
|
||||
onclosetag(name) {
|
||||
if (name === 'h1') {
|
||||
isNovelName = false;
|
||||
isH4 = true;
|
||||
}
|
||||
if (name === 'h4'){
|
||||
if (name === 'h4') {
|
||||
isH4 = false;
|
||||
}
|
||||
if (name === 'a'){
|
||||
if (name === 'a') {
|
||||
isGenres = false;
|
||||
}
|
||||
if (name === 'script'){
|
||||
if (name === 'script') {
|
||||
isScript = false;
|
||||
}
|
||||
if (name === 'body'){
|
||||
if (name === 'body') {
|
||||
isFooter = false;
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
novel.summary = novel.summary?.trim();
|
||||
novel.genres = genreArray.join(', ');
|
||||
switch(novel.status){
|
||||
switch (novel.status) {
|
||||
case 'ONGOING':
|
||||
novel.status = NovelStatus.Ongoing;
|
||||
break;
|
||||
@@ -224,106 +224,106 @@ class RoyalRoad implements Plugin.PluginBase {
|
||||
let isStyleText = false;
|
||||
let styles = '';
|
||||
const parser = new Parser({
|
||||
onopentag(name,attribs){
|
||||
if (isChapter && name === 'div'){
|
||||
let stylediv = attribs['style']
|
||||
if(stylediv){
|
||||
chapterText += `<div style="${stylediv}">`
|
||||
onopentag(name, attribs) {
|
||||
if (isChapter && name === 'div') {
|
||||
let stylediv = attribs['style'];
|
||||
if (stylediv) {
|
||||
chapterText += `<div style="${stylediv}">`;
|
||||
isStyleText = true;
|
||||
} else {
|
||||
chapterText += `<div>`
|
||||
chapterText += `<div>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
let w = attribs['width'];
|
||||
if(w) {
|
||||
if (w) {
|
||||
chapterText += `<table width="${w}">`;
|
||||
} else {
|
||||
chapterText += `<table>`;
|
||||
}
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `<tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `<tr>`;
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
let w1 = attribs['width'];
|
||||
if(w1) {
|
||||
if (w1) {
|
||||
chapterText += `<td width="${w1}">`;
|
||||
} else {
|
||||
chapterText += `<td>`;
|
||||
}
|
||||
}
|
||||
},
|
||||
onattribute(name, value){
|
||||
if (name === 'class' && value === 'chapter-inner chapter-content'){
|
||||
onattribute(name, value) {
|
||||
if (name === 'class' && value === 'chapter-inner chapter-content') {
|
||||
isChapter = true;
|
||||
}
|
||||
if (name === 'class' && value === 'portlet light t-center-3'){
|
||||
if (name === 'class' && value === 'portlet light t-center-3') {
|
||||
isChapter = false;
|
||||
isPtag = false;
|
||||
}
|
||||
if (name === 'class' && value === styles){
|
||||
if (name === 'class' && value === styles) {
|
||||
isPtag = false;
|
||||
}
|
||||
},
|
||||
onopentagname(name){
|
||||
if (isChapter && name === 'p'){
|
||||
onopentagname(name) {
|
||||
if (isChapter && name === 'p') {
|
||||
chapterText += '<p>';
|
||||
isPtag = true;
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
isStyleText = false;
|
||||
}
|
||||
}
|
||||
if (name === 'style'){
|
||||
if (name === 'style') {
|
||||
isStyle = true;
|
||||
}
|
||||
if (isChapter && name === 'br'){
|
||||
if (isChapter && name === 'br') {
|
||||
chapterText += `<br>`;
|
||||
}
|
||||
},
|
||||
ontext(data){
|
||||
if(isPtag){
|
||||
ontext(data) {
|
||||
if (isPtag) {
|
||||
chapterText += data;
|
||||
}
|
||||
if(isStyleText){
|
||||
if (isStyleText) {
|
||||
chapterText += data;
|
||||
}
|
||||
if (isStyle){
|
||||
if (data.includes('display: none;')){
|
||||
if (isStyle) {
|
||||
if (data.includes('display: none;')) {
|
||||
styles = data.match(/\.(.*)\{/)![1];
|
||||
}
|
||||
}
|
||||
},
|
||||
onclosetag(name){
|
||||
if (name === 'p'){
|
||||
onclosetag(name) {
|
||||
if (name === 'p') {
|
||||
isPtag = false;
|
||||
chapterText += '</p>'
|
||||
chapterText += '</p>';
|
||||
}
|
||||
if (name === 'style'){
|
||||
if (name === 'style') {
|
||||
isStyle = false;
|
||||
}
|
||||
if (isChapter && name === 'td'){
|
||||
if (isChapter && name === 'td') {
|
||||
chapterText += `</td>`;
|
||||
}
|
||||
if (isChapter && name === 'tr'){
|
||||
if (isChapter && name === 'tr') {
|
||||
chapterText += `</tr>`;
|
||||
}
|
||||
if (isChapter && name === 'tbody'){
|
||||
if (isChapter && name === 'tbody') {
|
||||
chapterText += `</tbody>`;
|
||||
}
|
||||
if (isChapter && name === 'table'){
|
||||
if (isChapter && name === 'table') {
|
||||
chapterText += `</table>`;
|
||||
}
|
||||
if (isChapter && name === 'div'){
|
||||
if (isChapter && name === 'div') {
|
||||
isStyleText = false;
|
||||
chapterText += `</div>`
|
||||
chapterText += `</div>`;
|
||||
}
|
||||
}
|
||||
})
|
||||
parser.write(html)
|
||||
},
|
||||
});
|
||||
parser.write(html);
|
||||
parser.end();
|
||||
|
||||
return chapterText;
|
||||
@@ -339,10 +339,6 @@ class RoyalRoad implements Plugin.PluginBase {
|
||||
return this.parseNovels(body);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: 'weekly-popular',
|
||||
|
||||
@@ -185,10 +185,6 @@ class ScribbleHubPlugin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Sort Results By',
|
||||
|
||||
@@ -170,7 +170,6 @@ class WTRLAB implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
filters = {
|
||||
order: {
|
||||
value: 'chapter',
|
||||
|
||||
@@ -285,10 +285,6 @@ class WuxiaWorld implements Plugin.PluginBase {
|
||||
return this.parseNovels(data);
|
||||
}
|
||||
|
||||
fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
proto = `
|
||||
syntax = "proto3";
|
||||
option optimize_for = CODE_SIZE;
|
||||
|
||||
@@ -250,8 +250,6 @@ class ChireadsPlugin implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
tag: {
|
||||
type: FilterTypes.Picker,
|
||||
|
||||
@@ -173,12 +173,6 @@ class HarkenEliwoodPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new HarkenEliwoodPlugin();
|
||||
|
||||
@@ -292,8 +292,6 @@ class NovelDeGlacePlugin implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
categorie_genre: {
|
||||
type: FilterTypes.Picker,
|
||||
|
||||
@@ -202,12 +202,6 @@ class NovhellPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new NovhellPlugin();
|
||||
|
||||
@@ -172,13 +172,6 @@ class PhenixScansTradPlugin implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
const headers = new Headers({
|
||||
'Referer': `${this.site}`,
|
||||
});
|
||||
return await fetchFile(url, { headers });
|
||||
}
|
||||
|
||||
filters = {
|
||||
genre: {
|
||||
type: FilterTypes.CheckboxGroup,
|
||||
|
||||
@@ -193,12 +193,6 @@ class WarriorLegendTradPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new WarriorLegendTradPlugin();
|
||||
|
||||
@@ -211,12 +211,6 @@ class WuxialnscantradPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new WuxialnscantradPlugin();
|
||||
|
||||
@@ -293,12 +293,6 @@ class XiaowazPlugin implements Plugin.PluginBase {
|
||||
|
||||
return await this.getNovelsCovers(novels);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new XiaowazPlugin();
|
||||
|
||||
@@ -131,10 +131,6 @@ class IndoWebNovel implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
status: {
|
||||
value: '',
|
||||
|
||||
@@ -140,10 +140,6 @@ class NovelRingan implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
status: {
|
||||
value: '',
|
||||
|
||||
@@ -159,10 +159,6 @@ class SakuraNovel implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
status: {
|
||||
value: '',
|
||||
|
||||
@@ -217,9 +217,7 @@ class Syosetu implements Plugin.PluginBase {
|
||||
// respond with novels!
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
resolveUrl(path: string, isNovel?: boolean | undefined): string {
|
||||
return this.novelPrefix + path;
|
||||
}
|
||||
|
||||
@@ -155,7 +155,6 @@ class Agitoon implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + (isNovel ? '/novel/list/' : '/novel/view/') + path;
|
||||
}
|
||||
|
||||
@@ -165,11 +165,7 @@ class NovelkiPL implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
// if your plugin has images and they won't load
|
||||
// this is the function to fiddle with
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
genres: {
|
||||
value: '',
|
||||
|
||||
@@ -151,8 +151,6 @@ class freedlit implements Plugin.PluginBase {
|
||||
return dateString || null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Сортировка:',
|
||||
|
||||
@@ -175,7 +175,6 @@ class AuthorToday implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
isNovel ? this.site + '/work/' + path : this.site + '/reader/' + path;
|
||||
|
||||
|
||||
@@ -138,7 +138,6 @@ class Bookriver implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + (isNovel ? '/book/' : '/reader/') + path;
|
||||
|
||||
|
||||
@@ -197,8 +197,6 @@ class ficbook implements Plugin.PluginBase {
|
||||
return dateString || null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Сортировка:',
|
||||
|
||||
@@ -193,8 +193,6 @@ class Jaomix implements Plugin.PluginBase {
|
||||
return dateString || null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
sortby: {
|
||||
label: 'Сортировка:',
|
||||
|
||||
@@ -143,7 +143,6 @@ class Neobook implements Plugin.PluginBase {
|
||||
return chapterText;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + (isNovel ? '/book/' : '/reader/') + path;
|
||||
|
||||
|
||||
@@ -158,7 +158,6 @@ class novelOvh implements Plugin.PluginBase {
|
||||
return html;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + '/novel/' + path;
|
||||
|
||||
|
||||
@@ -195,7 +195,6 @@ class TL implements Plugin.PluginBase {
|
||||
return chapterText;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) => 'https://' + path;
|
||||
|
||||
filters = {
|
||||
|
||||
@@ -164,7 +164,6 @@ class RNBH implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + '/ranobe/' + path;
|
||||
|
||||
|
||||
@@ -216,7 +216,6 @@ class RLIB implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) => {
|
||||
const ui = this.user?.ui ? 'ui=' + this.user.ui : '';
|
||||
|
||||
|
||||
@@ -134,8 +134,6 @@ class RNRF implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
filters = {
|
||||
sort: {
|
||||
label: 'Сортировка',
|
||||
|
||||
@@ -147,7 +147,6 @@ class ReN implements Plugin.PluginBase {
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + '/novel/' + path;
|
||||
|
||||
|
||||
@@ -190,7 +190,6 @@ class Zelluloza implements Plugin.PluginBase {
|
||||
return null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) =>
|
||||
this.site + '/books/' + path;
|
||||
|
||||
|
||||
@@ -136,9 +136,6 @@ class HasulTL implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new HasulTL();
|
||||
|
||||
@@ -176,9 +176,6 @@ class Ligera implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Ligera();
|
||||
|
||||
@@ -199,9 +199,6 @@ class ReinoWuxia implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new ReinoWuxia();
|
||||
|
||||
@@ -161,9 +161,6 @@ class Oasis implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Oasis();
|
||||
|
||||
@@ -128,9 +128,6 @@ class SkyNovels implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new SkyNovels();
|
||||
|
||||
@@ -182,10 +182,6 @@ class TuNovelaLigera implements Plugin.PagePlugin {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: 'rating',
|
||||
|
||||
@@ -179,9 +179,6 @@ class Yuuki implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new Yuuki();
|
||||
|
||||
@@ -159,9 +159,6 @@ class EpikNovel implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new EpikNovel();
|
||||
|
||||
@@ -166,9 +166,6 @@ class LSHNovel implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return await fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
|
||||
@@ -113,8 +113,6 @@ class Smakolykytl implements Plugin.PluginBase {
|
||||
);
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
export default new Smakolykytl();
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { Parser } from 'htmlparser2';
|
||||
import { fetchFile } from '@libs/fetch';
|
||||
import { HTMLParser2Util, Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
import { FilterTypes, Filters } from '@libs/filterInputs';
|
||||
@@ -395,6 +394,8 @@ class HakoPlugin implements Plugin.PluginBase {
|
||||
novel.status = NovelStatus.Unknown;
|
||||
}
|
||||
novel.genres = novel.genres?.replace(/,*\s*$/, '');
|
||||
novel.name = novel.name.trim();
|
||||
novel.summary = novel.summary?.trim();
|
||||
return novel;
|
||||
});
|
||||
}
|
||||
@@ -416,12 +417,11 @@ class HakoPlugin implements Plugin.PluginBase {
|
||||
this.site + '/tim-kiem?keywords=' + searchTerm + '&page=' + pageNo;
|
||||
return this.parseNovels(url);
|
||||
}
|
||||
fetchImage(url: string): Promise<string | undefined> {
|
||||
const headers = {
|
||||
imageRequestInit: Plugin.ImageRequestInit = {
|
||||
headers: {
|
||||
Referer: 'https://ln.hako.vn',
|
||||
};
|
||||
return fetchFile(url, { headers: headers });
|
||||
}
|
||||
},
|
||||
};
|
||||
filters = {
|
||||
alphabet: {
|
||||
type: FilterTypes.Picker,
|
||||
|
||||
@@ -247,9 +247,7 @@ class TruyenConect implements Plugin.PagePlugin {
|
||||
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
|
||||
filters = {
|
||||
category: {
|
||||
label: 'Lọc theo',
|
||||
|
||||
@@ -170,9 +170,6 @@ class LightNovelVN implements Plugin.PagePlugin {
|
||||
}) || [];
|
||||
return novels;
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new LightNovelVN();
|
||||
|
||||
@@ -119,8 +119,5 @@ class Nettruyen implements Plugin.PagePlugin {
|
||||
): Promise<Plugin.NovelItem[]> {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
export default new Nettruyen();
|
||||
|
||||
@@ -151,9 +151,6 @@ class TruyenFull implements Plugin.PagePlugin {
|
||||
const loadedCheerio = parseHTML(body);
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TruyenFull();
|
||||
|
||||
@@ -142,9 +142,6 @@ class TruyenFull implements Plugin.PagePlugin {
|
||||
const loadedCheerio = parseHTML(body);
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url);
|
||||
}
|
||||
}
|
||||
|
||||
export default new TruyenFull();
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchFile, fetchApi } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
@@ -162,8 +162,6 @@ class HotNovelPubPlugin implements Plugin.PluginBase {
|
||||
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
resolveUrl = (path: string, isNovel?: boolean) => this.site + '/' + path;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchFile, fetchApi } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
@@ -216,6 +216,4 @@ class IfreedomPlugin implements Plugin.PluginBase {
|
||||
}
|
||||
return dateString || null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { load as parseHTML } from 'cheerio';
|
||||
import { fetchApi, fetchFile } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import dayjs from 'dayjs';
|
||||
@@ -27,6 +27,9 @@ class LightNovelWorld implements Plugin.PagePlugin {
|
||||
Accept: 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = {
|
||||
headers: this.headers,
|
||||
};
|
||||
options?: LightNovelWorldOptions;
|
||||
|
||||
constructor(metadata: LightNovelWorldMetadata) {
|
||||
@@ -188,10 +191,6 @@ class LightNovelWorld implements Plugin.PagePlugin {
|
||||
return novels;
|
||||
}
|
||||
|
||||
async fetchImage(url: string): Promise<string | undefined> {
|
||||
return fetchFile(url, { headers: this.headers });
|
||||
}
|
||||
|
||||
filters = {
|
||||
order: {
|
||||
value: 'popular',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { load } from 'cheerio';
|
||||
import { Parser } from 'htmlparser2';
|
||||
import { fetchApi, fetchFile } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
import { defaultCover } from '@libs/defaultCover';
|
||||
@@ -407,8 +407,6 @@ class LightNovelWPPlugin implements Plugin.PluginBase {
|
||||
const html = await this.safeFecth(url, true);
|
||||
return this.parseNovels(html);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
function extractChapterNumber(data: string, tempChapter: Plugin.ChapterItem) {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchApi, fetchFile } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { Cheerio, AnyNode, CheerioAPI, load as parseHTML } from 'cheerio';
|
||||
@@ -294,8 +294,6 @@ class MadaraPlugin implements Plugin.PluginBase {
|
||||
return this.parseNovels(loadedCheerio);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
|
||||
parseData = (date: string) => {
|
||||
const dayJSDate = dayjs(); // today
|
||||
const timeAgo = date.match(/\d+/)?.[0] || '';
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { CheerioAPI, load } from 'cheerio';
|
||||
import { fetchApi, fetchFile } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
|
||||
@@ -172,6 +172,4 @@ class ReadNovelFullPlugin implements Plugin.PluginBase {
|
||||
|
||||
return this.parseNovels($);
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchFile, fetchApi } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
@@ -223,6 +223,4 @@ class ReadwnPlugin implements Plugin.PluginBase {
|
||||
.filter(novel => novel.name && novel.path);
|
||||
return novels;
|
||||
}
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { fetchFile, fetchApi } from '@libs/fetch';
|
||||
import { fetchApi } from '@libs/fetch';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { NovelStatus } from '@libs/novelStatus';
|
||||
@@ -246,8 +246,6 @@ class RulatePlugin implements Plugin.PluginBase {
|
||||
}
|
||||
return dateString || null;
|
||||
};
|
||||
|
||||
fetchImage = fetchFile;
|
||||
}
|
||||
|
||||
interface response {
|
||||
|
||||
@@ -4,6 +4,7 @@ import path from 'path';
|
||||
import { PluginList } from '@typings/types';
|
||||
import { Plugin } from '@typings/plugin';
|
||||
import { Filters } from '@libs/filterInputs';
|
||||
import { fetchFile } from '@libs/fetch';
|
||||
const root = path.dirname(require?.main?.filename || '');
|
||||
|
||||
export const fetchHeaders: Record<string, string> = {};
|
||||
@@ -83,8 +84,14 @@ export const parseChapter = async (
|
||||
chapterPath: string,
|
||||
) => (await getPlugin(pluginRequirePath))?.parseChapter(chapterPath);
|
||||
|
||||
export const fetchImage = async (pluginRequirePath: string, url: string) =>
|
||||
(await getPlugin(pluginRequirePath))?.fetchImage(url);
|
||||
export const fetchImage = async (pluginRequirePath: string, url: string) => {
|
||||
const plugin = await getPlugin(pluginRequirePath);
|
||||
return fetchFile(url, {
|
||||
method: plugin?.imageRequestInit?.method,
|
||||
headers: plugin?.imageRequestInit?.headers,
|
||||
body: plugin?.imageRequestInit?.body,
|
||||
});
|
||||
};
|
||||
|
||||
export const resolveUrl = async (
|
||||
pluginRequirePath: string,
|
||||
|
||||
+6
-1
@@ -53,6 +53,11 @@ export namespace Plugin {
|
||||
requirePath: string;
|
||||
icon: string;
|
||||
}
|
||||
export interface ImageRequestInit {
|
||||
method?: string;
|
||||
headers?: Record<string, string>;
|
||||
body?: string;
|
||||
}
|
||||
|
||||
export interface PluginBase {
|
||||
id: string;
|
||||
@@ -65,6 +70,7 @@ export namespace Plugin {
|
||||
*/
|
||||
icon: string;
|
||||
site: string;
|
||||
imageRequestInit?: ImageRequestInit;
|
||||
filters?: Filters;
|
||||
version: string;
|
||||
//flag indicates whether access to LocalStorage, SesesionStorage is required.
|
||||
@@ -93,7 +99,6 @@ export namespace Plugin {
|
||||
* return await fetchFile(url, { headers: headers });
|
||||
* ```
|
||||
*/
|
||||
fetchImage(url: string): Promise<string | undefined>;
|
||||
resolveUrl?(path: string, isNovel?: boolean): string;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user