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 { Plugin } from '@/types/plugin';
|
||||
import { Node } from 'domhandler';
|
||||
import { load as loadCheerio } from 'cheerio';
|
||||
import { Filters, FilterTypes } from '@libs/filterInputs';
|
||||
import { storage } from '@libs/storage';
|
||||
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 {
|
||||
id = 'fenrir';
|
||||
name = 'Fenrir Realm';
|
||||
icon = 'src/en/fenrirrealm/icon.png';
|
||||
site = 'https://fenrirealm.com';
|
||||
version = '1.0.11';
|
||||
version = '1.0.12';
|
||||
imageRequestInit?: Plugin.ImageRequestInit | undefined = undefined;
|
||||
|
||||
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> {
|
||||
@@ -88,14 +116,14 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||
).then(r => r.json());
|
||||
|
||||
if (this.hideLocked) {
|
||||
chapters = chapters.filter(c => !c.locked?.price);
|
||||
chapters = chapters.filter((c: APIChapter) => !c.locked?.price);
|
||||
}
|
||||
|
||||
novel.chapters = chapters
|
||||
.map(c => ({
|
||||
.map((c: APIChapter) => ({
|
||||
name:
|
||||
(c.locked?.price ? '🔒 ' : '') +
|
||||
(c.group?.index === null ? '' : 'Vol ' + c.group.index + ' ') +
|
||||
(c.group?.index === null ? '' : 'Vol ' + c.group?.index + ' ') +
|
||||
'Chapter ' +
|
||||
c.number +
|
||||
(c.title && c.title.trim() != 'Chapter ' + c.number
|
||||
@@ -103,13 +131,15 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||
: ''),
|
||||
path:
|
||||
novelPath +
|
||||
(c.group?.index === null ? '' : '/' + c.group.slug) +
|
||||
(c.group?.index === null ? '' : '/' + c.group?.slug) +
|
||||
'/chapter-' +
|
||||
c.number,
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -117,7 +147,15 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||
const page = await fetchApi(this.site + '/series/' + chapterPath, {}).then(
|
||||
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(
|
||||
@@ -128,10 +166,12 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||
`${this.site}/api/series/filter?page=${pageNo}&per_page=20&search=${encodeURIComponent(searchTerm)}`,
|
||||
)
|
||||
.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 {
|
||||
name: apiData.title,
|
||||
path: apiData.slug,
|
||||
@@ -249,11 +289,19 @@ class FenrirRealmPlugin implements Plugin.PluginBase {
|
||||
|
||||
export default new FenrirRealmPlugin();
|
||||
|
||||
type GenreData = {
|
||||
name: string;
|
||||
id: number;
|
||||
};
|
||||
|
||||
//paste into console on site to load
|
||||
async function getUpdatedGenres() {
|
||||
const data = await fetch(
|
||||
'https://fenrirealm.com/api/novels/taxonomy/genres',
|
||||
).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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user