fix: Broken Chapter Scraper Due to Layout Change (Fenrir) (#1884)
* fenrir: Fix broken chapter scrapper due to layout change Also remove comment nodes to reduce chapter size. Signed-off-by: Martian Potato <2260cse01024@manarat.ac.bd> * fenrir: Add type annotations Signed-off-by: Martian Potato <2260cse01024@manarat.ac.bd> --------- Signed-off-by: Martian Potato <2260cse01024@manarat.ac.bd>
This commit is contained in:
committed by
GitHub
parent
78d7a86f42
commit
0e92630eea
@@ -1,16 +1,44 @@
|
|||||||
import { fetchApi } from '@libs/fetch';
|
import { fetchApi } from '@libs/fetch';
|
||||||
import { Plugin } from '@/types/plugin';
|
import { Plugin } from '@/types/plugin';
|
||||||
|
import { Node } from 'domhandler';
|
||||||
import { load as loadCheerio } from 'cheerio';
|
import { load as loadCheerio } from 'cheerio';
|
||||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||||
import { storage } from '@libs/storage';
|
import { storage } from '@libs/storage';
|
||||||
import { defaultCover } from '@libs/defaultCover';
|
import { defaultCover } from '@libs/defaultCover';
|
||||||
|
|
||||||
|
type APINovel = {
|
||||||
|
title: string;
|
||||||
|
slug: string;
|
||||||
|
cover: string;
|
||||||
|
description: string;
|
||||||
|
status: string;
|
||||||
|
genres: { name: string }[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type APIChapter = {
|
||||||
|
locked: { price: number } | null;
|
||||||
|
group: null | {
|
||||||
|
index: number;
|
||||||
|
slug: string;
|
||||||
|
};
|
||||||
|
title: string;
|
||||||
|
number: number;
|
||||||
|
created_at: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
type ChapterInfo = {
|
||||||
|
name: string;
|
||||||
|
path: string;
|
||||||
|
releaseTime: string;
|
||||||
|
chapterNumber: number;
|
||||||
|
};
|
||||||
|
|
||||||
class FenrirRealmPlugin implements Plugin.PluginBase {
|
class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||||
id = 'fenrir';
|
id = 'fenrir';
|
||||||
name = 'Fenrir Realm';
|
name = 'Fenrir Realm';
|
||||||
icon = 'src/en/fenrirrealm/icon.png';
|
icon = 'src/en/fenrirrealm/icon.png';
|
||||||
site = 'https://fenrirealm.com';
|
site = 'https://fenrirealm.com';
|
||||||
version = '1.0.11';
|
version = '1.0.12';
|
||||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
||||||
|
|
||||||
hideLocked = storage.get('hideLocked');
|
hideLocked = storage.get('hideLocked');
|
||||||
@@ -48,7 +76,7 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
return res.data.map(r => this.parseNovelFromApi(r));
|
return res.data.map((r: APINovel) => this.parseNovelFromApi(r));
|
||||||
}
|
}
|
||||||
|
|
||||||
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
async parseNovel(novelPath: string): Promise<Plugin.SourceNovel> {
|
||||||
@@ -88,14 +116,14 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
).then(r => r.json());
|
).then(r => r.json());
|
||||||
|
|
||||||
if (this.hideLocked) {
|
if (this.hideLocked) {
|
||||||
chapters = chapters.filter(c => !c.locked?.price);
|
chapters = chapters.filter((c: APIChapter) => !c.locked?.price);
|
||||||
}
|
}
|
||||||
|
|
||||||
novel.chapters = chapters
|
novel.chapters = chapters
|
||||||
.map(c => ({
|
.map((c: APIChapter) => ({
|
||||||
name:
|
name:
|
||||||
(c.locked?.price ? '🔒 ' : '') +
|
(c.locked?.price ? '🔒 ' : '') +
|
||||||
(c.group?.index === null ? '' : 'Vol ' + c.group.index + ' ') +
|
(c.group?.index === null ? '' : 'Vol ' + c.group?.index + ' ') +
|
||||||
'Chapter ' +
|
'Chapter ' +
|
||||||
c.number +
|
c.number +
|
||||||
(c.title && c.title.trim() != 'Chapter ' + c.number
|
(c.title && c.title.trim() != 'Chapter ' + c.number
|
||||||
@@ -103,13 +131,15 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
: ''),
|
: ''),
|
||||||
path:
|
path:
|
||||||
novelPath +
|
novelPath +
|
||||||
(c.group?.index === null ? '' : '/' + c.group.slug) +
|
(c.group?.index === null ? '' : '/' + c.group?.slug) +
|
||||||
'/chapter-' +
|
'/chapter-' +
|
||||||
c.number,
|
c.number,
|
||||||
releaseTime: c.created_at,
|
releaseTime: c.created_at,
|
||||||
chapterNumber: c.number + c.group?.index * 1000000000000,
|
chapterNumber: c.number + (c.group?.index || 0) * 1000000000000,
|
||||||
}))
|
}))
|
||||||
.sort((a, b) => a.chapterNumber - b.chapterNumber);
|
.sort(
|
||||||
|
(a: ChapterInfo, b: ChapterInfo) => a.chapterNumber - b.chapterNumber,
|
||||||
|
);
|
||||||
return novel;
|
return novel;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,7 +147,15 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
const page = await fetchApi(this.site + '/series/' + chapterPath, {}).then(
|
const page = await fetchApi(this.site + '/series/' + chapterPath, {}).then(
|
||||||
r => r.text(),
|
r => r.text(),
|
||||||
);
|
);
|
||||||
return loadCheerio(page)('#reader-area').html() || '';
|
const chapter = loadCheerio(page)('[id^="reader-area-"]');
|
||||||
|
chapter
|
||||||
|
.contents()
|
||||||
|
.filter((_, node: Node) => {
|
||||||
|
return node.type === 'comment';
|
||||||
|
})
|
||||||
|
.remove();
|
||||||
|
|
||||||
|
return chapter.html() || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
async searchNovels(
|
async searchNovels(
|
||||||
@@ -128,10 +166,12 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
`${this.site}/api/series/filter?page=${pageNo}&per_page=20&search=${encodeURIComponent(searchTerm)}`,
|
`${this.site}/api/series/filter?page=${pageNo}&per_page=20&search=${encodeURIComponent(searchTerm)}`,
|
||||||
)
|
)
|
||||||
.then(r => r.json())
|
.then(r => r.json())
|
||||||
.then(r => r.data.map(novel => this.parseNovelFromApi(novel)));
|
.then(r =>
|
||||||
|
r.data.map((novel: APINovel) => this.parseNovelFromApi(novel)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
parseNovelFromApi(apiData) {
|
parseNovelFromApi(apiData: APINovel) {
|
||||||
return {
|
return {
|
||||||
name: apiData.title,
|
name: apiData.title,
|
||||||
path: apiData.slug,
|
path: apiData.slug,
|
||||||
@@ -249,11 +289,19 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
|||||||
|
|
||||||
export default new FenrirRealmPlugin();
|
export default new FenrirRealmPlugin();
|
||||||
|
|
||||||
|
type GenreData = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
||||||
//paste into console on site to load
|
//paste into console on site to load
|
||||||
async function getUpdatedGenres() {
|
async function getUpdatedGenres() {
|
||||||
const data = await fetch(
|
const data = await fetch(
|
||||||
'https://fenrirealm.com/api/novels/taxonomy/genres',
|
'https://fenrirealm.com/api/novels/taxonomy/genres',
|
||||||
).then(d => d.json());
|
).then(d => d.json());
|
||||||
const genreData = data.map(g => ({ label: g.name, value: g.id.toString() }));
|
const genreData = data.map((g: GenreData) => ({
|
||||||
|
label: g.name,
|
||||||
|
value: g.id.toString(),
|
||||||
|
}));
|
||||||
console.log(JSON.stringify(genreData));
|
console.log(JSON.stringify(genreData));
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user