From 036da02b9a7ceca3356cc2bb883ec1b78fcc7394 Mon Sep 17 00:00:00 2001 From: 7ui77 <99854073+7ui77@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:42:55 +0000 Subject: [PATCH 1/4] perf(madara): optimize chapter pagination, DOM queries and template generation --- plugins/multisrc/madara/generator.js | 7 +- plugins/multisrc/madara/template.ts | 132 ++++++++++++++++----------- 2 files changed, 84 insertions(+), 55 deletions(-) diff --git a/plugins/multisrc/madara/generator.js b/plugins/multisrc/madara/generator.js index cb3fa09c7..e5dbcb212 100644 --- a/plugins/multisrc/madara/generator.js +++ b/plugins/multisrc/madara/generator.js @@ -21,10 +21,11 @@ export const generateAll = function () { }); }; +const madaraTemplate = readFileSync(join(folder, 'template.ts'), { + encoding: 'utf-8', +}); + const generator = function generator(source) { - const madaraTemplate = readFileSync(join(folder, 'template.ts'), { - encoding: 'utf-8', - }); const pluginScript = ` ${madaraTemplate.replace('// CustomJS HERE', source.options?.customJs || '')} diff --git a/plugins/multisrc/madara/template.ts b/plugins/multisrc/madara/template.ts index 466c8c9be..e0bfde4da 100644 --- a/plugins/multisrc/madara/template.ts +++ b/plugins/multisrc/madara/template.ts @@ -167,17 +167,12 @@ export class MadaraPlugin implements Plugin.PluginBase { loadedCheerio('.page-item-detail, .c-tabs-item__content').each( (index, element) => { - const novelName = loadedCheerio(element) - .find('.post-title') - .text() - .trim(); - const novelUrl = - loadedCheerio(element).find('.post-title').find('a').attr('href') || - ''; + const item = loadedCheerio(element); + const postTitle = item.find('.post-title'); + const novelName = postTitle.text().trim(); + const novelUrl = postTitle.find('a').attr('href') || ''; if (!novelName || !novelUrl) return; - const novelCover = this.extractCover( - loadedCheerio(element).find('img'), - ); + const novelCover = this.extractCover(item.find('img')); const novel: Plugin.NovelItem = { name: novelName, @@ -280,9 +275,9 @@ export class MadaraPlugin implements Plugin.PluginBase { loadedCheerio('.post-content_item, .post-content').each(function () { const detailName = loadedCheerio(this).find('h5').text().trim(); - const detail = - loadedCheerio(this).find('.summary-content') || - loadedCheerio(this).find('.summary_content'); + const detail = loadedCheerio(this).find( + '.summary-content, .summary_content', + ); switch (detailName) { case 'Genre(s)': @@ -412,16 +407,34 @@ export class MadaraPlugin implements Plugin.PluginBase { const queryIndex = lastHref.indexOf('?'); if (queryIndex !== -1) { const queryTemplate = lastHref.slice(queryIndex).replace(/\d+$/, ''); + const pages: number[] = []; for (let page = 2; page <= maxPage; page++) { - const pageHtml = await fetchApi( - this.site + novelPath + 'ajax/chapters/' + queryTemplate + page, - { - method: 'POST', - headers: this.requestHeaders, - referrer: this.site + novelPath, - }, - ).then((res: Response) => res.text()); - if (pageHtml && pageHtml !== '0') html += pageHtml; + pages.push(page); + } + const BATCH_SIZE = 5; + for (let i = 0; i < pages.length; i += BATCH_SIZE) { + const batch = pages.slice(i, i + BATCH_SIZE); + const batchHtmls = await Promise.all( + batch.map(page => + fetchApi( + this.site + + novelPath + + 'ajax/chapters/' + + queryTemplate + + page, + { + method: 'POST', + headers: this.requestHeaders, + referrer: this.site + novelPath, + }, + ) + .then((res: Response) => res.text()) + .catch(() => ''), + ), + ); + for (const pageHtml of batchHtmls) { + if (pageHtml && pageHtml !== '0') html += pageHtml; + } } } } @@ -447,25 +460,25 @@ export class MadaraPlugin implements Plugin.PluginBase { } const totalChapters = loadedCheerio('.wp-manga-chapter').length; + const defaultDate = dayjs().format('LL'); loadedCheerio('.wp-manga-chapter').each((chapterIndex, element) => { - let chapterName = loadedCheerio(element).find('a').text().trim(); + const link = loadedCheerio(element).find('a'); + let chapterName = link.text().trim(); const locked = element.attribs['class'].includes('premium-block'); if (locked) { chapterName = '🔒 ' + chapterName; } - let releaseDate = loadedCheerio(element) + const rawReleaseDate = loadedCheerio(element) .find('span.chapter-release-date') .text() .trim(); - if (releaseDate) { - releaseDate = this.parseData(releaseDate); - } else { - releaseDate = dayjs().format('LL'); - } + const releaseDate = rawReleaseDate + ? this.parseData(rawReleaseDate) + : defaultDate; - const chapterUrl = loadedCheerio(element).find('a').attr('href') || ''; + const chapterUrl = link.attr('href') || ''; if (chapterUrl && chapterUrl != '#' && !(locked && this.hideLocked)) { chapters.push({ @@ -483,11 +496,25 @@ export class MadaraPlugin implements Plugin.PluginBase { async parseChapter(chapterPath: string): Promise { const loadedCheerio = await this.getCheerio(this.site + chapterPath, false); - const chapterText = - loadedCheerio('.text-left') || - loadedCheerio('.text-right') || - loadedCheerio('.entry-content') || - loadedCheerio('.c-blog-post > div > div:nth-child(2)'); + const candidates = [ + '.text-left', + '.text-right', + '.entry-content', + '.c-blog-post > div > div:nth-child(2)', + '.reading-content', + ]; + let chapterText: Cheerio = loadedCheerio('.entry-content'); + for (const selector of candidates) { + const el = loadedCheerio(selector); + if (el.length > 0) { + chapterText = el; + break; + } + } + + chapterText + .find('script, style, noscript, .code-block, .adsbygoogle') + .remove(); if (this.options?.customJs) { try { @@ -518,14 +545,17 @@ export class MadaraPlugin implements Plugin.PluginBase { } parseData = (date: string) => { - let dayJSDate = dayjs(); // today - const timeAgo = date.match(/\d+/)?.[0] || ''; - const timeAgoInt = parseInt(timeAgo, 10); + const timeAgo = date.match(/\d+/)?.[0]; + if (!timeAgo) { + const formatted = dayjs(date).format('LL'); + return formatted !== 'Invalid Date' ? formatted : date; + } - if (!timeAgo) return date; // there is no number! + const timeAgoInt = parseInt(timeAgo, 10); + let dayJSDate = dayjs(); if (includesAny(date, ['detik', 'segundo', 'second', 'วินาที'])) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'second'); // go back N seconds + dayJSDate = dayJSDate.subtract(timeAgoInt, 'second'); } else if ( includesAny(date, [ 'menit', @@ -537,7 +567,7 @@ export class MadaraPlugin implements Plugin.PluginBase { 'دقائق', ]) ) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'minute'); // go back N minute + dayJSDate = dayJSDate.subtract(timeAgoInt, 'minute'); } else if ( includesAny(date, [ 'jam', @@ -552,34 +582,32 @@ export class MadaraPlugin implements Plugin.PluginBase { '小时', ]) ) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'hours'); // go back N hours + dayJSDate = dayJSDate.subtract(timeAgoInt, 'hours'); } else if ( includesAny(date, [ 'hari', 'gün', 'jour', - 'día', + 'ngày', 'dia', + 'día', 'day', 'วัน', - 'ngày', 'giorni', 'أيام', '天', ]) ) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'days'); // go back N days + dayJSDate = dayJSDate.subtract(timeAgoInt, 'days'); } else if (includesAny(date, ['week', 'semana'])) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'week'); // go back N a week + dayJSDate = dayJSDate.subtract(timeAgoInt, 'week'); } else if (includesAny(date, ['month', 'mes'])) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'month'); // go back N months + dayJSDate = dayJSDate.subtract(timeAgoInt, 'month'); } else if (includesAny(date, ['year', 'año'])) { - dayJSDate = dayJSDate.subtract(timeAgoInt, 'year'); // go back N years + dayJSDate = dayJSDate.subtract(timeAgoInt, 'year'); } else { - if (dayjs(date).format('LL') !== 'Invalid Date') { - return dayjs(date).format('LL'); - } - return date; + const formatted = dayjs(date).format('LL'); + return formatted !== 'Invalid Date' ? formatted : date; } return dayJSDate.format('LL'); From dfefae0c176ed11145f3d1ed94690e320861ae1c Mon Sep 17 00:00:00 2001 From: 7ui77 <99854073+7ui77@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:47:20 +0000 Subject: [PATCH 2/4] chore(madara): bump base version to 2.3.0 --- plugins/multisrc/madara/template.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/multisrc/madara/template.ts b/plugins/multisrc/madara/template.ts index e0bfde4da..f369af8ad 100644 --- a/plugins/multisrc/madara/template.ts +++ b/plugins/multisrc/madara/template.ts @@ -48,7 +48,7 @@ export class MadaraPlugin implements Plugin.PluginBase { this.icon = `multisrc/madara/${metadata.id.toLowerCase()}/icon.png`; this.site = metadata.sourceSite; const versionIncrements = metadata.options?.versionIncrements || 0; - this.version = `2.2.${versionIncrements}`; + this.version = `2.3.${versionIncrements}`; this.options = metadata.options; this.filters = metadata.filters; From bda1ea545c22fff2f733c7228a54db933863bd82 Mon Sep 17 00:00:00 2001 From: 7ui77 <99854073+7ui77@users.noreply.github.com> Date: Mon, 12 Oct 2026 01:55:54 +0000 Subject: [PATCH 3/4] chore(madara): remove versionIncrements from sources.json --- plugins/multisrc/madara/sources.json | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/plugins/multisrc/madara/sources.json b/plugins/multisrc/madara/sources.json index 6e7b38526..c4f7a3602 100644 --- a/plugins/multisrc/madara/sources.json +++ b/plugins/multisrc/madara/sources.json @@ -222,8 +222,7 @@ "sourceName": "Foxaholic", "options": { "useNewChapterEndpoint": true, - "resolveCoverDataUri": true, - "versionIncrements": 1 + "resolveCoverDataUri": true } }, { @@ -414,8 +413,7 @@ "sourceName": "Belle Repository", "options": { "useNewChapterEndpoint": true, - "lang": "English", - "versionIncrements": 1 + "lang": "English" } }, { @@ -632,8 +630,7 @@ "sourceName": "BoxNovel", "options": { "lang": "English", - "useNewChapterEndpoint": true, - "versionIncrements": 2 + "useNewChapterEndpoint": true } }, { @@ -660,8 +657,7 @@ "sourceName": "Lovelyblossoms", "options": { "useNewChapterEndpoint": true, - "browserHeaders": true, - "versionIncrements": 1 + "browserHeaders": true } }, { From fb81516f3f654b524ac4904ab88306705239203c Mon Sep 17 00:00:00 2001 From: 7ui77 <99854073+7ui77@users.noreply.github.com> Date: Mon, 12 Oct 2026 03:52:14 +0000 Subject: [PATCH 4/4] fix(madara): propagate chapter page fetch errors instead of silently swallowing --- plugins/multisrc/madara/template.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/plugins/multisrc/madara/template.ts b/plugins/multisrc/madara/template.ts index f369af8ad..0a070e921 100644 --- a/plugins/multisrc/madara/template.ts +++ b/plugins/multisrc/madara/template.ts @@ -427,9 +427,7 @@ export class MadaraPlugin implements Plugin.PluginBase { headers: this.requestHeaders, referrer: this.site + novelPath, }, - ) - .then((res: Response) => res.text()) - .catch(() => ''), + ).then((res: Response) => res.text()), ), ); for (const pageHtml of batchHtmls) {