diff --git a/src/plugins/english/mvlempyr.ts b/src/plugins/english/mvlempyr.ts
index 74447a5..0a84b27 100644
--- a/src/plugins/english/mvlempyr.ts
+++ b/src/plugins/english/mvlempyr.ts
@@ -2,13 +2,34 @@ import { CheerioAPI, load as parseHTML } from 'cheerio';
import { fetchApi } from '@libs/fetch';
import { Plugin } from '@typings/plugin';
import { Filters, FilterTypes } from '@libs/filterInputs';
+import { Parser } from 'htmlparser2';
+
+//has to be here cus this scoping moment
+const parserData: {
+ inTag?: string;
+ depthRatingWrapper?: number;
+ depth: number;
+ ret?: {
+ path: string;
+ cover: string;
+ name?: string;
+ avgReview?: string;
+ reviewCount?: string;
+ chapterCount?: string;
+ updated?: string;
+ created?: string;
+ genres?: string;
+ tags?: string;
+ };
+ parser?: Parser;
+} = { depth: 0 };
class MVLEMPYRPlugin implements Plugin.PluginBase {
id = 'mvlempyr.com';
name = 'MVLEMPYR';
icon = 'src/en/mvlempyr/icon.png';
site = 'https://www.mvlempyr.com/';
- version = '1.0.1';
+ version = '1.0.2';
_chapSite = 'https://chp.mvlempyr.net/';
_allNovels: (Plugin.NovelItem & ExtraNovelData)[] | undefined;
@@ -47,7 +68,7 @@ class MVLEMPYRPlugin implements Plugin.PluginBase {
parseNovelsFast(body: string) {
const novelInfosStart = body.split('
');
- novelInfosStart.shift(); //remove first element that doesent have a novel
+ novelInfosStart.shift(); //remove first element that doesn't have a novel
const ret = [];
for (const novelInfo of novelInfosStart) {
@@ -62,6 +83,134 @@ class MVLEMPYRPlugin implements Plugin.PluginBase {
return ret;
}
+ /**
+ * Equivalent to parseNovelsFast except uses htmlparser2 instead of cheerio for even more fast-fast
+ */
+ parseNovelsFastNew(body: string) {
+ const novelInfosStart = body.split('
');
+ novelInfosStart.shift(); //remove first element that doesn't have a novel
+
+ const ret = [];
+ for (const novelInfo of novelInfosStart) {
+ const realNovelInfo =
+ novelInfo.split('READ
')[0] +
+ 'READ';
+
+ ret.push(this.parseNovelHtmlNew(realNovelInfo));
+ }
+
+ console.log(ret);
+ return ret;
+ }
+
+ parseNovelHtmlNew(el: string): Plugin.NovelItem & ExtraNovelData {
+ parserData.ret = {
+ name: '',
+ path: '',
+ cover: '',
+ avgReview: '',
+ reviewCount: '',
+ chapterCount: '',
+ updated: '',
+ created: '',
+ genres: '',
+ tags: '',
+ };
+ parserData.inTag = '';
+ parserData.depth = 0;
+ parserData.depthRatingWrapper = 0;
+ if (!parserData.parser) {
+ parserData.parser = new Parser({
+ onopentag(
+ name: string,
+ attribs: Record,
+ isImplied: boolean,
+ ) {
+ if (parserData.depthRatingWrapper) parserData.depthRatingWrapper++;
+ if (parserData.inTag) {
+ parserData.depth++;
+ return;
+ }
+
+ if (attribs['class']?.includes?.('ratingwrapper'))
+ parserData.depthRatingWrapper = 1;
+
+ if (name === 'h2' && attribs['fs-cmsfilter-field'] === 'name')
+ parserData.inTag = 'name';
+ if (name === 'a' && !parserData.ret!.path)
+ parserData.ret!.path = attribs['href'].replace(/^\//, '');
+ if (name === 'img' && !parserData.ret!.cover)
+ parserData.ret!.cover = attribs['src'];
+ if (
+ name === 'div' &&
+ attribs['fs-cmssort-field'] === 'avgr' &&
+ parserData.depthRatingWrapper
+ )
+ parserData.inTag = 'avgReview';
+ if (
+ name === 'div' &&
+ attribs['fs-cmssort-field'] === 'reviews' &&
+ parserData.depthRatingWrapper
+ )
+ parserData.inTag = 'reviewCount';
+ if (
+ name === 'div' &&
+ attribs['fs-cmssort-field'] === 'chapter' &&
+ attribs['class']?.includes?.('chapter-count')
+ )
+ parserData.inTag = 'chapterCount';
+ if (name === 'div' && attribs['fs-cmssort-field'] === 'update')
+ parserData.inTag = 'updated';
+ if (name === 'div' && attribs['fs-cmssort-field'] === 'crdate')
+ parserData.inTag = 'created';
+ if (name === 'div' && attribs['fs-cmsnest-collection'] === 'genre')
+ parserData.inTag = 'genres';
+ if (name === 'div' && attribs['fs-cmsnest-collection'] === 'tags')
+ parserData.inTag = 'tags';
+
+ if (parserData.inTag) {
+ parserData.depth++;
+ }
+ },
+ ontext(data: string) {
+ if (!parserData.inTag) return;
+
+ // @ts-ignore
+ parserData.ret[parserData.inTag] =
+ (parserData.ret[parserData.inTag] || '') + data;
+ },
+ onclosetag(name: string, isImplied: boolean) {
+ if (parserData.depthRatingWrapper) parserData.depthRatingWrapper--;
+ if (!parserData.inTag) return;
+ parserData.depth--;
+ if (!parserData.depth) parserData.inTag = '';
+ },
+ });
+ }
+
+ parserData.parser.reset();
+ parserData.parser.write(el);
+ parserData.parser.end();
+
+ // @ts-ignore
+ parserData.ret.avgReview = parseFloat(parserData.ret.avgReview);
+ // @ts-ignore
+ parserData.ret.reviewCount = parseFloat(parserData.ret.reviewCount);
+ // @ts-ignore
+ parserData.ret.chapterCount = parseFloat(parserData.ret.chapterCount);
+ // @ts-ignore
+ parserData.ret.updated = new Date(parserData.ret.updated).getTime();
+ // @ts-ignore
+ parserData.ret.created = new Date(parserData.ret.created).getTime();
+ // @ts-ignore
+ parserData.ret.genres = parserData.ret.genres.split(', ');
+ // @ts-ignore
+ parserData.ret.tags = parserData.ret.tags.split(', ');
+
+ // @ts-ignore
+ return parserData.ret;
+ }
+
parseNovelHtml(el: CheerioAPI) {
return {
name: el('h2[fs-cmsfilter-field="name"]').text(),
@@ -138,7 +287,7 @@ class MVLEMPYRPlugin implements Plugin.PluginBase {
});
const body = await result.text();
if (!nextPageConsumer) {
- return this.parseNovelsFast(body);
+ return this.parseNovelsFastNew(body);
}
const loadedCheerio = parseHTML(body);
@@ -247,8 +396,11 @@ class MVLEMPYRPlugin implements Plugin.PluginBase {
return this._allNovels;
}
this._allNovelsPromise = this.loadAll();
- this._allNovels = await this._allNovelsPromise;
- this._allNovelsPromise = undefined;
+ try {
+ this._allNovels = await this._allNovelsPromise;
+ } finally {
+ this._allNovelsPromise = undefined;
+ }
return this._allNovels;
}