From 1f6ecda9e92bf7a39fb1b22da3d63a5effcd5a12 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Jun 2023 19:48:35 +0200 Subject: [PATCH 01/83] Add FlatManga decorator and plugins --- .../engine/websites/decorators/FlatManga.ts | 144 ++++++++++++++++++ web/src/engine/websites/legacy/KissAway.ts | 48 +++--- web/src/engine/websites/legacy/Manga33.ts | 75 +++------ web/src/engine/websites/legacy/MangaTR.ts | 94 ++++-------- web/src/engine/websites/legacy/ManhuaScan.ts | 84 +++------- .../engine/websites/legacy/TruyenTranhLH.ts | 65 ++------ web/src/engine/websites/legacy/WeLoveManga.ts | 111 ++------------ 7 files changed, 265 insertions(+), 356 deletions(-) create mode 100644 web/src/engine/websites/decorators/FlatManga.ts diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts new file mode 100644 index 0000000000..18e5fa63a9 --- /dev/null +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -0,0 +1,144 @@ +import { FetchCSS, FetchRequest } from "../../FetchProvider"; +import { Chapter, Manga, MangaScraper} from "../../providers/MangaPlugin"; +import { Page } from "../../providers/MangaPlugin"; +import type * as Common from './Common'; + +export const pathSinglePageManga = '/manga-list.html?listType=allABC'; +export const queryChapterLanguage = 'ul.manga-info h1 span.flag-icon'; +export const queryChapterLanguageClassRX = /flag-icon-([a-zA-Z]+)/; + +export const queryMangaTitle = [ + 'li:last-of-type span[itemprop="name"]', + 'ul.manga-info h3', + 'ul.manga-info h1', +].join(','); + +export const queryMangas = [ + 'span[data-toggle="mangapop"] a', + 'div.media h3.media-heading a', + 'div.container a[data-toggle="mangapop"]', + 'div.card-body div.series-title a' +].join(','); + +export const queryChapters = [ + 'div#tab-chapper table tr td a.chapter', + 'ul.list-chapters > a', + 'div#tab-chapper div#list-chapters span.title a.chapter' +].join(','); + +export const queryChapterTitle = [ + 'div.chapter-name', +].join(','); + +export const queryPages = [ + 'img.chapter-img', + 'div#chapter-content img', + 'div.chapter-content img' +].join(','); + + +/********************************************** + ******** Chapters List Extraction Methods ****** + **********************************************/ + +/** + * A class decorator that adds the ability to extract all chapters for a given manga from this website using the given CSS {@link query}. + * This method utilizes the HTML pages provided by the **MadTheme Admin AJAX endpoint** to extract the chapters. + * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted + */ +export function ChaptersSinglePageCSS(query = queryChapters) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + if (context && context.kind !== 'class') { + throw new Error(context.name); + } + return class extends ctor { + public async FetchChapters(this: MangaScraper, manga: Manga): Promise { + return FetchChaptersSinglePageCSS.call(this, manga, query); + } + }; + }; +} + +/** + * An extension method for extracting all chapters for the given {@link manga} using the given CSS {@link query}. + * This method utilizes the HTML pages provided by the **MadTheme Admin AJAX endpoint** to extract the chapters. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param manga - A reference to the {@link Manga} which shall be assigned as parent for the extracted chapters + * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted + */ +export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters): Promise { + const url = new URL(manga.Identifier, this.URI) + const request = new FetchRequest(url.href); + const data = await FetchCSS(request, query); + + return data.map(anchor => { + if (anchor.dataset.href) { + anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); + } + const id = anchor.pathname; + const titleElement = anchor.querySelector(queryChapterTitle); + let title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); + let mangaTitle = manga.Title.replace(/\s*-\s*RAW$/, ''); + //escape all special characters used in Javascript regexes + title = title.replace(new RegExp(mangaTitle.replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&')), ''); + title = title.replace(/^\s*-\s*/, ''); + title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); + return new Chapter(this, manga, id, title); + }); +} + +/********************************************** + ******** Page List Extraction Methods ******** + **********************************************/ + +/** + * An extension method for extracting all pages for the given {@link chapter} using the first match of the given regular expression {@link matchers}. + * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages + * @param query - CSS query to get chapter link + */ +export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query = queryPages): Promise { + const uri = new URL(chapter.Identifier, this.URI); + const request = new FetchRequest(uri.href); + const data = await FetchCSS(request, query); + const pages = data + .map(element => { + try { + element.dataset.src = window.atob(element.dataset.src); + } catch (_) { /* ignore */ } + try { + element.dataset.src = window.atob(element.dataset.srcset); + } catch (_) { /* ignore */ } + try { + element.dataset.original = window.atob(element.dataset.original); + } catch (_) { /* ignore */ } + try { + element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc); + } catch (_) { /* ignore */ } + try { + element.dataset.aload = window.atob(element.dataset.aload); + } catch (_) { /* ignore */ } + return element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; + }); + return pages.filter(url => !url.includes('3282f6a4b7_o') && !url.includes('donate')).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.href })); + +} + +/** + * A class decorator that adds the ability to extract all pages for the given {@link chapter} using the first match of the given regular expression {@link matchers}. + * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. + * @param query - CSS query to get chapter link + */ +export function PagesSinglePageCSS(query = queryPages) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + if (context && context.kind !== 'class') { + throw new Error(context.name); + } + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageCSS.call(this, chapter, query); + } + }; + }; +} diff --git a/web/src/engine/websites/legacy/KissAway.ts b/web/src/engine/websites/legacy/KissAway.ts index 70bf18f22f..eff7cd88da 100755 --- a/web/src/engine/websites/legacy/KissAway.ts +++ b/web/src/engine/websites/legacy/KissAway.ts @@ -1,32 +1,42 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './KissAway.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { type Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; +import { FetchRequest, FetchWindowScript } from '../../FetchProvider'; + +//TODO Implement at request level a BYPASS for this DDOSS protection +//its not triggered on main page but on manga page + +let ddosProtectionPassed = false; + +@Common.MangaCSS(/^https?:\/\/klz9\.com\/\S+\.html$/, FlatManga.queryMangaTitle) +@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) +@FlatManga.PagesSinglePageCSS() +@Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('kissaway', `KLManga`, 'https://klmanga.com' /*, Tags.Language.English, Tags ... */); + super('kissaway', `KLManga`, 'https://klz9.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } -} - -// Original Source -/* -class KissAway extends FlatManga { - constructor() { - super(); - super.id = 'kissaway'; - super.label = 'KLManga'; - this.tags = [ 'manga', 'raw', 'japanese' ]; - this.url = 'https://klmanga.com'; - this.requestOptions.headers.set('x-referer', this.url); + public override async FetchChapters(manga: Manga): Promise { + if (!ddosProtectionPassed) { + await FetchWindowScript(new FetchRequest(new URL(manga.Identifier, this.URI).href), '', 5000); + ddosProtectionPassed = true; + } + const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga, FlatManga.queryChapters); + //dupe example : https://klz9.com/ybed-29-years-old-bachelor-was-brought-to-a-different-world-to-live-freely-raw.html + const uniqueChapters = chapters.filter( + (obj, index) => + chapters.findIndex((item) => item.Identifier === obj.Identifier) === index + ); + return uniqueChapters; } + } -*/ \ No newline at end of file diff --git a/web/src/engine/websites/legacy/Manga33.ts b/web/src/engine/websites/legacy/Manga33.ts index edf2a4ddc4..632310780f 100755 --- a/web/src/engine/websites/legacy/Manga33.ts +++ b/web/src/engine/websites/legacy/Manga33.ts @@ -1,69 +1,30 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './Manga33.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; - +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; + +@Common.MangaCSS(/^https?:\/\/www\.manga33\.com\/manga\/\S+\.html$/, FlatManga.queryMangaTitle) +@Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) +@Common.PagesSinglePageCSS(FlatManga.queryPages) +@Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('manga33', `Manga33`, 'https://www.manga33.com' /*, Tags.Language.English, Tags ... */); + super('manga33', `Manga33`, 'https://www.manga33.com', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); } public override get Icon() { return icon; } -} - -// Original Source -/* -class Manga33 extends FlatManga { - - constructor() { - super(); - super.id = 'manga33'; - super.label = 'Manga33'; - this.tags = [ 'manga', 'webtoon', 'english' ]; - this.url = 'https://www.manga33.com'; - this.path = '/list/lastdotime-0.html'; - this.requestOptions.headers.set('x-referer', this.url); - - this.queryMangaTitle = 'head meta[name="description"]'; - this.queryMangas = 'div.media div.media-body h3.media-heading a'; - this.queryPages = 'div.chapter-content source'; - this.language = 'en'; - } - - async _getMangas() { - let mangaList = []; - const uri = new URL(this.path, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'ul.pagination li:last-of-type a'); - const pageCount = parseInt(data[0].href.match(/(\d+)\.html$/)[1]); - for(let page = 0; page <= pageCount; page++) { - let mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - } - return mangaList; - } - - async _getMangasFromPage(page) { - const uri = new URL(`/list/lastdotime-${page}.html`, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryMangas); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } - async _getChapters(manga) { - const chapters = await super._getChapters(manga); - chapters.forEach(chapter => chapter.id = chapter.id.replace(/-\d+.html$/, '-all.html')); - return chapters; + public override async FetchChapters(manga: Manga): Promise { + const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga, FlatManga.queryChapters); + const fixedChapters = chapters.map(chapter => new Chapter(this, manga, chapter.Identifier.replace(/-\d+.html$/, '-all.html'), chapter.Title)); + const uniqueChapters = fixedChapters.filter( + (obj, index) => + fixedChapters.findIndex((item) => item.Identifier === obj.Identifier) === index + ); + return uniqueChapters; } } -*/ \ No newline at end of file diff --git a/web/src/engine/websites/legacy/MangaTR.ts b/web/src/engine/websites/legacy/MangaTR.ts index 43eedb1c53..0d42c5cb68 100755 --- a/web/src/engine/websites/legacy/MangaTR.ts +++ b/web/src/engine/websites/legacy/MangaTR.ts @@ -1,70 +1,44 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './MangaTR.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import { FetchCSS, FetchRequest, FetchWindowScript } from '../../FetchProvider'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; +function MangaLabelExtractor(element: HTMLTitleElement) { + return element.text.split(' - ')[0]; +} +@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/\S+\.html$/, 'body title', MangaLabelExtractor) +@Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) +@FlatManga.PagesSinglePageCSS() +@Common.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { - super('mangatr', `Manga-TR`, 'https://manga-tr.com' /*, Tags.Language.English, Tags ... */); + super('mangatr', `Manga-TR`, 'https://manga-tr.com', Tags.Language.Turkish, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } -} - -// Original Source -/* -class MangaTR extends FlatManga { - - constructor() { - super(); - super.id = 'mangatr'; - super.label = 'Manga-TR'; - this.tags = [ 'manga', 'turkish' ]; - this.url = 'https://manga-tr.com'; - - this.queryMangaTitle = 'meta[property="og:title"]'; - this.queryMangas = 'div.container a[data-toggle="mangapop"]'; - this.requestOptions.headers.set('x-referer', this.url); - this.requestOptions.headers.set('x-cookie', 'read_type=1'); - } - async _initializeConnector() { - for(let path of [this.path, '/manga-list.html']) { - const uri = new URL(path, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, '', 30000, true); - } - } - - async _getMangaFromURI(uri) { - const manga = await super._getMangaFromURI(uri); - manga.title = manga.title.split(' - ').shift().trim(); - return manga; + public override async Initialize(): Promise { + const uri = new URL('/manga-list.html', this.URI); + const request = new FetchRequest(uri.href); + return FetchWindowScript(request, `window.cookieStore.set('read_type', '1')`, 0, 30000); } - async _getChapters(manga) { - let chapterList = []; - let uri = new URL(manga.id, this.url); - let request = new Request(uri, this.requestOptions); - let data = await this.fetchRegex(request, /"([^"]*cek\/fetch_pages_manga.php\?manga_cek=[^"]*)"/g); - request = new Request(new URL(data[0], this.url), this.requestOptions); - request.headers.set('x-requested-with', 'XMLHttpRequest'); - data = await this.fetchDOM(request, 'ul.pagination1 li:last-of-type a'); - const pageCount = data.length > 0 ? parseInt(data.pop().dataset.page) : 1; - for(let page = 1; page <= pageCount; page++) { - let chapters = await this._getChaptersFromPage(manga, request.url, page); - chapterList.push(...chapters); + public override async FetchChapters(manga: Manga): Promise { + const chapterList = []; + for (let page = 1, run = true; run; page++) { + const chapters = await this._getChaptersFromPage(manga, page); + chapters.length > 0 ? chapterList.push(...chapters) : run = false; } return chapterList; } - - async _getChaptersFromPage(manga, action, page) { - const request = new Request(action, { + private async _getChaptersFromPage(manga: Manga, page: number): Promise{ + const mangaslug = manga.Identifier.match(/manga-([\S]+)\.html/)[1]; + const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); + const request = new FetchRequest(url.href, { method: 'POST', body: 'page=' + page, headers: { @@ -72,13 +46,11 @@ class MangaTR extends FlatManga { 'x-requested-with': 'XMLHttpRequest' } }); - const data = await this.fetchDOM(request, 'table.table tr td.table-bordered:first-of-type > a'); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.replace(manga.title, '').trim() - }; - }); + + const data = await FetchCSS(request, 'table.table tr td.table-bordered:first-of-type > a'); + const esc = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); + const reg = new RegExp(esc, 'i'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(reg, ''))); } -} -*/ \ No newline at end of file + +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ManhuaScan.ts b/web/src/engine/websites/legacy/ManhuaScan.ts index 44f5572eb5..acc6eea47f 100755 --- a/web/src/engine/websites/legacy/ManhuaScan.ts +++ b/web/src/engine/websites/legacy/ManhuaScan.ts @@ -1,64 +1,10 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './ManhuaScan.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; -export default class extends DecoratableMangaScraper { - - public constructor() { - super('manhuascan', `ManhuaScan`, 'https://manhuascan.com' /*, Tags.Language.English, Tags ... */); - } - - public override get Icon() { - return icon; - } -} - -// Original Source -/* -class ManhuaScan extends FlatManga { - - constructor() { - super(); - super.id = 'manhuascan'; - super.label = 'ManhuaScan'; - this.tags = [ 'manga', 'webtoon', 'hentai', 'multi-lingual' ]; - this.url = 'https://manhuascan.com'; - this.requestOptions.headers.set('x-referer', this.url + '/'); - - this.queryChapters = 'div#tab-chapper div#list-chapters span.title a.chapter'; - } - - async _getMangas() { - let mangaList = []; - const uri = new URL('/manga-list.html', this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'div.pagination-wrap ul.pagination li:nth-last-of-type(2) a'); - const pageCount = parseInt(data[0].text); - for(let page = 1; page <= pageCount; page++) { - const mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - } - return mangaList; - } - - async _getMangasFromPage(page) { - const uri = new URL('/manga-list.html?page=' + page, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'div.media h3.media-heading a'); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } - - // Same decryption as in HeroScan - async _getPages(chapter) { - const script = ` +const pageScript = ` new Promise(async resolve => { const response = await fetch('/app/manga/controllers/cont.chapterServer1.php', { method: 'POST', @@ -74,11 +20,19 @@ class ManhuaScan extends FlatManga { const decrypted = CryptoJS.AES.decrypt(data, key, options).toString(CryptoJS.enc.Utf8).replace(/(^\u0002+)|(\u0003+$)/g, '').trim(); resolve(decrypted.split(',')); }); - `; - const uri = new URL(chapter.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await Engine.Request.fetchUI(request, script); - return data.map(link => this.createConnectorURI(link)); +`; + +@Common.MangaCSS(/^https?:\/\/manhuascan\.io\/manga\/[^/]+$/, FlatManga.queryMangaTitle) +@Common.MangasMultiPageCSS('/manga-list?page={page}', FlatManga.queryMangas) +@FlatManga.ChaptersSinglePageCSS(FlatManga.queryChapters) +@Common.PagesSinglePageJS(pageScript) +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('manhuascan', `ManhuaScan`, 'https://manhuascan.io', Tags.Language.English, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); + } + public override get Icon() { + return icon; } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/TruyenTranhLH.ts b/web/src/engine/websites/legacy/TruyenTranhLH.ts index 3e5c80f673..4a6f83288c 100755 --- a/web/src/engine/websites/legacy/TruyenTranhLH.ts +++ b/web/src/engine/websites/legacy/TruyenTranhLH.ts @@ -1,65 +1,22 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './TruyenTranhLH.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; + +@Common.MangaCSS(/^https?:\/\/truyentranhlh\.net\/truyen-tranh\/[^/]+$/, 'span.series-name') +@Common.MangasMultiPageCSS('/danh-sach?page={page}', FlatManga.queryMangas) +@FlatManga.ChaptersSinglePageCSS() +@Common.PagesSinglePageCSS(FlatManga.queryPages) +@Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('truyentranhlh', `TruyentranhLH`, 'https://truyentranhlh.net' /*, Tags.Language.English, Tags ... */); + super('truyentranhlh', `TruyentranhLH`, 'https://truyentranhlh.net', Tags.Language.Vietnamese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } -} - -// Original Source -/* -class TruyenTranhLH extends FlatManga { - - constructor() { - super(); - super.id = 'truyentranhlh'; - super.label = 'TruyentranhLH'; - this.tags = [ 'manga', 'webtoon', 'vietnamese' ]; - this.url = 'https://truyentranhlh.net'; - this.links = { - login: 'https://truyentranhlh.net/login' - }; - - this.queryMangaTitle = 'meta[property="og:title"]'; - this.queryChapters = 'ul.list-chapters > a'; - this.queryChapterTitle = 'div.chapter-name'; - this.queryPages = 'div#chapter-content source'; - this.language = ''; - } - - async _getMangas() { - let mangaList = []; - let uri = new URL('/danh-sach', this.url); - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'div.pagination_wrap a:last-of-type'); - let pageCount = parseInt(data[0].href.match(/(\d+)$/)[1]); - for(let page = 1; page <= pageCount; page++) { - let mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - } - return mangaList; - } - - async _getMangasFromPage(page) { - let uri = new URL('/danh-sach?page=' + page, this.url); - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'div.card-body div.thumb-item-flow div.series-title a'); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/WeLoveManga.ts b/web/src/engine/websites/legacy/WeLoveManga.ts index 362bafde39..9f0e20eb43 100755 --- a/web/src/engine/websites/legacy/WeLoveManga.ts +++ b/web/src/engine/websites/legacy/WeLoveManga.ts @@ -1,111 +1,22 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './WeLoveManga.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as FlatManga from '../decorators/FlatManga'; + +@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/\S+\/$/, FlatManga.queryMangaTitle) +@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas) +@FlatManga.ChaptersSinglePageCSS(FlatManga.queryChapters) +@Common.PagesSinglePageCSS(FlatManga.queryPages) +@Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('lovehug', `WeLoveManga`, 'https://welovemanga.net' /*, Tags.Language.English, Tags ... */); + super('lovehug', `WeLoveManga.One`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } -} - -// Original Source -/* -class WeLoveManga extends FlatManga { - - constructor() { - super(); - super.id = 'lovehug'; - super.label = 'WeLoveManga'; - this.tags = [ 'manga', 'hentai', 'raw', 'japanese' ]; - this.url = 'https://welovemanga.net'; - this.path = '/manga-list.html'; - this.requestOptions.headers.set('x-referer', this.url); - - this.queryMangaTitle = 'ul.manga-info h3'; - this.queryMangas = 'div.card-body div.series-title a'; - this.queryChapters = 'ul.list-chapters > a'; - this.queryChapterTitle = 'div.chapter-name'; - } - - async _initializeConnector() { - for(let path of [this.path, '/0/0/']) { - const uri = new URL(path, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, '', 30000, true); - } - } - - async _getMangas() { - let mangaList = []; - const uri = new URL(this.path, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'ul.pagination li:nth-last-of-type(2) a'); - const pageCount = parseInt(data[0].text.trim()); - for(let page = 1; page <= pageCount; page++) { - let mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - await this.wait(5000); - } - return mangaList; - } - - async _getMangasFromPage(page) { - const uri = new URL(this.path, this.url); - uri.searchParams.set('page', page); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryMangas); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } - - async _getChapters(manga) { - const script = ` - new Promise(resolve => { - const chapters = [...document.querySelectorAll('ul.list-chapters > a')].map(element => { - return { - id: element.pathname, - title: element.title - }; - }); - resolve(chapters); - }); - `; - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, script); - } - - async _getPages(chapter) { - const uri = new URL(chapter.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryPages); - return data.map(element => { - const link = [ ...element.attributes] - .filter(attribute => !['src', 'class', 'alt'].includes(attribute.name)) - .map(attribute => { - try { - return atob(attribute.value.trim()); - } catch(_) { - return attribute.value.trim(); - } - }) - .find(value => { - return /^http/.test(value); - }); - return this.createConnectorURI(this.getAbsolutePath(link || element, request.url)); - }); - } -} -*/ \ No newline at end of file +} \ No newline at end of file From d19c61a1e348bdd97cc941073d2f656818d6b809 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Jun 2023 19:55:48 +0200 Subject: [PATCH 02/83] Update FlatManga.ts --- web/src/engine/websites/decorators/FlatManga.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 18e5fa63a9..d68755040b 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,5 +1,5 @@ import { FetchCSS, FetchRequest } from "../../FetchProvider"; -import { Chapter, Manga, MangaScraper} from "../../providers/MangaPlugin"; +import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; import type * as Common from './Common'; @@ -36,7 +36,6 @@ export const queryPages = [ 'div.chapter-content img' ].join(','); - /********************************************** ******** Chapters List Extraction Methods ****** **********************************************/ @@ -67,7 +66,7 @@ export function ChaptersSinglePageCSS(query = queryChapters) { * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters): Promise { - const url = new URL(manga.Identifier, this.URI) + const url = new URL(manga.Identifier, this.URI); const request = new FetchRequest(url.href); const data = await FetchCSS(request, query); @@ -78,8 +77,8 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang const id = anchor.pathname; const titleElement = anchor.querySelector(queryChapterTitle); let title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); - let mangaTitle = manga.Title.replace(/\s*-\s*RAW$/, ''); - //escape all special characters used in Javascript regexes + const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/, ''); + //escape all special characters used in Javascript regexes title = title.replace(new RegExp(mangaTitle.replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&')), ''); title = title.replace(/^\s*-\s*/, ''); title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); From 974e12bd5b05845c4b572a6251e0885fc8d42984 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Jun 2023 19:56:49 +0200 Subject: [PATCH 03/83] Update KissAway.ts --- web/src/engine/websites/legacy/KissAway.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/engine/websites/legacy/KissAway.ts b/web/src/engine/websites/legacy/KissAway.ts index eff7cd88da..de9589d684 100755 --- a/web/src/engine/websites/legacy/KissAway.ts +++ b/web/src/engine/websites/legacy/KissAway.ts @@ -38,5 +38,4 @@ export default class extends DecoratableMangaScraper { ); return uniqueChapters; } - } From be0134bc25a4ddaf81522d1e307c82ff86129dbc Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 12 Jun 2023 19:35:14 +0200 Subject: [PATCH 04/83] case insensitive replace --- web/src/engine/websites/decorators/FlatManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index d68755040b..423f7210f6 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -77,7 +77,7 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang const id = anchor.pathname; const titleElement = anchor.querySelector(queryChapterTitle); let title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); - const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/, ''); + const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, ''); //escape all special characters used in Javascript regexes title = title.replace(new RegExp(mangaTitle.replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&')), ''); title = title.replace(/^\s*-\s*/, ''); From 25d5d3cb068bc795679b59b4535825a70c5cc015 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 21 Jun 2023 22:27:36 +0200 Subject: [PATCH 05/83] remove useless parameters --- web/src/engine/websites/legacy/ManhuaScan.ts | 2 +- web/src/engine/websites/legacy/WeLoveManga.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/legacy/ManhuaScan.ts b/web/src/engine/websites/legacy/ManhuaScan.ts index acc6eea47f..94ed0fead5 100755 --- a/web/src/engine/websites/legacy/ManhuaScan.ts +++ b/web/src/engine/websites/legacy/ManhuaScan.ts @@ -24,7 +24,7 @@ const pageScript = ` @Common.MangaCSS(/^https?:\/\/manhuascan\.io\/manga\/[^/]+$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/manga-list?page={page}', FlatManga.queryMangas) -@FlatManga.ChaptersSinglePageCSS(FlatManga.queryChapters) +@FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageJS(pageScript) @Common.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/legacy/WeLoveManga.ts b/web/src/engine/websites/legacy/WeLoveManga.ts index 9f0e20eb43..e998ab6cc1 100755 --- a/web/src/engine/websites/legacy/WeLoveManga.ts +++ b/web/src/engine/websites/legacy/WeLoveManga.ts @@ -6,7 +6,7 @@ import * as FlatManga from '../decorators/FlatManga'; @Common.MangaCSS(/^https?:\/\/welovemanga\.one\/\S+\/$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas) -@FlatManga.ChaptersSinglePageCSS(FlatManga.queryChapters) +@FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() From 3faab1d50b0706abdae1837b20474184f9c9a657 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 8 Jul 2023 21:15:23 +0200 Subject: [PATCH 06/83] moved sites from legacy and add tests --- .../engine/websites/{legacy => }/Manga33.ts | 8 +++--- .../engine/websites/{legacy => }/Manga33.webp | Bin web/src/engine/websites/Manga33_e2e.ts | 25 ++++++++++++++++++ .../websites/{legacy => }/ManhuaScan.ts | 8 +++--- .../websites/{legacy => }/ManhuaScan.webp | Bin web/src/engine/websites/ManhuaScan_e2e.ts | 25 ++++++++++++++++++ .../websites/{legacy => }/TruyenTranhLH.ts | 8 +++--- .../websites/{legacy => }/TruyenTranhLH.webp | Bin web/src/engine/websites/TruyenTranhLH_e2e.ts | 25 ++++++++++++++++++ .../websites/{legacy => }/WeLoveManga.ts | 12 ++++----- .../websites/{legacy => }/WeLoveManga.webp | Bin web/src/engine/websites/WeLoveManga_e2e.ts | 25 ++++++++++++++++++ web/src/engine/websites/_index.ts | 8 +++--- .../engine/websites/decorators/FlatManga.ts | 17 ++++++++++-- 14 files changed, 137 insertions(+), 24 deletions(-) rename web/src/engine/websites/{legacy => }/Manga33.ts (88%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/Manga33.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/Manga33_e2e.ts rename web/src/engine/websites/{legacy => }/ManhuaScan.ts (87%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ManhuaScan.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/ManhuaScan_e2e.ts rename web/src/engine/websites/{legacy => }/TruyenTranhLH.ts (74%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/TruyenTranhLH.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/TruyenTranhLH_e2e.ts rename web/src/engine/websites/{legacy => }/WeLoveManga.ts (65%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/WeLoveManga.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/WeLoveManga_e2e.ts diff --git a/web/src/engine/websites/legacy/Manga33.ts b/web/src/engine/websites/Manga33.ts old mode 100755 new mode 100644 similarity index 88% rename from web/src/engine/websites/legacy/Manga33.ts rename to web/src/engine/websites/Manga33.ts index 632310780f..e7a5603aa1 --- a/web/src/engine/websites/legacy/Manga33.ts +++ b/web/src/engine/websites/Manga33.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './Manga33.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; @Common.MangaCSS(/^https?:\/\/www\.manga33\.com\/manga\/\S+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) diff --git a/web/src/engine/websites/legacy/Manga33.webp b/web/src/engine/websites/Manga33.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/Manga33.webp rename to web/src/engine/websites/Manga33.webp diff --git a/web/src/engine/websites/Manga33_e2e.ts b/web/src/engine/websites/Manga33_e2e.ts new file mode 100644 index 0000000000..39b24dc38d --- /dev/null +++ b/web/src/engine/websites/Manga33_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'manga33', + title: 'Manga33' + }, + container: { + url: 'https://www.manga33.com/manga/yuan-zun.html', + id: '/manga/yuan-zun.html' , + title: 'Yuan Zun' + }, + child: { + id: '/manga/yuan-zun-510-all.html', + title: 'Chapter 510' + }, + entry: { + index: 0, + size: 191_444, + type: 'image/jpeg' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ManhuaScan.ts b/web/src/engine/websites/ManhuaScan.ts old mode 100755 new mode 100644 similarity index 87% rename from web/src/engine/websites/legacy/ManhuaScan.ts rename to web/src/engine/websites/ManhuaScan.ts index 94ed0fead5..93e2fcadcc --- a/web/src/engine/websites/legacy/ManhuaScan.ts +++ b/web/src/engine/websites/ManhuaScan.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './ManhuaScan.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; const pageScript = ` new Promise(async resolve => { diff --git a/web/src/engine/websites/legacy/ManhuaScan.webp b/web/src/engine/websites/ManhuaScan.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/ManhuaScan.webp rename to web/src/engine/websites/ManhuaScan.webp diff --git a/web/src/engine/websites/ManhuaScan_e2e.ts b/web/src/engine/websites/ManhuaScan_e2e.ts new file mode 100644 index 0000000000..58ce0b0597 --- /dev/null +++ b/web/src/engine/websites/ManhuaScan_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'manhuascan', + title: 'ManhuaScan' + }, + container: { + url: 'https://manhuascan.io/manga/wu-dong-qian-kun', + id: '/manga/wu-dong-qian-kun' , + title: 'WU DONG QIAN KUN' + }, + child: { + id: '/manga/wu-dong-qian-kun/chapter-203', + title: 'Chapter 203', + }, + entry: { + index: 1, + size: 166_888, + type: 'image/webp' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/legacy/TruyenTranhLH.ts b/web/src/engine/websites/TruyenTranhLH.ts old mode 100755 new mode 100644 similarity index 74% rename from web/src/engine/websites/legacy/TruyenTranhLH.ts rename to web/src/engine/websites/TruyenTranhLH.ts index 4a6f83288c..2a39815aa6 --- a/web/src/engine/websites/legacy/TruyenTranhLH.ts +++ b/web/src/engine/websites/TruyenTranhLH.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './TruyenTranhLH.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; @Common.MangaCSS(/^https?:\/\/truyentranhlh\.net\/truyen-tranh\/[^/]+$/, 'span.series-name') @Common.MangasMultiPageCSS('/danh-sach?page={page}', FlatManga.queryMangas) diff --git a/web/src/engine/websites/legacy/TruyenTranhLH.webp b/web/src/engine/websites/TruyenTranhLH.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/TruyenTranhLH.webp rename to web/src/engine/websites/TruyenTranhLH.webp diff --git a/web/src/engine/websites/TruyenTranhLH_e2e.ts b/web/src/engine/websites/TruyenTranhLH_e2e.ts new file mode 100644 index 0000000000..8712aa67b3 --- /dev/null +++ b/web/src/engine/websites/TruyenTranhLH_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'truyentranhlh', + title: 'TruyentranhLH' + }, + container: { + url: 'https://truyentranhlh.net/truyen-tranh/tho-ren-huyen-thoai', + id: '/truyen-tranh/tho-ren-huyen-thoai' , + title: 'Thợ Rèn Huyền Thoại' + }, + child: { + id: '/truyen-tranh/tho-ren-huyen-thoai/chapter-188-227', + title: 'Chapter 188', + }, + entry: { + index: 0, + size: 232_191, + type: 'image/jpeg' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/legacy/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts old mode 100755 new mode 100644 similarity index 65% rename from web/src/engine/websites/legacy/WeLoveManga.ts rename to web/src/engine/websites/WeLoveManga.ts index e998ab6cc1..267d28c6bd --- a/web/src/engine/websites/legacy/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -1,11 +1,11 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './WeLoveManga.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/\S+\/$/, FlatManga.queryMangaTitle) -@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas) +@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/\S+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas,1,1,0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() diff --git a/web/src/engine/websites/legacy/WeLoveManga.webp b/web/src/engine/websites/WeLoveManga.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/WeLoveManga.webp rename to web/src/engine/websites/WeLoveManga.webp diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts new file mode 100644 index 0000000000..b034938221 --- /dev/null +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'lovehug', + title: 'WeLoveManga.One' + }, + container: { + url: 'https://welovemanga.one/mgraw-1067/', + id: '/mgraw-1067/', + title: 'TONO KANRI O SHITE MIYOU' + }, + child: { + id: '/read-tono-kanri-o-shite-miyou-raw-chapter-65.2.html', + title: 'Chapter 65.2', + }, + entry: { + index: 0, + size: 219_948, + type: 'image/jpeg' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 2ef30585d2..733e3171da 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -204,6 +204,7 @@ export { default as MagicalTranslators } from './MagicalTranslators'; export { default as MaID } from './MaID'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga41 } from './Manga41'; export { default as Manga68 } from './Manga68'; export { default as Manga347 } from './Manga347'; @@ -344,6 +345,7 @@ export { default as ManhuaES } from './ManhuaES'; export { default as ManhuaFast } from './ManhuaFast'; export { default as Manhuaga } from './Manhuaga'; export { default as ManhuaPlus } from './ManhuaPlus'; +export { default as ManhuaScan } from './ManhuaScan'; export { default as ManhuaUs } from './ManhuaUs'; export { default as ManhwaClub } from './ManhwaClub'; export { default as ManhwaFull } from './ManhwaFull'; @@ -544,6 +546,7 @@ export { default as TrashScanlations } from './TrashScanlations'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; export { default as TruyenTranhAudioOnline } from './TruyenTranhAudioOnline'; +export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TRWebtoon } from './TRWebtoon'; export { default as TsubakiNoScan } from './TsubakiNoScan'; export { default as TuMangaNet } from './TuMangaNet'; @@ -569,6 +572,7 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRCOM } from './WebtoonTRCOM'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhatStatus } from './WhatStatus'; export { default as WhiteCloudPavilion } from './WhiteCloudPavilion'; @@ -776,7 +780,6 @@ export { default as MagKan } from './legacy/MagKan'; export { default as Manamoa } from './legacy/Manamoa'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga99 } from './legacy/Manga99'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaArab } from './legacy/MangaArab'; @@ -870,7 +873,6 @@ export { default as ManHuaFen } from './legacy/ManHuaFen'; export { default as ManHuaGui } from './legacy/ManHuaGui'; export { default as ManhuaID } from './legacy/ManhuaID'; export { default as ManHuaNiu } from './legacy/ManHuaNiu'; -export { default as ManhuaScan } from './legacy/ManhuaScan'; export { default as ManhuaTai } from './legacy/ManhuaTai'; export { default as ManhuaZ } from './legacy/ManhuaZ'; export { default as Manhwa18 } from './legacy/Manhwa18'; @@ -1033,7 +1035,6 @@ export { default as ToonSarang } from './legacy/ToonSarang'; export { default as TrueColorsScan } from './legacy/TrueColorsScan'; export { default as TruyenChon } from './legacy/TruyenChon'; export { default as TruyenTranhAudio } from './legacy/TruyenTranhAudio'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TruyenTranhtuan } from './legacy/TruyenTranhtuan'; export { default as TsubasaSociety } from './legacy/TsubasaSociety'; export { default as Tsumino } from './legacy/Tsumino'; @@ -1065,7 +1066,6 @@ export { default as WebNovel } from './legacy/WebNovel'; export { default as WebNovelLive } from './legacy/WebNovelLive'; export { default as WeComics } from './legacy/WeComics'; export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WhimSubs } from './legacy/WhimSubs'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 423f7210f6..6d1d384a60 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -3,6 +3,18 @@ import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlug import { Page } from "../../providers/MangaPlugin"; import type * as Common from './Common'; +export function MangaLabelExtractor(element: HTMLElement) { + let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; + title = title.replace(/\s*-\s*RAW$/i, ''); + return title; +} +export function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + let title = anchor.getAttribute('text') ? anchor.getAttribute('text') : anchor.textContent; + title = title.replace(/\s*-\s*RAW$/i, ''); + return { id, title }; +} + export const pathSinglePageManga = '/manga-list.html?listType=allABC'; export const queryChapterLanguage = 'ul.manga-info h1 span.flag-icon'; export const queryChapterLanguageClassRX = /flag-icon-([a-zA-Z]+)/; @@ -77,10 +89,11 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang const id = anchor.pathname; const titleElement = anchor.querySelector(queryChapterTitle); let title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); - const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, ''); //escape all special characters used in Javascript regexes - title = title.replace(new RegExp(mangaTitle.replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&')), ''); + const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, '').replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&'); + title = title.replace(new RegExp(mangaTitle, 'i'), ''); title = title.replace(/^\s*-\s*/, ''); + title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); return new Chapter(this, manga, id, title); }); From c895675a18deb43c35fa2e1d7e491f6a50994b9b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 8 Jul 2023 22:11:53 +0200 Subject: [PATCH 07/83] some changes * Add the possibility to use custom filters when getting pages * move mangaTR from legacy to websites --- .../engine/websites/{legacy => }/MangaTR.ts | 19 +++++++------ .../engine/websites/{legacy => }/MangaTR.webp | Bin web/src/engine/websites/MangaTR_e2e.ts | 25 ++++++++++++++++++ web/src/engine/websites/_index.ts | 2 +- .../engine/websites/decorators/FlatManga.ts | 11 ++++---- 5 files changed, 40 insertions(+), 17 deletions(-) rename web/src/engine/websites/{legacy => }/MangaTR.ts (80%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/MangaTR.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/MangaTR_e2e.ts diff --git a/web/src/engine/websites/legacy/MangaTR.ts b/web/src/engine/websites/MangaTR.ts old mode 100755 new mode 100644 similarity index 80% rename from web/src/engine/websites/legacy/MangaTR.ts rename to web/src/engine/websites/MangaTR.ts index 0d42c5cb68..4c31e5cf7c --- a/web/src/engine/websites/legacy/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -1,22 +1,21 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './MangaTR.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import { FetchCSS, FetchRequest, FetchWindowScript } from '../../FetchProvider'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import { FetchCSS, FetchRequest, FetchWindowScript } from '../FetchProvider'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; function MangaLabelExtractor(element: HTMLTitleElement) { - return element.text.split(' - ')[0]; + return element.text.split(' - ')[0].trim(); } -@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/\S+\.html$/, 'body title', MangaLabelExtractor) +@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/manga-\S+\.html$/, 'body title', MangaLabelExtractor) @Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) -@FlatManga.PagesSinglePageCSS() +@FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('mangatr', `Manga-TR`, 'https://manga-tr.com', Tags.Language.Turkish, Tags.Media.Manga, Tags.Source.Aggregator); } - public override get Icon() { return icon; } @@ -50,7 +49,7 @@ export default class extends DecoratableMangaScraper { const data = await FetchCSS(request, 'table.table tr td.table-bordered:first-of-type > a'); const esc = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); const reg = new RegExp(esc, 'i'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(reg, ''))); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(reg, '').trim())); } } \ No newline at end of file diff --git a/web/src/engine/websites/legacy/MangaTR.webp b/web/src/engine/websites/MangaTR.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/MangaTR.webp rename to web/src/engine/websites/MangaTR.webp diff --git a/web/src/engine/websites/MangaTR_e2e.ts b/web/src/engine/websites/MangaTR_e2e.ts new file mode 100644 index 0000000000..6a91f71653 --- /dev/null +++ b/web/src/engine/websites/MangaTR_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'mangatr', + title: 'Manga-TR' + }, + container: { + url: 'https://manga-tr.com/manga-mairimashita-iruma-kun.html', + id: '/manga-mairimashita-iruma-kun.html' , + title: 'Mairimashita! Iruma-kun' + }, + child: { + id: '/id-153837-read-mairimashita-iruma-kun-chapter-174.html', + title: '174' + }, + entry: { + index: 1, + size: 376_632, + type: 'image/jpeg' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 733e3171da..0c56e09320 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -317,6 +317,7 @@ export { default as MangaTitan } from './MangaTitan'; export { default as MangaTopya } from './MangaTopya'; export { default as MangaToRead } from './MangaToRead'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTube } from './MangaTube'; export { default as MangaTurf } from './MangaTurf'; export { default as MangaTX } from './MangaTX'; @@ -858,7 +859,6 @@ export { default as MangaToro } from './legacy/MangaToro'; export { default as MangaToroJA } from './legacy/MangaToroJA'; export { default as MangaToroVI } from './legacy/MangaToroVI'; export { default as MangaTownOnline } from './legacy/MangaTownOnline'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaVadisi } from './legacy/MangaVadisi'; export { default as Mangaz } from './legacy/Mangaz'; export { default as MangaZukiArchive } from './legacy/MangaZukiArchive'; diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 6d1d384a60..acc25e5003 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -15,6 +15,7 @@ export function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } +export const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; export const pathSinglePageManga = '/manga-list.html?listType=allABC'; export const queryChapterLanguage = 'ul.manga-info h1 span.flag-icon'; export const queryChapterLanguageClassRX = /flag-icon-([a-zA-Z]+)/; @@ -93,7 +94,6 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, '').replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&'); title = title.replace(new RegExp(mangaTitle, 'i'), ''); title = title.replace(/^\s*-\s*/, ''); - title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); return new Chapter(this, manga, id, title); }); @@ -110,7 +110,7 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages * @param query - CSS query to get chapter link */ -export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query = queryPages): Promise { +export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query: string = queryPages, exclude: RegExp[] = DefaultExcludes): Promise { const uri = new URL(chapter.Identifier, this.URI); const request = new FetchRequest(uri.href); const data = await FetchCSS(request, query); @@ -133,8 +133,7 @@ export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapt } catch (_) { /* ignore */ } return element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; }); - return pages.filter(url => !url.includes('3282f6a4b7_o') && !url.includes('donate')).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.href })); - + return pages.filter(url => !exclude.some(pattern => pattern.test(url))).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.href })); } /** @@ -142,14 +141,14 @@ export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapt * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. * @param query - CSS query to get chapter link */ -export function PagesSinglePageCSS(query = queryPages) { +export function PagesSinglePageCSS(query : string = queryPages, excludes : RegExp[] = DefaultExcludes) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { if (context && context.kind !== 'class') { throw new Error(context.name); } return class extends ctor { public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageCSS.call(this, chapter, query); + return FetchPagesSinglePageCSS.call(this, chapter, query, excludes); } }; }; From 5697c7a0265dc81cc3cf454a615f9d895a0208b1 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 18 Jul 2023 14:46:49 +0200 Subject: [PATCH 08/83] Update KissAway.ts --- web/src/engine/websites/legacy/KissAway.ts | 51 +++++++++++++++++----- 1 file changed, 39 insertions(+), 12 deletions(-) diff --git a/web/src/engine/websites/legacy/KissAway.ts b/web/src/engine/websites/legacy/KissAway.ts index de9589d684..a073456c62 100755 --- a/web/src/engine/websites/legacy/KissAway.ts +++ b/web/src/engine/websites/legacy/KissAway.ts @@ -5,18 +5,50 @@ import * as Common from '../decorators/Common'; import * as FlatManga from '../decorators/FlatManga'; import { FetchRequest, FetchWindowScript } from '../../FetchProvider'; +const chapterScript = ` + new Promise(async resolve => { + const uri = new URL('app/manga/controllers/cont.listChapter.php', window.location.origin); + uri.searchParams.set('slug', dataL); + const response = await fetch(uri); + data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('a.chapter[title]')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title + }; + }); + const uniqueChapters = chapters.filter((obj, index) =>chapters.findIndex((item) => item.id === obj.id) === index ); + resolve(uniqueChapters); + }); +`; + +const pageScript = ` + new Promise(async resolve => { + const chapId = document.querySelector('input#chapter').value; + const uri = new URL('app/manga/controllers/cont.listImg.php', window.location.origin); + uri.searchParams.set('cid', chapId); + const response = await fetch(uri); + const data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('img.chapter-img')]; + resolve(nodes.map(picture => picture.src)); + }); +`; + //TODO Implement at request level a BYPASS for this DDOSS protection //its not triggered on main page but on manga page -let ddosProtectionPassed = false; - @Common.MangaCSS(/^https?:\/\/klz9\.com\/\S+\.html$/, FlatManga.queryMangaTitle) @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) -@FlatManga.PagesSinglePageCSS() +@Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { + private ddosProtectionPassed = false; + public constructor() { super('kissaway', `KLManga`, 'https://klz9.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } @@ -26,16 +58,11 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - if (!ddosProtectionPassed) { + if (!this.ddosProtectionPassed) { await FetchWindowScript(new FetchRequest(new URL(manga.Identifier, this.URI).href), '', 5000); - ddosProtectionPassed = true; + this.ddosProtectionPassed = true; } - const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga, FlatManga.queryChapters); - //dupe example : https://klz9.com/ybed-29-years-old-bachelor-was-brought-to-a-different-world-to-live-freely-raw.html - const uniqueChapters = chapters.filter( - (obj, index) => - chapters.findIndex((item) => item.Identifier === obj.Identifier) === index - ); - return uniqueChapters; + return Common.FetchChaptersSinglePageJS.call(this, manga, chapterScript, 1000); } + } From cf64432367baad81f74f5feea2c8253d7ee080cb Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 29 Sep 2023 13:10:44 +0200 Subject: [PATCH 09/83] weloma / lovehug fixes (also apply previous fixes by ronny) --- web/src/engine/websites/WeLoMa.ts | 21 ++++ .../engine/websites/{legacy => }/WeLoMa.webp | Bin web/src/engine/websites/WeLoMa_e2e.ts | 25 ++++ web/src/engine/websites/WeLoveManga.ts | 47 +++++++- web/src/engine/websites/WeLoveManga_e2e.ts | 9 +- web/src/engine/websites/_index.ts | 10 +- web/src/engine/websites/legacy/WeLoMa.ts | 112 ------------------ web/src/engine/websites/legacy/WeLoveManga.ts | 111 ----------------- 8 files changed, 97 insertions(+), 238 deletions(-) create mode 100644 web/src/engine/websites/WeLoMa.ts rename web/src/engine/websites/{legacy => }/WeLoMa.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/WeLoMa_e2e.ts delete mode 100755 web/src/engine/websites/legacy/WeLoMa.ts delete mode 100755 web/src/engine/websites/legacy/WeLoveManga.ts diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts new file mode 100644 index 0000000000..f87dc2be12 --- /dev/null +++ b/web/src/engine/websites/WeLoMa.ts @@ -0,0 +1,21 @@ +import { Tags } from '../Tags'; +import icon from './WeLoMa.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; + +@Common.MangaCSS(/^https?:\/\/weloma\.art\/\S+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageCSS() +@Common.PagesSinglePageCSS(FlatManga.queryPages) +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('weloma', `WeLoMa`, 'https://weloma.art', Tags.Media.Manga, Tags.Language.Japanese); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/WeLoMa.webp b/web/src/engine/websites/WeLoMa.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/WeLoMa.webp rename to web/src/engine/websites/WeLoMa.webp diff --git a/web/src/engine/websites/WeLoMa_e2e.ts b/web/src/engine/websites/WeLoMa_e2e.ts new file mode 100644 index 0000000000..c03cf2fdd3 --- /dev/null +++ b/web/src/engine/websites/WeLoMa_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'weloma', + title: 'WeLoMa' + }, + container: { + url: 'https://weloma.art/429/', + id: '/429/', + title: 'SLIME TAOSHITE 300-NEN, SHIRANAI UCHI NI LEVEL MAX NI NATTEMASHITA' + }, + child: { + id: '/429/131864/', + title: 'Chapter 73.1', + }, + entry: { + index: 0, + size: 546_228, + type: 'image/png' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 267d28c6bd..2a35d67abf 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -1,22 +1,57 @@ import { Tags } from '../Tags'; import icon from './WeLoveManga.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/\S+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) -@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas,1,1,0, FlatManga.MangaExtractor) -@FlatManga.ChaptersSinglePageCSS() -@Common.PagesSinglePageCSS(FlatManga.queryPages) +const chapterScript = ` + new Promise(async resolve => { + loadChapterData(mIds); + const nodes = [...document.querySelectorAll('ul.list-chapters a[title]')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title + }; + }); + const uniqueChapters = chapters.filter((obj, index) =>chapters.findIndex((item) => item.id === obj.id) === index ); + resolve(uniqueChapters); + }); +`; + +@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('lovehug', `WeLoveManga.One`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); + super('lovehug', `WeloveManga`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } + + public override async FetchPages(chapter: Chapter): Promise { + let url = new URL(chapter.Identifier, this.URI); + let request = new FetchRequest(url.href, { + headers: { + 'Referer': this.URI.href, + } + }); + const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; + + url = new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI); + request = new FetchRequest(url.href, { + headers: { + 'Referer': this.URI.href, + } + }); + const nodes = await FetchCSS(request, 'img.chapter-img'); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.original.replace(/\n/g, '')))); + } + } \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts index b034938221..47a98fd8ff 100644 --- a/web/src/engine/websites/WeLoveManga_e2e.ts +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -3,12 +3,13 @@ const config = { plugin: { id: 'lovehug', - title: 'WeLoveManga.One' + title: 'WeloveManga' }, container: { - url: 'https://welovemanga.one/mgraw-1067/', - id: '/mgraw-1067/', - title: 'TONO KANRI O SHITE MIYOU' + url: 'https://welovemanga.one/1067/', + id: '/1067/', + title: 'TONO KANRI O SHITE MIYOU', + timeout : 15000 }, child: { id: '/read-tono-kanri-o-shite-miyou-raw-chapter-65.2.html', diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d9a33d0323..b0198b704b 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -173,6 +173,7 @@ export { default as MagicalTranslators } from './MagicalTranslators'; export { default as MaID } from './MaID'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga347 } from './Manga347'; export { default as Manga365 } from './Manga365'; @@ -256,6 +257,7 @@ export { default as MangaTeca } from './MangaTeca'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; export { default as MangaWeebs } from './MangaWeebs'; @@ -415,6 +417,7 @@ export { default as TopToon } from './TopToon'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TRWebtoon } from './TRWebtoon'; export { default as TuMangaOnlineHentai } from './TuMangaOnlineHentai'; @@ -431,6 +434,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRCOM } from './WebtoonTRCOM'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhiteCloudPavilion } from './WhiteCloudPavilion'; export { default as WIBTranslation } from './WIBTranslation'; @@ -627,7 +632,6 @@ export { default as MagKan } from './legacy/MagKan'; export { default as Manamoa } from './legacy/Manamoa'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga99 } from './legacy/Manga99'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaArab } from './legacy/MangaArab'; @@ -706,7 +710,6 @@ export { default as MangaToro } from './legacy/MangaToro'; export { default as MangaToroJA } from './legacy/MangaToroJA'; export { default as MangaToroVI } from './legacy/MangaToroVI'; export { default as MangaTownOnline } from './legacy/MangaTownOnline'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaVadisi } from './legacy/MangaVadisi'; export { default as Mangaz } from './legacy/Mangaz'; export { default as MangaZukiArchive } from './legacy/MangaZukiArchive'; @@ -878,7 +881,6 @@ export { default as Toonkor } from './legacy/Toonkor'; export { default as ToonSarang } from './legacy/ToonSarang'; export { default as TrueColorsScan } from './legacy/TrueColorsScan'; export { default as TruyenChon } from './legacy/TruyenChon'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TruyenTranhtuan } from './legacy/TruyenTranhtuan'; export { default as TsubasaSociety } from './legacy/TsubasaSociety'; export { default as Tsumino } from './legacy/Tsumino'; @@ -909,8 +911,6 @@ export { default as Webmangatr } from './legacy/Webmangatr'; export { default as WebNovel } from './legacy/WebNovel'; export { default as WebNovelLive } from './legacy/WebNovelLive'; export { default as WeComics } from './legacy/WeComics'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WhimSubs } from './legacy/WhimSubs'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; diff --git a/web/src/engine/websites/legacy/WeLoMa.ts b/web/src/engine/websites/legacy/WeLoMa.ts deleted file mode 100755 index 15850f540d..0000000000 --- a/web/src/engine/websites/legacy/WeLoMa.ts +++ /dev/null @@ -1,112 +0,0 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; -import icon from './WeLoMa.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; - -export default class extends DecoratableMangaScraper { - - public constructor() { - super('weloma', `WeLoMa`, 'https://weloma.art' /*, Tags.Language.English, Tags ... */); - } - - public override get Icon() { - return icon; - } -} - -// Original Source -/* -class WeLoMa extends FlatManga { - - constructor() { - super(); - super.id = 'weloma'; - super.label = 'WeLoveManga'; - this.tags = ['manga', 'hentai', 'raw', 'japanese']; - this.url = 'https://weloma.net'; - this.path = '/list-manga.html'; - this.requestOptions.headers.set('x-referer', this.url); - - this.queryMangaTitle = 'ul.manga-info h3'; - this.queryMangas = 'div.card-body div.series-title a'; - this.queryChapters = 'ul.list-chapters > a'; - this.queryChapterTitle = 'div.chapter-name'; - this.queryPages = 'div.chapter-content embed'; - } - - async _initializeConnector() { - for (let path of [this.path, '/0/']) { - const uri = new URL(path, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, '', 30000, true); - } - } - - async _getMangas() { - let mangaList = []; - const uri = new URL(this.path, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'ul.pagination li:nth-last-of-type(2) a'); - const pageCount = parseInt(data[0].text.trim()); - for (let page = 1; page <= pageCount; page++) { - let mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - await this.wait(5000); - } - return mangaList; - } - - async _getMangasFromPage(page) { - const uri = new URL(this.path, this.url); - uri.searchParams.set('page', page); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryMangas); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } - - async _getChapters(manga) { - const script = ` - new Promise(resolve => { - const chapters = [...document.querySelectorAll('ul.list-chapters > a')].map(element => { - return { - id: element.pathname, - title: element.title - }; - }); - resolve(chapters); - }); - `; - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, script); - } - - async _getPages(chapter) { - const uri = new URL(chapter.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryPages); - return data.map(element => { - const link = [...element.attributes] - .filter(attribute => !['src', 'class', 'alt'].includes(attribute.name)) - .map(attribute => { - try { - return atob(attribute.value.trim()); - } catch (_) { - return attribute.value.trim(); - } - }) - .find(value => { - return /^http/.test(value); - }); - return this.createConnectorURI(this.getAbsolutePath(link || element, request.url)); - }); - } -} -*/ \ No newline at end of file diff --git a/web/src/engine/websites/legacy/WeLoveManga.ts b/web/src/engine/websites/legacy/WeLoveManga.ts deleted file mode 100755 index f2b30c1796..0000000000 --- a/web/src/engine/websites/legacy/WeLoveManga.ts +++ /dev/null @@ -1,111 +0,0 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; -import icon from './WeLoveManga.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; - -export default class extends DecoratableMangaScraper { - - public constructor() { - super('lovehug', `WeloveManga`, 'https://welovemanga.one' /*, Tags.Language.English, Tags ... */); - } - - public override get Icon() { - return icon; - } -} - -// Original Source -/* -class WeLoveManga extends FlatManga { - - constructor() { - super(); - super.id = 'lovehug'; - super.label = 'WeLoveManga'; - this.tags = [ 'manga', 'hentai', 'raw', 'japanese' ]; - this.url = 'https://welovemanga.net'; - this.path = '/manga-list.html'; - this.requestOptions.headers.set('x-referer', this.url); - - this.queryMangaTitle = 'ul.manga-info h3'; - this.queryMangas = 'div.card-body div.series-title a'; - this.queryChapters = 'ul.list-chapters > a'; - this.queryChapterTitle = 'div.chapter-name'; - } - - async _initializeConnector() { - for(let path of [this.path, '/0/0/']) { - const uri = new URL(path, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, '', 30000, true); - } - } - - async _getMangas() { - let mangaList = []; - const uri = new URL(this.path, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'ul.pagination li:nth-last-of-type(2) a'); - const pageCount = parseInt(data[0].text.trim()); - for(let page = 1; page <= pageCount; page++) { - let mangas = await this._getMangasFromPage(page); - mangaList.push(...mangas); - await this.wait(5000); - } - return mangaList; - } - - async _getMangasFromPage(page) { - const uri = new URL(this.path, this.url); - uri.searchParams.set('page', page); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryMangas); - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.text.trim() - }; - }); - } - - async _getChapters(manga) { - const script = ` - new Promise(resolve => { - const chapters = [...document.querySelectorAll('ul.list-chapters > a')].map(element => { - return { - id: element.pathname, - title: element.title - }; - }); - resolve(chapters); - }); - `; - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - return Engine.Request.fetchUI(request, script); - } - - async _getPages(chapter) { - const uri = new URL(chapter.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, this.queryPages); - return data.map(element => { - const link = [ ...element.attributes] - .filter(attribute => !['src', 'class', 'alt'].includes(attribute.name)) - .map(attribute => { - try { - return atob(attribute.value.trim()); - } catch(_) { - return attribute.value.trim(); - } - }) - .find(value => { - return /^http/.test(value); - }); - return this.createConnectorURI(this.getAbsolutePath(link || element, request.url)); - }); - } -} -*/ \ No newline at end of file From a735982db991dced4bdbc7806abc30ee0740ad3a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Oct 2023 13:16:46 +0200 Subject: [PATCH 10/83] fix spacing --- web/src/engine/websites/Manga33.ts | 4 ++-- web/src/engine/websites/Manga33_e2e.ts | 4 ++-- web/src/engine/websites/MangaTR_e2e.ts | 2 +- web/src/engine/websites/TruyenTranhLH_e2e.ts | 2 +- web/src/engine/websites/WeLoveManga_e2e.ts | 2 +- 5 files changed, 7 insertions(+), 7 deletions(-) diff --git a/web/src/engine/websites/Manga33.ts b/web/src/engine/websites/Manga33.ts index e7a5603aa1..0ed2f251c0 100644 --- a/web/src/engine/websites/Manga33.ts +++ b/web/src/engine/websites/Manga33.ts @@ -4,14 +4,14 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/www\.manga33\.com\/manga\/\S+\.html$/, FlatManga.queryMangaTitle) +@Common.MangaCSS(/^https?:\/\/www\.manga333\.com\/manga\/\S+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('manga33', `Manga33`, 'https://www.manga33.com', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); + super('manga33', `Manga33`, 'https://www.manga333.com', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); } public override get Icon() { diff --git a/web/src/engine/websites/Manga33_e2e.ts b/web/src/engine/websites/Manga33_e2e.ts index 39b24dc38d..2cee162175 100644 --- a/web/src/engine/websites/Manga33_e2e.ts +++ b/web/src/engine/websites/Manga33_e2e.ts @@ -6,8 +6,8 @@ const config = { title: 'Manga33' }, container: { - url: 'https://www.manga33.com/manga/yuan-zun.html', - id: '/manga/yuan-zun.html' , + url: 'https://www.manga333.com/manga/yuan-zun.html', + id: '/manga/yuan-zun.html', title: 'Yuan Zun' }, child: { diff --git a/web/src/engine/websites/MangaTR_e2e.ts b/web/src/engine/websites/MangaTR_e2e.ts index 6a91f71653..19f11d40f3 100644 --- a/web/src/engine/websites/MangaTR_e2e.ts +++ b/web/src/engine/websites/MangaTR_e2e.ts @@ -7,7 +7,7 @@ const config = { }, container: { url: 'https://manga-tr.com/manga-mairimashita-iruma-kun.html', - id: '/manga-mairimashita-iruma-kun.html' , + id: '/manga-mairimashita-iruma-kun.html', title: 'Mairimashita! Iruma-kun' }, child: { diff --git a/web/src/engine/websites/TruyenTranhLH_e2e.ts b/web/src/engine/websites/TruyenTranhLH_e2e.ts index 8712aa67b3..3e358c4553 100644 --- a/web/src/engine/websites/TruyenTranhLH_e2e.ts +++ b/web/src/engine/websites/TruyenTranhLH_e2e.ts @@ -7,7 +7,7 @@ const config = { }, container: { url: 'https://truyentranhlh.net/truyen-tranh/tho-ren-huyen-thoai', - id: '/truyen-tranh/tho-ren-huyen-thoai' , + id: '/truyen-tranh/tho-ren-huyen-thoai', title: 'Thợ Rèn Huyền Thoại' }, child: { diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts index 47a98fd8ff..8bbbe40ba9 100644 --- a/web/src/engine/websites/WeLoveManga_e2e.ts +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -9,7 +9,7 @@ const config = { url: 'https://welovemanga.one/1067/', id: '/1067/', title: 'TONO KANRI O SHITE MIYOU', - timeout : 15000 + timeout: 15000 }, child: { id: '/read-tono-kanri-o-shite-miyou-raw-chapter-65.2.html', From 50a870829db1d3adcaf36f075c3baa5fdce25d0f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Oct 2023 13:19:26 +0200 Subject: [PATCH 11/83] lovehug => welovemanga --- web/src/engine/websites/WeLoveManga.ts | 2 +- web/src/engine/websites/WeLoveManga_e2e.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 2a35d67abf..89ebe989d0 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -28,7 +28,7 @@ const chapterScript = ` export default class extends DecoratableMangaScraper { public constructor() { - super('lovehug', `WeloveManga`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); + super('welovemanga', `WeloveManga`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts index 8bbbe40ba9..7994bfe7c0 100644 --- a/web/src/engine/websites/WeLoveManga_e2e.ts +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -2,7 +2,7 @@ const config = { plugin: { - id: 'lovehug', + id: 'welovemanga', title: 'WeloveManga' }, container: { From bc1f47eb02959a6c61807d1a5395c2594785650d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Oct 2023 14:06:44 +0200 Subject: [PATCH 12/83] use new error in decorator --- web/src/engine/websites/decorators/FlatManga.ts | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index acc25e5003..82943cba8a 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,7 +1,7 @@ import { FetchCSS, FetchRequest } from "../../FetchProvider"; import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; -import type * as Common from './Common'; +import * as Common from './Common'; export function MangaLabelExtractor(element: HTMLElement) { let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; @@ -60,9 +60,8 @@ export const queryPages = [ */ export function ChaptersSinglePageCSS(query = queryChapters) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - if (context && context.kind !== 'class') { - throw new Error(context.name); - } + Common.ThrowOnUnsupportedDecoratorContext(context); + return class extends ctor { public async FetchChapters(this: MangaScraper, manga: Manga): Promise { return FetchChaptersSinglePageCSS.call(this, manga, query); @@ -143,9 +142,8 @@ export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapt */ export function PagesSinglePageCSS(query : string = queryPages, excludes : RegExp[] = DefaultExcludes) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - if (context && context.kind !== 'class') { - throw new Error(context.name); - } + Common.ThrowOnUnsupportedDecoratorContext(context); + return class extends ctor { public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { return FetchPagesSinglePageCSS.call(this, chapter, query, excludes); From 90421843094fd186338668ce7047c104964de87e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 23 Oct 2023 17:58:55 +0200 Subject: [PATCH 13/83] Update _index.ts --- web/src/engine/websites/_index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 2d4b4b0867..488ae56614 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -168,6 +168,7 @@ export { default as MagicalTranslators } from './MagicalTranslators'; export { default as MaID } from './MaID'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga347 } from './Manga347'; export { default as Manga365 } from './Manga365'; @@ -247,6 +248,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; export { default as MangaWeebs } from './MangaWeebs'; @@ -420,6 +422,7 @@ export { default as TopToon } from './TopToon'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TRWebtoon } from './TRWebtoon'; export { default as Tsumino } from './Tsumino'; @@ -440,6 +443,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRCOM } from './WebtoonTRCOM'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -619,7 +624,6 @@ export { default as MagKan } from './legacy/MagKan'; export { default as Manamoa } from './legacy/Manamoa'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga99 } from './legacy/Manga99'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaArab } from './legacy/MangaArab'; @@ -693,7 +697,6 @@ export { default as MangaToro } from './legacy/MangaToro'; export { default as MangaToroJA } from './legacy/MangaToroJA'; export { default as MangaToroVI } from './legacy/MangaToroVI'; export { default as MangaTownOnline } from './legacy/MangaTownOnline'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaVadisi } from './legacy/MangaVadisi'; export { default as MangaZukiArchive } from './legacy/MangaZukiArchive'; export { default as MangaZukimobi } from './legacy/MangaZukimobi'; @@ -843,7 +846,6 @@ export { default as Toonkor } from './legacy/Toonkor'; export { default as ToonSarang } from './legacy/ToonSarang'; export { default as TrueColorsScan } from './legacy/TrueColorsScan'; export { default as TruyenChon } from './legacy/TruyenChon'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TruyenTranhtuan } from './legacy/TruyenTranhtuan'; export { default as TsubasaSociety } from './legacy/TsubasaSociety'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; @@ -870,8 +872,6 @@ export { default as WebComicGamma } from './legacy/WebComicGamma'; export { default as Webmangatr } from './legacy/Webmangatr'; export { default as WebNovelLive } from './legacy/WebNovelLive'; export { default as WeComics } from './legacy/WeComics'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 459522f0570adf6f8c239672859dfc66cca6ab5b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 2 Nov 2023 10:18:09 +0100 Subject: [PATCH 14/83] Update _index.ts --- web/src/engine/websites/_index.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 11d3cb7440..5d3c0a9199 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -180,6 +180,7 @@ export { default as MagicalTranslators } from './MagicalTranslators'; export { default as MaID } from './MaID'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga347 } from './Manga347'; export { default as Manga365 } from './Manga365'; @@ -261,6 +262,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; export { default as MangaWeebs } from './MangaWeebs'; @@ -435,6 +437,7 @@ export { default as TopToon } from './TopToon'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TRWebtoon } from './TRWebtoon'; export { default as Tsumino } from './Tsumino'; @@ -456,6 +459,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRCOM } from './WebtoonTRCOM'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -560,7 +565,6 @@ export { default as MagaParkPublisher } from './legacy/MagaParkPublisher'; export { default as MagKan } from './legacy/MagKan'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaArab } from './legacy/MangaArab'; export { default as MangaCat } from './legacy/MangaCat'; @@ -596,7 +600,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -678,7 +681,6 @@ export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; export { default as ToonSarang } from './legacy/ToonSarang'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TruyenTranhtuan } from './legacy/TruyenTranhtuan'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as TuMangaOnline } from './legacy/TuMangaOnline'; @@ -691,8 +693,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 8bbb9da4552aa703d53c7248035f87969b28cc77 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 8 Nov 2023 17:08:54 +0100 Subject: [PATCH 15/83] better regexp --- web/src/engine/websites/Manga33.ts | 2 +- web/src/engine/websites/MangaTR.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/Manga33.ts b/web/src/engine/websites/Manga33.ts index 0ed2f251c0..dcca8a9652 100644 --- a/web/src/engine/websites/Manga33.ts +++ b/web/src/engine/websites/Manga33.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/www\.manga333\.com\/manga\/\S+\.html$/, FlatManga.queryMangaTitle) +@Common.MangaCSS(/^https?:\/\/www\.manga333\.com\/manga\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 4c31e5cf7c..ff834a9de2 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -8,7 +8,7 @@ function MangaLabelExtractor(element: HTMLTitleElement) { return element.text.split(' - ')[0].trim(); } -@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/manga-\S+\.html$/, 'body title', MangaLabelExtractor) +@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/manga-[^/]+\.html$/, 'body title', MangaLabelExtractor) @Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) @FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index f87dc2be12..1c7f5785e5 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/weloma\.art\/\S+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangaCSS(/^https?:\/\/weloma\.art\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) From 0616125d5b84f26c9b69b246fdcdb6026fa6fe03 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 8 Nov 2023 17:11:55 +0100 Subject: [PATCH 16/83] Update FlatManga.ts --- web/src/engine/websites/decorators/FlatManga.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 82943cba8a..be92d83940 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -17,8 +17,6 @@ export function MangaExtractor(anchor: HTMLAnchorElement) { export const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; export const pathSinglePageManga = '/manga-list.html?listType=allABC'; -export const queryChapterLanguage = 'ul.manga-info h1 span.flag-icon'; -export const queryChapterLanguageClassRX = /flag-icon-([a-zA-Z]+)/; export const queryMangaTitle = [ 'li:last-of-type span[itemprop="name"]', From cc0f73f3cd51600f3f3860db48b31e6d3caed15c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 12 Nov 2023 17:03:15 +0100 Subject: [PATCH 17/83] use origin placeholder --- web/src/engine/websites/Manga33.ts | 2 +- web/src/engine/websites/MangaTR.ts | 2 +- web/src/engine/websites/TruyenTranhLH.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 2 +- web/src/engine/websites/WeLoveManga.ts | 2 +- web/src/engine/websites/legacy/KissAway.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/Manga33.ts b/web/src/engine/websites/Manga33.ts index dcca8a9652..1325e4d5b8 100644 --- a/web/src/engine/websites/Manga33.ts +++ b/web/src/engine/websites/Manga33.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/www\.manga333\.com\/manga\/[^/]+\.html$/, FlatManga.queryMangaTitle) +@Common.MangaCSS(/^{origin}\/manga\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index ff834a9de2..72017a12eb 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -8,7 +8,7 @@ function MangaLabelExtractor(element: HTMLTitleElement) { return element.text.split(' - ')[0].trim(); } -@Common.MangaCSS(/^https?:\/\/manga-tr\.com\/manga-[^/]+\.html$/, 'body title', MangaLabelExtractor) +@Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, 'body title', MangaLabelExtractor) @Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) @FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() diff --git a/web/src/engine/websites/TruyenTranhLH.ts b/web/src/engine/websites/TruyenTranhLH.ts index 2a39815aa6..9e4062a5fe 100644 --- a/web/src/engine/websites/TruyenTranhLH.ts +++ b/web/src/engine/websites/TruyenTranhLH.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/truyentranhlh\.net\/truyen-tranh\/[^/]+$/, 'span.series-name') +@Common.MangaCSS(/^{origin}\/truyen-tranh\/[^/]+$/, 'span.series-name') @Common.MangasMultiPageCSS('/danh-sach?page={page}', FlatManga.queryMangas) @FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index 1c7f5785e5..2b5e82cdc1 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -@Common.MangaCSS(/^https?:\/\/weloma\.art\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangaCSS(/^{origin}\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 89ebe989d0..abd1e58d52 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -20,7 +20,7 @@ const chapterScript = ` }); `; -@Common.MangaCSS(/^https?:\/\/welovemanga\.one\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangaCSS(/^{origin}\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() diff --git a/web/src/engine/websites/legacy/KissAway.ts b/web/src/engine/websites/legacy/KissAway.ts index a073456c62..92a4ef6d5c 100755 --- a/web/src/engine/websites/legacy/KissAway.ts +++ b/web/src/engine/websites/legacy/KissAway.ts @@ -40,7 +40,7 @@ const pageScript = ` //TODO Implement at request level a BYPASS for this DDOSS protection //its not triggered on main page but on manga page -@Common.MangaCSS(/^https?:\/\/klz9\.com\/\S+\.html$/, FlatManga.queryMangaTitle) +@Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) @Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() From a3f2d06d355f54473b2037a3a357fddd67d5dcd0 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 5 Dec 2023 13:46:53 +0100 Subject: [PATCH 18/83] Flatmanga : code improvement && use distinct --- web/src/engine/websites/Manga33.ts | 7 +------ web/src/engine/websites/Manga33_e2e.ts | 14 +++++++------- web/src/engine/websites/MangaTR.ts | 16 +++++++++------- web/src/engine/websites/WeLoMa.ts | 2 +- web/src/engine/websites/WeLoveManga.ts | 9 +++------ web/src/engine/websites/decorators/FlatManga.ts | 2 +- 6 files changed, 22 insertions(+), 28 deletions(-) diff --git a/web/src/engine/websites/Manga33.ts b/web/src/engine/websites/Manga33.ts index 1325e4d5b8..7472a7976e 100644 --- a/web/src/engine/websites/Manga33.ts +++ b/web/src/engine/websites/Manga33.ts @@ -20,11 +20,6 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga, FlatManga.queryChapters); - const fixedChapters = chapters.map(chapter => new Chapter(this, manga, chapter.Identifier.replace(/-\d+.html$/, '-all.html'), chapter.Title)); - const uniqueChapters = fixedChapters.filter( - (obj, index) => - fixedChapters.findIndex((item) => item.Identifier === obj.Identifier) === index - ); - return uniqueChapters; + return chapters.map(chapter => new Chapter(this, manga, chapter.Identifier.replace(/-\d+.html$/, '-all.html'), chapter.Title)); } } diff --git a/web/src/engine/websites/Manga33_e2e.ts b/web/src/engine/websites/Manga33_e2e.ts index 2cee162175..d867d8c0e9 100644 --- a/web/src/engine/websites/Manga33_e2e.ts +++ b/web/src/engine/websites/Manga33_e2e.ts @@ -6,18 +6,18 @@ const config = { title: 'Manga33' }, container: { - url: 'https://www.manga333.com/manga/yuan-zun.html', - id: '/manga/yuan-zun.html', - title: 'Yuan Zun' + url: 'https://www.manga333.com/manga/black-clover.html', + id: '/manga/black-clover.html', + title: 'Black Clover' }, child: { - id: '/manga/yuan-zun-510-all.html', - title: 'Chapter 510' + id: '/manga/black-clover-368-all.html', + title: 'Chapter 368' }, entry: { index: 0, - size: 191_444, - type: 'image/jpeg' + size: 516_711, + type: 'image/jpeg', } }; diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 72017a12eb..51a03a7733 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import { FetchCSS, FetchRequest, FetchWindowScript } from '../FetchProvider'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; + function MangaLabelExtractor(element: HTMLTitleElement) { return element.text.split(' - ')[0].trim(); } @@ -12,6 +13,7 @@ function MangaLabelExtractor(element: HTMLTitleElement) { @Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) @FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() + export default class extends DecoratableMangaScraper { public constructor() { super('mangatr', `Manga-TR`, 'https://manga-tr.com', Tags.Language.Turkish, Tags.Media.Manga, Tags.Source.Aggregator); @@ -29,13 +31,13 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const chapterList = []; for (let page = 1, run = true; run; page++) { - const chapters = await this._getChaptersFromPage(manga, page); + const chapters = await this.getChaptersFromPage(manga, page); chapters.length > 0 ? chapterList.push(...chapters) : run = false; } - return chapterList; + return chapterList.distinct(); } - private async _getChaptersFromPage(manga: Manga, page: number): Promise{ - const mangaslug = manga.Identifier.match(/manga-([\S]+)\.html/)[1]; + private async getChaptersFromPage(manga: Manga, page: number): Promise{ + const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); const request = new FetchRequest(url.href, { method: 'POST', @@ -47,9 +49,9 @@ export default class extends DecoratableMangaScraper { }); const data = await FetchCSS(request, 'table.table tr td.table-bordered:first-of-type > a'); - const esc = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); - const reg = new RegExp(esc, 'i'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(reg, '').trim())); + const escapedMangaTitle = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); + const regexp = new RegExp(escapedMangaTitle, 'i'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(regexp, '').trim())); } } \ No newline at end of file diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index 2b5e82cdc1..0424e41eb2 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -12,7 +12,7 @@ import * as FlatManga from './decorators/FlatManga'; export default class extends DecoratableMangaScraper { public constructor() { - super('weloma', `WeLoMa`, 'https://weloma.art', Tags.Media.Manga, Tags.Language.Japanese); + super('weloma', `WeLoMa`, 'https://weloma.art', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Aggregator); } public override get Icon() { diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index abd1e58d52..496eacaca1 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -15,8 +15,7 @@ const chapterScript = ` title : chapter.title }; }); - const uniqueChapters = chapters.filter((obj, index) =>chapters.findIndex((item) => item.id === obj.id) === index ); - resolve(uniqueChapters); + resolve(chapters); }); `; @@ -36,16 +35,14 @@ export default class extends DecoratableMangaScraper { } public override async FetchPages(chapter: Chapter): Promise { - let url = new URL(chapter.Identifier, this.URI); + const url = new URL(chapter.Identifier, this.URI); let request = new FetchRequest(url.href, { headers: { 'Referer': this.URI.href, } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - - url = new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI); - request = new FetchRequest(url.href, { + request = new FetchRequest(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI).href, { headers: { 'Referer': this.URI.href, } diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index be92d83940..9e90963cf5 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -93,7 +93,7 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang title = title.replace(/^\s*-\s*/, ''); title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); return new Chapter(this, manga, id, title); - }); + }).distinct(); } /********************************************** From 52cc8335d9036f29cfde9086a283a7fa71dc5d54 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 5 Dec 2023 14:39:56 +0100 Subject: [PATCH 19/83] add KLManga (old Kissaway) --- .../engine/transformers/BookmarkConverter.ts | 1 + .../transformers/BookmarkConverter_test.ts | 1 + .../{legacy/KissAway.ts => KLManga.ts} | 32 +++++------------- web/src/engine/websites/KLManga.webp | Bin 0 -> 2064 bytes web/src/engine/websites/KLManga_e2e.ts | 25 ++++++++++++++ web/src/engine/websites/_index.ts | 2 +- web/src/engine/websites/legacy/KissAway.webp | Bin 1196 -> 0 bytes 7 files changed, 37 insertions(+), 24 deletions(-) rename web/src/engine/websites/{legacy/KissAway.ts => KLManga.ts} (54%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/KLManga.webp create mode 100644 web/src/engine/websites/KLManga_e2e.ts delete mode 100755 web/src/engine/websites/legacy/KissAway.webp diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index 60d900238b..b4142dac8a 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -15,6 +15,7 @@ const legacyWebsiteIdentifierMap = { 'heavenmanga': 'beetoon', // (future zbulu PR) 'heavenmanga2': 'heavenmanga', // (future zbulu PR) 'kisscomic': 'readcomiconline', + 'kissaway': 'klmanga', 'kumascans': 'retsu', 'lyrascans': 'quantumscans', //https://www.mangaupdates.com/groups.html?id=35005683580 'Formerly known as LyraScans' 'lovehug': 'welovemanga', diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index 7fb7789f45..57c53bcfb2 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -68,6 +68,7 @@ describe('BookmarkConverter', () => { { sourceID: 'firstkiss', targetID: 'likemanga'}, { sourceID: 'gateanimemanga', targetID: 'gatemanga' }, { sourceID: 'kisscomic', targetID: 'readcomiconline' }, + { sourceID: 'kissaway', targetID: 'klmanga'}, { sourceID: 'kumascans', targetID: 'retsu' }, { sourceID: 'heavenmanga', targetID: 'beetoon' }, // (future zbulu PR) { sourceID: 'heavenmanga2', targetID: 'heavenmanga' }, // (future zbulu PR) diff --git a/web/src/engine/websites/legacy/KissAway.ts b/web/src/engine/websites/KLManga.ts old mode 100755 new mode 100644 similarity index 54% rename from web/src/engine/websites/legacy/KissAway.ts rename to web/src/engine/websites/KLManga.ts index 92a4ef6d5c..241e134124 --- a/web/src/engine/websites/legacy/KissAway.ts +++ b/web/src/engine/websites/KLManga.ts @@ -1,9 +1,8 @@ -import { Tags } from '../../Tags'; -import icon from './KissAway.webp'; -import { type Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as FlatManga from '../decorators/FlatManga'; -import { FetchRequest, FetchWindowScript } from '../../FetchProvider'; +import { Tags } from '../Tags'; +import icon from './KLManga.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; const chapterScript = ` new Promise(async resolve => { @@ -19,8 +18,7 @@ const chapterScript = ` title : chapter.title }; }); - const uniqueChapters = chapters.filter((obj, index) =>chapters.findIndex((item) => item.id === obj.id) === index ); - resolve(uniqueChapters); + resolve(chapters); }); `; @@ -32,37 +30,25 @@ const pageScript = ` const response = await fetch(uri); const data = await response.text(); const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('img.chapter-img')]; + const nodes = [...dom.querySelectorAll('img.chapter-img[alt*="Page"]')]; resolve(nodes.map(picture => picture.src)); }); `; -//TODO Implement at request level a BYPASS for this DDOSS protection -//its not triggered on main page but on manga page - @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) +@Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { - private ddosProtectionPassed = false; - public constructor() { - super('kissaway', `KLManga`, 'https://klz9.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); + super('klmanga', `KLManga`, 'https://klz9.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { return icon; } - public override async FetchChapters(manga: Manga): Promise { - if (!this.ddosProtectionPassed) { - await FetchWindowScript(new FetchRequest(new URL(manga.Identifier, this.URI).href), '', 5000); - this.ddosProtectionPassed = true; - } - return Common.FetchChaptersSinglePageJS.call(this, manga, chapterScript, 1000); - } - } diff --git a/web/src/engine/websites/KLManga.webp b/web/src/engine/websites/KLManga.webp new file mode 100644 index 0000000000000000000000000000000000000000..d61638e7fa9e8d41543c05e5117ff25e7230718e GIT binary patch literal 2064 zcmV+r2=Dh&Nk&Ep2mkJq!*gr9lv%JKjY zy;f`v3R}MSLSr8zIKMX&m%|6QeC^`WE(CK9+n&K<3b@Ymcb^?$UWp^fr&Gi$hj*7= zzp!JNb3C!grjan4oElbyWD>_(0>_?K7i*FI>XYv!25(+901) zfX0zKR~NA0n~tZ8p=%zwaOT%92gvG^6m0SFi&Ht~B+5FH>kluqH{br8`XyQLi!a>| zJusOlEsni4o5D&Vt4n4~67Hw*?Kt0t#$n7;Aq(h6WE)dht8gz8f8)_(5xi7}X0BI-AVy=Dz&B*$*u zoCZ%LVZvc|x|)omFFexNpuwa~VXs|{<1b$u55R&Hf!~|K%DHgi_3jWW)NsUD^k%4h z>mC%1CQ*t!ZC81HEibnJtRY$!}n^;ZChfQQ<48Ic*D9altl!36_X`7-U4OBGzUb{`i179udwq~O- z)c|2P=|%(esA|wx=l=wxe$GI#>{pXzVQLB^)?Eiy%AAdSvq`+W2~`dM`NoOv;#?yJ zQKXGZz`LIgxb)y8rb(H|hl#9$!OAZyd)>R|B0vm1&aB*1_vte6fRq|_3L`DLcu5m+ z2ALtNW(H}}!a)F`T1?}Oe7==VQ+IE$&=PXgZrXWgZLYg;5v#+{=0`uBI(6jGtV~z{ zAywJ^;Lr8ma*I$0nE(3StznTYoIHK<$XvofZy+H7=I9R?XG}2L+S^%Q%L-F#?(mVN zZnvF?gBCzI(isvgSZ$I_eq;6DzgPO9*lCWcn_Re0W_R@(H$B)doP#~L_VStc?g<*exXJc(U z%g2@+=^pP8h}1AMkV6oL+nXD!8~xdHNhJVQP&gnM1ONaq5&)e6DnI~006uLjkVT{- zp_mK?d_V@owg6xauXd~KZB+j6xF~P?ADoWbPcfYfH*@iG!Sea74MEo!(elbBTOO`2G!NNdkjsJC(i7(QJ4tIkQ(#{I#SESC#UQ)hf zGVoSEhWTHW`#Y^RR}3QsxqgX|(*i`zEcCx*vp<8ZfB^pfr8XX_w+YZMM*at^{N7Vc zD0a1;oHGA;X21D_VC^|EyNpc)s4o>T5*3;{HFcCF&)xIiHGhNG&7pkPl7&9Ef$ouU zZ}V)0OJOmNb8UB!A@#CDRZJ~Tv>Z3^AaYr0knJDBV;H%g>PZKa zZC+m~a44-nwvHrNz{mSbH!P|*zS{%Q%p=K!1s2eRT)lz@jwSvkXSyNeDipqXQ0c2S z33sPJvx#DRDVHwa*dMl6i=ZM{Rs@A&YFH=0s&biG&1hr}|7t@1ezW(SlfHm>zs&!* z3Kmo`|CYWnSGX28w_dUv`2OSIb~n~IJDk@KPuZ_c8s`$m6u?9nISHmF6V_*4 z2SGZIpin=%v&4=sd_upkFY|1g5AP{B!WNa?Vyq*4A6e((+6*^>ENxcrzKlrfXCAJv{j{Q0 z fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 883848ddd6..04bc145ae4 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -186,6 +186,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikAV } from './KomikAV'; @@ -602,7 +603,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; diff --git a/web/src/engine/websites/legacy/KissAway.webp b/web/src/engine/websites/legacy/KissAway.webp deleted file mode 100755 index 45deb2ab419e5a12d43e73c55c9e1d6161384a01..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1196 zcmV;d1XKG`Nk&Gb1ONb6MM6+kP&il$0000G0000#002J#06|PpNGSsV01c3!?VpoI z{}~tv0=8$BOq%I+d%Hl+y%*@s^eSdW%#+16uoFRMwu{UKB4Pp{Q*2n}`JJuh*=lhL z?grn!o*nMB`yu0yOKds|(^Wh6I@f(R5IQm0f4Z+y2K@rfa$F;~%e8guxkLiB=N zDw{;bad6dQVj`GW&h`u%au^?54y6w2?D=8BvqMu$FJAUoDj-{|+RM-HzkYMcL{?<} zQ7wu%WRI|BI*%>?b34hVxUi~+DNGm}D|7bn)E#7ijD`EPI{}kd=;qpW(`8~Dq&(eF zVgY$XT75S?dY_6hjHlDV2y%)@`F^GQp8a2OVIvqqe$_^!a^w#Fhb-JzMv!N{aX)Rk z$-mJ2YAuF*tL5G6)3*2 zJF#m_a}Kg1m15tjrXVk->P^{>B?5DHoLJN>47kKHHb8P^mJx zbh9{;ix^WvE`@;fcSMmYO$G*$Dq-JDU8-U9wNjAkM{riRrMm4M(vno)y**mS67jy* z)=W#HFpB#jaU}9%JG@aTmWF$&$$U&zB#9VxIOcBb*jN&N>uUhr04-~h#AnC`h^{)% zO)LeE-p*hE-rBqG7*a5QuK)nR{MV0H6baI^kN40YB79@bQItF3wIdz=nq2z!riOAR z;=|Cyf8*@)aIH>qmh?_^1pgH6)9c-`nyXR&RgJ)ZCT=sm-_Ub3Y&Df4{P(~;sx%sE zZbq$EP=GPn`)=ianV?*Vq~8n(8b_q>kJ8<`hH@a{-YcbmU~IwM=JnbpRVJ2thbOfn zWIAw9hxXixfhWS*Sv%ATWSq1=`_^N})G*3O@Hp~6Mka#H1-pFn`u_7}Tg931(e2sW zy?Z)_3GyWL_d3X-)UogwJoLSek7f!8CM;O%Du}U4%yP*t=tO}u8UDEa-jCvxYc_@) z@~G?jH=#ypy!5*7tL&x>snL#6;$P&gn|0RR9H2mqY{DnI~006xJ`o=dqoqM^6; zssk_>2|yY6C1`upf7m_AG9|Kz=99a`wW4DJ%CN6#SN7>y5$gQLr25(V+de+6GG9Od z0RHkj-XgyjP1?NKON)}OE+`O%<>9|QjB%M1x%S~ccZRnCHbO%V#}Cak$%h&8oM5_J&kd)({R;9;h#z{&wLKj;_Y6z$+dL<@NCA zqj$J1?hhz?@XlzJlM!Pj0*9@#dO$IQGg)!VhW+ajL=7rA;KmysI5*q&T4##79GjR3 z;(0D~cy|boxXV1|lG<*9|1?#`lz*DmF(vEp!es-k(ksX@tP^do_9m4dKtxXWm~(!w z-Drbk6M4gA_QoJ9=^s{QBK6vhVOYSg7k=9B3x7HY+G_U`hw=a|NR+3J#xrG`VtXSG K^3%0wnvei+rAfO0 From 04fa722bc6c362d540d167acbe7d420581b74354 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 21 Dec 2023 14:25:57 +0100 Subject: [PATCH 20/83] add TruyenChapVn --- web/src/engine/websites/TruyenChapVn.ts | 37 ++++++++++++++++++++ web/src/engine/websites/TruyenChapVn.webp | Bin 0 -> 460 bytes web/src/engine/websites/TruyenChapVn_e2e.ts | 25 +++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 63 insertions(+) create mode 100644 web/src/engine/websites/TruyenChapVn.ts create mode 100644 web/src/engine/websites/TruyenChapVn.webp create mode 100644 web/src/engine/websites/TruyenChapVn_e2e.ts diff --git a/web/src/engine/websites/TruyenChapVn.ts b/web/src/engine/websites/TruyenChapVn.ts new file mode 100644 index 0000000000..aad297ff9d --- /dev/null +++ b/web/src/engine/websites/TruyenChapVn.ts @@ -0,0 +1,37 @@ +import { Tags } from '../Tags'; +import icon from './TruyenChapVn.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + return { + id: anchor.pathname, + title: anchor.text.replace(/\(chap.vn\)/i, '').trim() + }; +} + +function MangaLabelExtractor(element: HTMLElement) { + return element.textContent.replace(/\(chap.vn\)/i, '').trim(); +} + +@Common.MangaCSS(/^{origin}\/truyen\/[^/]+\/$/, 'div.page-header h1#tables', MangaLabelExtractor) +@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, MangaExtractor) +@Common.PagesSinglePageCSS('img.chapter-img') +@Common.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('truyenchapvn', `TruyenChapVn`, 'https://truyen.chap.vn', Tags.Language.Vietnamese, Tags.Media.Manga, Tags.Source.Aggregator); + } + + public override get Icon() { + return icon; + } + + public override async FetchChapters(manga: Manga): Promise { + const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga); + return chapters.map(chapter => new Chapter(this, manga, chapter.Identifier, chapter.Title.replace(/\(chap.vn\)/i, '').trim())); + } +} \ No newline at end of file diff --git a/web/src/engine/websites/TruyenChapVn.webp b/web/src/engine/websites/TruyenChapVn.webp new file mode 100644 index 0000000000000000000000000000000000000000..1c7d49f435413c0afb15a9c23d9123d97159b924 GIT binary patch literal 460 zcmV;-0WvaJxva2zyjAnUkWTw5{~;Avso$*ZVgv=!M$Z=X z^Q{o&x6)kzlP_f#)cC;fx$N`+0RFhdPjsJ741fG9Ss(tu_yhm-27koa{z0FgW@l~O z+eo7`S){S`9Ef(%SYkCLF}a^y-+y#zqi_Uw%XN9#LZNOmh1Q{bNl01w zh0ooTD{NxLwk28EXN4MzM56w3hMgu`GQXj$C!0p7(MBAcEhP7OH3<)YZbM)NtN&t1 zew_|YXkv>#X{5JGn_YJU@*T|>g;~R6-A2GZacW)r4%KcjtM1xvrdIdyJ~YGPfWB6E zV$0MDO0`A fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 04bc145ae4..d0617ea7a8 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -506,6 +506,7 @@ export { default as TopToon } from './TopToon'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TRWebtoon } from './TRWebtoon'; From 77b54527dc1d9cd53ee2363739f57796a31d291c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 21 Dec 2023 15:18:53 +0100 Subject: [PATCH 21/83] Update BookmarkConverter_test.ts --- web/src/engine/transformers/BookmarkConverter_test.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index 58e13db918..78764d4255 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -69,11 +69,9 @@ describe('BookmarkConverter', () => { { sourceID: 'firstkiss', targetID: 'likemanga' }, { sourceID: 'flamescans-org', targetID: 'flamecomics' }, { sourceID: 'gateanimemanga', targetID: 'gatemanga' }, - { sourceID: 'kisscomic', targetID: 'readcomiconline' }, - { sourceID: 'kissaway', targetID: 'klmanga'}, - { sourceID: 'kumascans', targetID: 'retsu' }, { sourceID: 'heavenmanga', targetID: 'beetoon' }, // (future zbulu PR) { sourceID: 'heavenmanga2', targetID: 'heavenmanga' }, // (future zbulu PR) + { sourceID: 'kissaway', targetID: 'klmanga' }, { sourceID: 'kisscomic', targetID: 'readcomiconline' }, { sourceID: 'kumascans', targetID: 'retsu' }, { sourceID: 'lovehug', targetID: 'welovemanga' }, From c032f3659760368f359522b4e48885e58f811171 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 5 Jan 2024 17:24:05 +0100 Subject: [PATCH 22/83] Update _index.ts --- web/src/engine/websites/_index.ts | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index e3eaf1c97a..d968669914 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -15,7 +15,6 @@ export { default as Anisamanga } from './Anisamanga'; export { default as AnshScans } from './AnshScans'; export { default as AnzManga } from './AnzManga'; export { default as ApollComics } from './ApollComics'; -export { default as ApollToons } from './ApollToons'; export { default as AquaManga } from './AquaManga'; export { default as ArcaneScans } from './ArcaneScans'; export { default as AresManga } from './AresManga'; @@ -45,7 +44,6 @@ export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; -export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; @@ -164,7 +162,6 @@ export { default as HikariScan } from './HikariScan'; export { default as Hinapyon } from './Hinapyon'; export { default as HiperCool } from './HiperCool'; export { default as Hiperdex } from './Hiperdex'; -export { default as HManhwa } from './HManhwa'; export { default as HniScanTrad } from './HniScanTrad'; export { default as HqNow } from './HqNow'; export { default as HunterScan } from './HunterScan'; @@ -402,6 +399,7 @@ export { default as MomoNoHanaScan } from './MomoNoHanaScan'; export { default as MonochromeScans } from './MonochromeScans'; export { default as MonoManga } from './MonoManga'; export { default as MoonWitchInLove } from './MoonWitchInLove'; +export { default as MundoManhwa } from './MundoManhwa'; export { default as NatsuID } from './NatsuID'; export { default as Nekomik } from './Nekomik'; export { default as NeoxScan } from './NeoxScan'; @@ -510,9 +508,11 @@ export { default as SheepMangaBroken } from './SheepMangaBroken'; export { default as ShinigamiID } from './ShinigamiID'; export { default as Shirakami } from './Shirakami'; export { default as ShonenJumpPlus } from './ShonenJumpPlus'; +export { default as ShonenJumpRookie } from './ShonenJumpRookie'; export { default as ShonenMagazine } from './ShonenMagazine'; export { default as ShootingStarScans } from './ShootingStarScans'; export { default as Shqqaa } from './Shqqaa'; +export { default as ShueishaMangaPlus } from './ShueishaMangaPlus'; export { default as SilenceScan } from './SilenceScan'; export { default as SilentSkyScans } from './SilentSkyScans'; export { default as SinensisScan } from './SinensisScan'; @@ -536,43 +536,50 @@ export { default as TCBScans } from './TCBScans'; export { default as Team1x1 } from './Team1x1'; export { default as TecnoScan } from './TecnoScan'; export { default as Tempestfansub } from './Tempestfansub'; +export { default as TempestScans } from './TempestScans'; export { default as TenshiID } from './TenshiID'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; +export { default as ToomTam } from './ToomTam'; export { default as ToonGod } from './ToonGod'; export { default as Toonily } from './Toonily'; -export { default as ToonilyNet } from './ToonilyNet'; -export { default as ToonLatino } from './ToonLatino'; export { default as TopComicPorno } from './TopComicPorno'; export { default as TopManhua } from './TopManhua'; export { default as TopManhuaNet } from './TopManhuaNet'; export { default as TopToon } from './TopToon'; +export { default as TortugaCeviri } from './TortugaCeviri'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; +export { default as TruyenTranhtuan } from './TruyenTranhtuan'; export { default as TRWebtoon } from './TRWebtoon'; export { default as Tsumino } from './Tsumino'; +export { default as TukangKomik } from './TukangKomik'; +export { default as TuMangaNet } from './TuMangaNet'; export { default as TuMangaOnlineHentai } from './TuMangaOnlineHentai'; export { default as TuManhwas } from './TuManhwas'; export { default as Turktoon } from './Turktoon'; -export { default as TvYManga } from './TvYManga'; export { default as UraSunday } from './UraSunday'; export { default as UzayManga } from './UzayManga'; +export { default as VerManhwa } from './VerManhwa'; +export { default as ViewComics } from './ViewComics'; export { default as ViyaFansub } from './ViyaFansub'; export { default as VNSharing } from './VNSharing'; export { default as VoidScans } from './VoidScans'; export { default as WantedTeam } from './WantedTeam'; +export { default as WarungKomik } from './WarungKomik'; export { default as WebAce } from './WebAce'; export { default as WebComicsApp } from './WebComicsApp'; export { default as WebNovel } from './WebNovel'; export { default as WebtoonHatti } from './WebtoonHatti'; export { default as WebtoonTR } from './WebtoonTR'; -export { default as WebtoonTRCOM } from './WebtoonTRCOM'; +export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; export { default as WeLoMa } from './WeLoMa'; @@ -588,6 +595,7 @@ export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; export { default as YaoiScan } from './YaoiScan'; @@ -595,9 +603,11 @@ export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as YugenMangasES } from './YugenMangasES'; export { default as YugenMangasPT } from './YugenMangasPT'; +export { default as YumeKomik } from './YumeKomik'; export { default as YuriVerso } from './YuriVerso'; export { default as Zebrack } from './Zebrack'; export { default as ZeroScans } from './ZeroScans'; +export { default as ZeurelScan } from './ZeurelScan'; export { default as ZinManga } from './ZinManga'; export { default as ZuiMH } from './ZuiMH'; // Legacy Websites @@ -671,7 +681,6 @@ export { default as MangaFoxFun } from './legacy/MangaFoxFun'; export { default as MangaFreak } from './legacy/MangaFreak'; export { default as MangaGo } from './legacy/MangaGo'; export { default as MangaHereFun } from './legacy/MangaHereFun'; -export { default as MangaHome } from './legacy/MangaHome'; export { default as MangaHub } from './legacy/MangaHub'; export { default as MangaKakalotFun } from './legacy/MangaKakalotFun'; export { default as MangaKu } from './legacy/MangaKu'; @@ -736,8 +745,6 @@ export { default as SakuraManga } from './legacy/SakuraManga'; export { default as ScanManga } from './legacy/ScanManga'; export { default as SelfManga } from './legacy/SelfManga'; export { default as ShinobiScans } from './legacy/ShinobiScans'; -export { default as ShonenJumpRookie } from './legacy/ShonenJumpRookie'; -export { default as ShueishaMangaPlus } from './legacy/ShueishaMangaPlus'; export { default as SixMH7 } from './legacy/SixMH7'; export { default as SixParkbbsClub } from './legacy/SixParkbbsClub'; export { default as SixParkbbsWeb } from './legacy/SixParkbbsWeb'; @@ -763,8 +770,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as ToonSarang } from './legacy/ToonSarang'; -export { default as TruyenTranhtuan } from './legacy/TruyenTranhtuan'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as TuMangaOnline } from './legacy/TuMangaOnline'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; @@ -782,7 +787,6 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YesMangasBR } from './legacy/YesMangasBR'; export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 0bf3faa207aa73d54cc3f71b1f91a5d286b3b964 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 16 Jan 2024 13:51:31 +0100 Subject: [PATCH 23/83] improve platform abstraction --- web/src/engine/websites/MangaTR.ts | 6 +++--- web/src/engine/websites/WeLoveManga.ts | 6 +++--- web/src/engine/websites/decorators/FlatManga.ts | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 51a03a7733..e887ff1147 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -1,7 +1,7 @@ import { Tags } from '../Tags'; import icon from './MangaTR.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; -import { FetchCSS, FetchRequest, FetchWindowScript } from '../FetchProvider'; +import { FetchCSS, FetchWindowScript } from '../platform/FetchProvider'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { public override async Initialize(): Promise { const uri = new URL('/manga-list.html', this.URI); - const request = new FetchRequest(uri.href); + const request = new Request(uri.href); return FetchWindowScript(request, `window.cookieStore.set('read_type', '1')`, 0, 30000); } @@ -39,7 +39,7 @@ export default class extends DecoratableMangaScraper { private async getChaptersFromPage(manga: Manga, page: number): Promise{ const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); - const request = new FetchRequest(url.href, { + const request = new Request(url.href, { method: 'POST', body: 'page=' + page, headers: { diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 496eacaca1..38b83ef1d1 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -3,7 +3,7 @@ import icon from './WeLoveManga.webp'; import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; const chapterScript = ` new Promise(async resolve => { @@ -36,13 +36,13 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { const url = new URL(chapter.Identifier, this.URI); - let request = new FetchRequest(url.href, { + let request = new Request(url.href, { headers: { 'Referer': this.URI.href, } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - request = new FetchRequest(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI).href, { + request = new Request(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI).href, { headers: { 'Referer': this.URI.href, } diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 9e90963cf5..1fc45b91d5 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,4 +1,4 @@ -import { FetchCSS, FetchRequest } from "../../FetchProvider"; +import { FetchCSS } from "../../platform/FetchProvider"; import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; import * as Common from './Common'; @@ -77,7 +77,7 @@ export function ChaptersSinglePageCSS(query = queryChapters) { */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters): Promise { const url = new URL(manga.Identifier, this.URI); - const request = new FetchRequest(url.href); + const request = new Request(url.href); const data = await FetchCSS(request, query); return data.map(anchor => { @@ -109,7 +109,7 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang */ export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query: string = queryPages, exclude: RegExp[] = DefaultExcludes): Promise { const uri = new URL(chapter.Identifier, this.URI); - const request = new FetchRequest(uri.href); + const request = new Request(uri.href); const data = await FetchCSS(request, query); const pages = data .map(element => { From c4c847ffbeee231cb7acdf86b9e9664c1ee4ac4a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 25 Jan 2024 09:53:13 +0100 Subject: [PATCH 24/83] WeloveManga : filter junk picture --- web/src/engine/websites/WeLoveManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 38b83ef1d1..05be2f2321 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -47,7 +47,7 @@ export default class extends DecoratableMangaScraper { 'Referer': this.URI.href, } }); - const nodes = await FetchCSS(request, 'img.chapter-img'); + const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); return nodes.map(image => new Page(this, chapter, new URL(image.dataset.original.replace(/\n/g, '')))); } From ec4a8a5f630b476a72037e2b9f1fc88d90b6be21 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 1 Feb 2024 14:00:17 +0100 Subject: [PATCH 25/83] Flatmanga ; trim manga title --- web/src/engine/websites/decorators/FlatManga.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 1fc45b91d5..a989481936 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -6,12 +6,12 @@ import * as Common from './Common'; export function MangaLabelExtractor(element: HTMLElement) { let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; title = title.replace(/\s*-\s*RAW$/i, ''); - return title; + return title.trim(); } export function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; let title = anchor.getAttribute('text') ? anchor.getAttribute('text') : anchor.textContent; - title = title.replace(/\s*-\s*RAW$/i, ''); + title = title.replace(/\s*-\s*RAW$/i, '').trim(); return { id, title }; } From 76e58e8b84a0f8ecb996c42fd27d72064c3bc8c8 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 1 Feb 2024 14:00:39 +0100 Subject: [PATCH 26/83] Add OlimpoScan https://github.com/manga-download/hakuneko/issues/6286 --- web/src/engine/websites/OlimpoScans.ts | 31 +++++++++++++++++++++ web/src/engine/websites/OlimpoScans.webp | Bin 0 -> 1268 bytes web/src/engine/websites/OlimpoScans_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 57 insertions(+) create mode 100644 web/src/engine/websites/OlimpoScans.ts create mode 100644 web/src/engine/websites/OlimpoScans.webp create mode 100644 web/src/engine/websites/OlimpoScans_e2e.ts diff --git a/web/src/engine/websites/OlimpoScans.ts b/web/src/engine/websites/OlimpoScans.ts new file mode 100644 index 0000000000..9d268349e9 --- /dev/null +++ b/web/src/engine/websites/OlimpoScans.ts @@ -0,0 +1,31 @@ +import { Tags } from '../Tags'; +import icon from './OlimpoScans.webp'; +import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; + +@Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageCSS() +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('olimposcans', `OlimpoScans`, 'https://olimposcans.com', Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Language.Spanish, Tags.Source.Scanlator); + } + + public override get Icon() { + return icon; + } + + public override async FetchPages(chapter: Chapter): Promise { + const pages = await FlatManga.FetchPagesSinglePageCSS.call(this, chapter); + return pages.map(page => new Page(this, chapter, this.stripSearch(page.Link))); + } + + stripSearch(Link: URL): URL { + Link.pathname = Link.pathname.replace(/&.*/g, ''); + return Link; + + } +} diff --git a/web/src/engine/websites/OlimpoScans.webp b/web/src/engine/websites/OlimpoScans.webp new file mode 100644 index 0000000000000000000000000000000000000000..1dde330fea97b97a03a1e446aabd0b4c1413f344 GIT binary patch literal 1268 zcmVAo!p5sD-Z6|}Wq`myfT~YldFrK#;3LJvwujBe@MeI~ zZvX}sW-YeLCao*3{3GTOVsFt4feN!B#w^rYX`fY&eI~kwiMoZ3^5Z_65&+ZPj4 zpU0P;J|?xAmb-7?5h`juoV3wasokvH`FUT0>O|V{kj=7%<|uc6*qxXdsPO%c+wDmv zSQF%G$2Sfo_88Lbw*%8D%YuAj7A)Aempnr3F|^EXIB&V_SDz96m<`W1+t89iIjSMPrEN3Tj1fD6w(kTT$z z!4^F+Ryh_h1YiJSWD}BS#xFk-aP<6QbVIZSYs(7&IZ&pt|2B8EZ*cih+I7v zV$&ugh9u$Hoh^*Vk?F<7O7r#qXu{)Yp1c*L!@7J`)-UFj>)UND_8&Yf#S8!d{!%yR z841$>e%MiVZoO`Oc;n=$UsX`uhI8rvtc+>*Gn(8C4hufsXv;)Tv!1hkz{}5G2uit{bJHpM$6Rvw z)`)MN49HJk33fW0TE~0*nHKuH3{sexs<-^(*e_+U0{x^b2&os( zJYep1c5UwhE7H$HL1@u36XS5NOoW-)usp{qtmjY(qCU7vq9E|TU~)YsHT!Djh*=c+ zk|;`y8=XD{#ZNmub81{!;Xg|rIRSg*1TeWcDEteup{uX6KV#|8R`I90L%)gmX|n0u za#mDSuq$Dm5+I)ytfSd*+)*wStboX)lSg=;QxLWXseh02d=D$o1qwpD77_Po!&1o- zsL7CaA(zv?KL!8QoQDi^cu4IhV7I@%E2r+ZUL@8^%O8B>Q?_nLc3aE*v-tJkJU!iI zL2wa!aNoO@VPe;U9s5(X3qG>IgPNk4Mu$zVX)TjY>fSFqSg% z*5}dk98NZtz~jTTD4_v&`w((jqSrqIl}yH)+af@or@%F=cL|+6X@D1v;Yab@h_h`I e(bso fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 48bbe3373c..d4ba75be20 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -436,6 +436,7 @@ export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; From 90e9ae1f6c2298f8c90fc2fbfecdb9fc47196084 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 1 Feb 2024 14:12:41 +0100 Subject: [PATCH 27/83] Flatmanga : generic multipage manga patth --- web/src/engine/websites/OlimpoScans.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 2 +- web/src/engine/websites/WeLoveManga.ts | 2 +- web/src/engine/websites/decorators/FlatManga.ts | 1 + 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/OlimpoScans.ts b/web/src/engine/websites/OlimpoScans.ts index 9d268349e9..e22d429927 100644 --- a/web/src/engine/websites/OlimpoScans.ts +++ b/web/src/engine/websites/OlimpoScans.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) -@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageCSS() @Common.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index 0424e41eb2..acac833e12 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; @Common.MangaCSS(/^{origin}\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) -@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageCSS() @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 05be2f2321..b81b81838d 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -20,7 +20,7 @@ const chapterScript = ` `; @Common.MangaCSS(/^{origin}\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) -@Common.MangasMultiPageCSS('/manga-list.html?page={page}', FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index a989481936..0e67c20551 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -17,6 +17,7 @@ export function MangaExtractor(anchor: HTMLAnchorElement) { export const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; export const pathSinglePageManga = '/manga-list.html?listType=allABC'; +export const pathMultiPageManga = '/manga-list.html?page={page}'; export const queryMangaTitle = [ 'li:last-of-type span[itemprop="name"]', From 7d0aa4842a0ec8c04bde2e0717abb124282d3ecd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 1 Feb 2024 15:11:21 +0100 Subject: [PATCH 28/83] Add NicoManga https://github.com/manga-download/hakuneko/issues/6398 --- web/src/engine/websites/NicoManga.ts | 57 +++++++++++++++++++++++ web/src/engine/websites/NicoManga.webp | Bin 0 -> 2162 bytes web/src/engine/websites/NicoManga_e2e.ts | 25 ++++++++++ web/src/engine/websites/WeLoveManga.ts | 2 +- web/src/engine/websites/_index.ts | 1 + 5 files changed, 84 insertions(+), 1 deletion(-) create mode 100644 web/src/engine/websites/NicoManga.ts create mode 100644 web/src/engine/websites/NicoManga.webp create mode 100644 web/src/engine/websites/NicoManga_e2e.ts diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts new file mode 100644 index 0000000000..29b6d23bc5 --- /dev/null +++ b/web/src/engine/websites/NicoManga.ts @@ -0,0 +1,57 @@ +import { Tags } from '../Tags'; +import icon from './NicoManga.webp'; +import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; +import { FetchCSS } from '../platform/FetchProvider'; + +const chapterScript = ` + new Promise(async resolve => { + const uri = new URL('app/manga/controllers/cont.Listchapterapi.php', window.location.origin); + uri.searchParams.set('slug', sLugs); + const response = await fetch(uri); + data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('ul > a')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title + }; + }); + resolve(chapters); + }); +`; + +@Common.MangaCSS(/^{origin}\/manga[^/]+\.html$/, FlatManga.queryMangaTitle) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.ChaptersSinglePageJS(chapterScript, 1000) +@Common.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('nicomanga', `NicoManga`, 'https://NicoManga.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); + } + + public override get Icon() { + return icon; + } + + public override async FetchPages(chapter: Chapter): Promise { + const url = new URL(chapter.Identifier, this.URI); + let request = new Request(url.href, { + headers: { + 'Referer': this.URI.href, + } + }); + const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; + request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI).href, { + headers: { + 'Referer': this.URI.href, + } + }); + const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.src.replace(/\n/g, ''), this.URI))); + } +} \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga.webp b/web/src/engine/websites/NicoManga.webp new file mode 100644 index 0000000000000000000000000000000000000000..92fb7462f8b39721d0d56442897d380562ce7ba0 GIT binary patch literal 2162 zcmV-&2#xnrNk&F$2mks4 zl9y=9He&`t#cT^+2$zQc49<;-(yxTD{44hDtCUu%Sr+}hXCzfXQHjzo(G}_;k(5Hn zDRlm7f3$3Y$LMlL4{R!;BG}49q04t%b|^H?W0rUOu8)Kn>P5b*To&=OMrq#&o|aZQZ;89oW6#~ z&9ufCYYl(w?Rf)D%BLV2oxkR|QP5R$#&Y^9-hN)Vv&G?}s%5@>Ar=E8Kv_Xj})Q23mNZg;dmhp%a>)xyH4mie1LcgRxz}^ z46V@V2bw?*Rfy;!Yv!dlg1mjx*p|+6M@XkHXhJ!pD`l+T%u9#};4hmpv%C)-zNZN# z;c)1JJFTE2gUnn5I(#>^8BIrb{0B6_otxx8&;(mAq9aR~yecGw#w9e&Tvm2;E5-nhwvz&;t?3A{_gSzQY#ZvZ7& zvsnh6Feo_iHkeCW@D8-X(KK8-0FqaUcWwlUSBC1LB?Eucd30X)L1>M)+2CK2Z$!|3 z=+Hj!M#$>Z3s{cx46@n$CWd!IC%A;p+XFzO^HrnGe@kCl1sVy~n&M&nBt;1uEnu40 zg7cX<&g$RSK$`SITgNT9Jw-n1O!y`z+^=JS4NrSLja$Njtm-DWv zohipOyVY{@Ce^GI0D)vru+vI!IOl13DtQM~;ei@qDy&4%0=s!>lJQ}*Xo<6Lfd)K8 zMVff+Qiwvw=R_rdsMxc{K$03h0nyRj-3#I(&p{;iw67#d4WERlsP0iPSSrLrA^DjN zk}NADBG_;qZTYnCHfTg-ompjA{<|7twly}KNgHnIPV=bvB_L=j91sj2FoW7s`ZDj#>T7HDxjbg zYF#7b4FCXEP&gna1ONc=6#$(9DnI~006v96p-`nGqav;uEO4L@fCC+-()T=zDPP@o zLQY>|bAa;z{UqrD<^%R;(ks=^`tL{%qMtwyEpKH1^B!OqdEZjyf|F~HdjXUW0rY`P z|HTK^zQEtCK8hZvzf^sRe^J~I%GsEWFJ348{L0xoAO#?SZa*#bA6!fJr)gxBo=OTd z^SjZY4WNmNj@3|xbRukz_#35r*0OF`CUgc7yyCg1vcQE>WG*A``OoUEN9FbsAFk;C7%d~ zx1;Q!D{FRbkI%P|AHGJJDVF;w{0dEEq4+j#5Ct?@V&H@K7fe6e>#Ez}*WvVM)z)V_F z7$nB>fVzTvr4B8PqZ1MhjBx~DnQ%XgD&#NJL##=yx%wqB`_QV6%n0b6Cx^>1hk4z{ zeG3U=I4DGq;+^_8VRBY462ck03$Rb%YG&TnN1VsVJMp41RTQbCt_aVF*Hgy|VQqH! zF<1N(?1c%B9atgj(rNXYT{{hEk9v2j(7Bj!bV~D}`Dnb#mMf~AUkgygG1dF7kB~pJ z(T_fuI-y2 fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index b81b81838d..5835c0c3ea 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -48,7 +48,7 @@ export default class extends DecoratableMangaScraper { } }); const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.original.replace(/\n/g, '')))); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.original.replace(/\n/g, ''), this.URI))); } } \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d4ba75be20..8724c73413 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -425,6 +425,7 @@ export { default as NewType } from './NewType'; export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; export { default as NHentaiCom } from './NHentaiCom'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; From 6bf2137b30e1ffb43d0d5236afce71bd0fa0feee Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 5 Feb 2024 18:32:51 +0100 Subject: [PATCH 29/83] Update _index.ts --- web/src/engine/websites/_index.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 47198eb561..07a8489e08 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -213,6 +213,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikAV } from './KomikAV'; @@ -267,6 +268,7 @@ export { default as MaID } from './MaID'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -377,6 +379,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; export { default as MangaWeebs } from './MangaWeebs'; @@ -456,6 +459,7 @@ export { default as NewType } from './NewType'; export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; export { default as NHentaiCom } from './NHentaiCom'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -470,6 +474,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -617,7 +622,9 @@ export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; +export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TruyenTranhtuan } from './TruyenTranhtuan'; export { default as TRWebtoon } from './TRWebtoon'; @@ -648,6 +655,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -722,7 +731,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -739,7 +747,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; @@ -763,7 +770,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -831,7 +837,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as TuMangaOnline } from './legacy/TuMangaOnline'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; @@ -843,8 +848,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 5ad884f29888f21bd4eaf48e7217f1af11c88ad8 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 8 Mar 2024 19:45:10 +0100 Subject: [PATCH 30/83] minor fixes --- web/src/engine/websites/NicoManga.ts | 6 +++--- web/src/engine/websites/WeLoveManga.ts | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 29b6d23bc5..b6d1302065 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -31,7 +31,7 @@ const chapterScript = ` export default class extends DecoratableMangaScraper { public constructor() { - super('nicomanga', `NicoManga`, 'https://NicoManga.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); + super('nicomanga', `NicoManga`, 'https://nicomanga.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } public override get Icon() { @@ -42,13 +42,13 @@ export default class extends DecoratableMangaScraper { const url = new URL(chapter.Identifier, this.URI); let request = new Request(url.href, { headers: { - 'Referer': this.URI.href, + 'Referer': this.URI.origin } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI).href, { headers: { - 'Referer': this.URI.href, + 'Referer': this.URI.origin } }); const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 5835c0c3ea..a36b6a2b93 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -38,13 +38,13 @@ export default class extends DecoratableMangaScraper { const url = new URL(chapter.Identifier, this.URI); let request = new Request(url.href, { headers: { - 'Referer': this.URI.href, + 'Referer': this.URI.origin, } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; request = new Request(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI).href, { headers: { - 'Referer': this.URI.href, + 'Referer': this.URI.origin, } }); const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); From c4f5241aaf8aae6343b826cb19fd60f7a670aed3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 9 Mar 2024 12:04:19 +0100 Subject: [PATCH 31/83] Nicomanga : fix async promise --- web/src/engine/websites/NicoManga.ts | 36 +++++++++++++++------------- 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index b6d1302065..724fa13141 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -6,20 +6,24 @@ import * as FlatManga from './decorators/FlatManga'; import { FetchCSS } from '../platform/FetchProvider'; const chapterScript = ` - new Promise(async resolve => { - const uri = new URL('app/manga/controllers/cont.Listchapterapi.php', window.location.origin); - uri.searchParams.set('slug', sLugs); - const response = await fetch(uri); - data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('ul > a')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title - }; - }); - resolve(chapters); + new Promise(async (resolve, reject) => { + try { + const uri = new URL('app/manga/controllers/cont.Listchapterapi.php', window.location.origin); + uri.searchParams.set('slug', sLugs); + const response = await fetch(uri); + data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('ul > a')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title + }; + }); + resolve(chapters); + } catch (error) { + reject(error); + } }); `; @@ -40,13 +44,13 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { const url = new URL(chapter.Identifier, this.URI); - let request = new Request(url.href, { + let request = new Request(url, { headers: { 'Referer': this.URI.origin } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI).href, { + request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI), { headers: { 'Referer': this.URI.origin } From 2a17406052bd9b6183821c25c1f99d44bedea6fd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 9 Mar 2024 12:05:07 +0100 Subject: [PATCH 32/83] minor fixes (href) --- web/src/engine/websites/MangaTR.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index e887ff1147..1468faf24b 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -23,8 +23,7 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - const uri = new URL('/manga-list.html', this.URI); - const request = new Request(uri.href); + const request = new Request(new URL('/manga-list.html', this.URI)); return FetchWindowScript(request, `window.cookieStore.set('read_type', '1')`, 0, 30000); } @@ -39,7 +38,7 @@ export default class extends DecoratableMangaScraper { private async getChaptersFromPage(manga: Manga, page: number): Promise{ const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); - const request = new Request(url.href, { + const request = new Request(url, { method: 'POST', body: 'page=' + page, headers: { From d6fccdb6bc988682337f098ddec1cace8cd0ee48 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 9 Mar 2024 12:07:55 +0100 Subject: [PATCH 33/83] Update BookmarkConverter.ts --- web/src/engine/transformers/BookmarkConverter.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index 01eae169c4..95e43c55e6 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -20,10 +20,9 @@ const legacyWebsiteIdentifierMap = { 'heavenmanga': 'beetoon', // (future zbulu PR) 'heavenmanga2': 'heavenmanga', // (future zbulu PR) 'imperioscans': 'neroxus', + 'kissaway': 'klmanga', 'kisscomic': 'readcomiconline', 'komikav': 'apkomik', - 'kissaway': 'klmanga', - 'imperioscans': 'neroxus', 'kumascans': 'retsu', 'lovehug': 'welovemanga', 'lyrascans': 'quantumscans', //https://www.mangaupdates.com/groups.html?id=35005683580 'Formerly known as LyraScans' From 063ab2c13e371ddce573ae39a80a116ee472ceb5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 17 Mar 2024 15:02:37 +0100 Subject: [PATCH 34/83] remove Truyentranhlh (dead) https://github.com/keiyoushi/extensions-source/issues/1834 --- web/src/engine/websites/TruyenTranhLH.ts | 22 ---------------- web/src/engine/websites/TruyenTranhLH.webp | Bin 1306 -> 0 bytes web/src/engine/websites/TruyenTranhLH_e2e.ts | 25 ------------------- web/src/engine/websites/_index.ts | 1 - 4 files changed, 48 deletions(-) delete mode 100644 web/src/engine/websites/TruyenTranhLH.ts delete mode 100644 web/src/engine/websites/TruyenTranhLH.webp delete mode 100644 web/src/engine/websites/TruyenTranhLH_e2e.ts diff --git a/web/src/engine/websites/TruyenTranhLH.ts b/web/src/engine/websites/TruyenTranhLH.ts deleted file mode 100644 index 9e4062a5fe..0000000000 --- a/web/src/engine/websites/TruyenTranhLH.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './TruyenTranhLH.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import * as FlatManga from './decorators/FlatManga'; - -@Common.MangaCSS(/^{origin}\/truyen-tranh\/[^/]+$/, 'span.series-name') -@Common.MangasMultiPageCSS('/danh-sach?page={page}', FlatManga.queryMangas) -@FlatManga.ChaptersSinglePageCSS() -@Common.PagesSinglePageCSS(FlatManga.queryPages) -@Common.ImageAjax() - -export default class extends DecoratableMangaScraper { - - public constructor() { - super('truyentranhlh', `TruyentranhLH`, 'https://truyentranhlh.net', Tags.Language.Vietnamese, Tags.Media.Manga, Tags.Source.Aggregator); - } - - public override get Icon() { - return icon; - } -} \ No newline at end of file diff --git a/web/src/engine/websites/TruyenTranhLH.webp b/web/src/engine/websites/TruyenTranhLH.webp deleted file mode 100644 index 3c18e9bc86b6a1583642bbe7bb8b627326c8e34e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1306 zcmV+#1?BouNk&Ez1pok7MM6+kP&il$0000G0000#002J#06|PpNLm8`01csx=zoB= zw!LX2>Hj4sDQfPXWv2VT72Z8;W|*n2R41{dg+XWOFk%8GKso^U$j5&3t3VSoN$%ZX~vP`H_ zUP`J)f*jG4-i0%t_<(SoUQ#Iv6bT9x$YhU}-uIDKE9-@f0)>PWmGPS7=soYbamR#} zwE#gR4N3|Fa$7bmJ*Px40OXwObZRw~lmt+ztYm5`sR012wC>&6FgMXCOQ?ZSN(rDq zCTl%PDibrt4F-v#LSDa8>-0>vFlBmcPbw2Ynn0u072s+VFCmJ|DA=%42eMFQI*aUr3l75Gcy?6x^bW;Mzdp!%YM<> zrD!x0Qx2{qf?&j?vOq8@2=IS?03ryZGD%`a)oL{w+qNw&jpx>#xrHx$?%bL2thJJ4 z-+||z8xMf#%r&yCB$G87nRy-OlEk@^dcB3Y!63Xw*+L|hQ|GqrXjBvgGQqgg5;ZmR zy&oLdwQnCOaIR+trHN!_=E9lA1OWsfrIHG%AUcDBXv0jF^|D*HoFSN5SXii3z&u$g zhp5spCb-_f01!|Jb5p%6Kq>`B|6!6-{^*SN|P0TbJS!ZVM zg^qD$1!r6!2sKqnGE=McvhWvHP&gox0RR9{3ILq}DnI~006wusn@gu7qM^O`hydUg z32Xq!kU5Dbz+jw&KI(s~06SEBPOrXkwyq^ydTPF!JRai9?5b#-7r~Hk3aGoZ0%{Quk-!2V0XDdtY0%@j(I#|SeWcn|V5Io&z#}hK zBo@B7v<2b^Mo8D|bZLZ7>`jCTfBS)~CJ`Xk!b3S&TFlS}AqkzA;e^z)cUL02Sj@lw zr5LP6EibHX)o$n~QFh^9ncTH;LC}e!YL2!4V$7ddKUz*wTv7k$-hVy^tFJ)0Q2>$O z`CUKKV5pNah#PgbWoy0>(<`}41BzF)pfuz3j~EePCe#&|!suhb{+m~k3w4zeMQ@>> QeE!hyUpFV)@3P-O06K|5o&W#< diff --git a/web/src/engine/websites/TruyenTranhLH_e2e.ts b/web/src/engine/websites/TruyenTranhLH_e2e.ts deleted file mode 100644 index 3e358c4553..0000000000 --- a/web/src/engine/websites/TruyenTranhLH_e2e.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; - -const config = { - plugin: { - id: 'truyentranhlh', - title: 'TruyentranhLH' - }, - container: { - url: 'https://truyentranhlh.net/truyen-tranh/tho-ren-huyen-thoai', - id: '/truyen-tranh/tho-ren-huyen-thoai', - title: 'Thợ Rèn Huyền Thoại' - }, - child: { - id: '/truyen-tranh/tho-ren-huyen-thoai/chapter-188-227', - title: 'Chapter 188', - }, - entry: { - index: 0, - size: 232_191, - type: 'image/jpeg' - } -}; - -const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 53edc0f86b..a25eaf365f 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -632,7 +632,6 @@ export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; -export { default as TruyenTranhLH } from './TruyenTranhLH'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TruyenTranhtuan } from './TruyenTranhtuan'; export { default as TRWebtoon } from './TRWebtoon'; From ca340faae31e911fe29d0b0c4e3c73865d3d798d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 24 Mar 2024 13:34:23 +0100 Subject: [PATCH 35/83] Add RawInu https://github.com/manga-download/hakuneko/issues/6444 --- web/src/engine/websites/RawInu.ts | 53 ++++++++++++++++++ web/src/engine/websites/RawInu.webp | Bin 0 -> 2454 bytes web/src/engine/websites/RawInu_e2e.ts | 25 +++++++++ web/src/engine/websites/_index.ts | 1 + .../engine/websites/decorators/FlatManga.ts | 2 - 5 files changed, 79 insertions(+), 2 deletions(-) create mode 100644 web/src/engine/websites/RawInu.ts create mode 100644 web/src/engine/websites/RawInu.webp create mode 100644 web/src/engine/websites/RawInu_e2e.ts diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts new file mode 100644 index 0000000000..88fc10fbdc --- /dev/null +++ b/web/src/engine/websites/RawInu.ts @@ -0,0 +1,53 @@ +import { Tags } from '../Tags'; +import icon from './RawInu.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; + +const chapterScript = ` + new Promise(async resolve => { + const uri = new URL('app/manga/controllers/cont.Listchapter.php', window.location.origin); + const slug = document.documentElement.innerHTML.match(/var slugs\\s*=\\s*'([^']+)/i)[1]; + uri.searchParams.set('slug', slug); + const response = await fetch(uri); + data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('a')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title.trim() + }; + }); + resolve(chapters); + }); +`; + +const pageScript = ` + new Promise(async resolve => { + const chapId = document.querySelector('input#chapter').value; + const uri = new URL('app/manga/controllers/cont.imagesChap.php', window.location.origin); + uri.searchParams.set('cid', chapId); + const response = await fetch(uri); + const data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('img')]; + resolve(nodes.map(picture => picture.dataset.src.trim())); + }); +`; + +@Common.MangaCSS(/^{origin}\/[^.]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.ChaptersSinglePageJS(chapterScript, 500) +@Common.PagesSinglePageJS(pageScript, 500) +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('rawinu', `RawInu`, 'https://rawinu.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Aggregator); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/RawInu.webp b/web/src/engine/websites/RawInu.webp new file mode 100644 index 0000000000000000000000000000000000000000..5344c9428634343e3d15d0ab38ad5e37a93b80fe GIT binary patch literal 2454 zcmV;H32F9HNk&GF2><|BMM6+kP&il$0000G0000#002J#06|PpNY?}a00FRtZQCJ9 z((`>^WZQQ4+8EomZQHhO+qP}nc4KT8@{f2ADyt$R2geaH0sOwTh+mWi;Qq@AXX2Xk zK-e!Mg8qAaEnWY2JgoIRj1}Kku3Q}_4kDt(EHh@hT}7ccepb@dje_u23TND@ol5$2 zTVLQArCd+Xk7d>>5yaMCD=D2m3MaPsT&d7ygqgqA|6e$Fy?(;d9Fui!onyS&hXO@v$Nv&^zfuW*anbU9I#ISq~MM*XaF zdSf&;_Eo2rqavg4CcEsg*GrqwCu>NT{m3$Uwts|VvK%Co%-rqb?A;-WjLoR6_Pq;oHd>R zaK=2NT*`G*U%Xit=(~v+V9xems*qIZ)Bh0wZndpno<9Aptv3gHzU-{{^L7&(DK}b-@_>rSkvcjlvmnc2d&Uo7XT(ThMFUPn3%M;>mb4 zir1vsi7poO+V*25b(}elaGDv;u;bfR*Y^hwCZfUX(rk@j$ybyYy6fLq7|pfJ`P-e! zlcui(;q=7FE>}_4)RnMsn(qNCy{eS!{@Jh$?=E8(wRP%zrxsM}L9cDTQc^l^BHpVz zXXejUFFrkF7!lP#I1|rJO8RDpn!nKv#y@YB3Qb+x2(JbUWA+D?C%wAjOWonl60a!b zdT4Gevr51NmVaMK^^P9kL2dIdl?q)t29IhWg24xVr##O!Yc~+i*t0uS*B5*C!>t+! zXVOJUh34o17RG<>Ql9kI%0}fD#=Oty)nQn7-~p??rnNfHFgKcLnX$mSz4#@2fc>H%GJZ7y09H^qAdmzA0I(JSodGI9 z06+jfg+ifFr6Z#vsu`N-pb&rnPg(v0!rumddG?>w1)=}b@W1cB6FbWsr}}4j&ZANh zWC`=H@SeaQ$N#K<%KKILfBJLHm(CyhzsLLpe<}XG=}GIG^}E<#_6dJgh>he4Beehg z!+HW5k;UW;nP}DVyqxm_& z4iFCSdJfl%_%%Rtm0%VZ>PtkV$*|Jg* zaf{d=F_&Tpu=#^C>LyeB&+%8l)hY7Ji6ZU>S&aj7!AM3MD%+XUC2@`&e~~f!zQA{6%+93&s%rOa%FpbP-$hAtzhg)(ZBwM^?m2#f zDd+g2;X?76;R<{wSKv?L1UNqef*V{Wml1ZdLv_4c(rx9Vhl=(D*^ST zI4zMrT2SBs8bH?}huJ^0fqfbfzRZ9qCt)0L9cHg6exnm0>qFN`kCuh~TCd5{d2Xpa zzDLa!YTt8RWCwS9{%Km$Ol8vwHp2txUv#DHG+68IICc{jn**YKG02{x2GE`sEs{jQ z7g3ayiJZ`?Fe%`iLQJS~L%-hTX}PHn>JL!s;*Umvd4I`GxM?J9dhZ`|)&K>Q@ z6fL2Z*T=9$&Pa*(=+GzkB;58@i7JX|SMLQ|dfd8=DkvRzz(9npILnZfk?ANSow5df z^G;$!9ruqp_O8@D_^aZGe8MREqp$s0(dXKC0km?=(#4{fjE_?MC}SiaQc*zW=7aPL1%QyCqY3sG25Q-3v9u=@;ux zh7gWDkOc(iCbxXAlNh(7Zn3ie2d7v)V}ALmD(Lx?AxAQMowDdO&d1G_-ImCjRIu;Q z)8Ek(lHn($eA^Va5;~56XOq%Sf{!F|Mx6D)nPBr`y?8o|CYZR}d{Xkds!=$MQ~8GV!RCyEqF;$MJ;q$VQAf@8&i!=70)n!ydx)wu>2`277Rm zBu)^|nDV&LU{UE~uP)gQ4FcQ%THrDDocV$W{>_XNCXsj4;C00{mX$9AsUpKfRCOTX zS$J356_m!WO$@Jdg&_XnNrw64TZp;T)Fh|7jr)lW<0eC0xu5p~p700c0FO^)JJbwdEK90Qj8NuK)l5 literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/RawInu_e2e.ts b/web/src/engine/websites/RawInu_e2e.ts new file mode 100644 index 0000000000..f6681b8732 --- /dev/null +++ b/web/src/engine/websites/RawInu_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'rawinu', + title: 'RawInu' + }, + container: { + url: 'https://rawinu.com/manga-tatari-watari.html', + id: '/manga-tatari-watari.html', + title: 'TATARI (WATARI)' + }, + child: { + id: '/chapter-44-cthide-tatari-watari.html', + title: 'Chapter 44' + }, + entry: { + index: 0, + size: 548_603, + type: 'image/jpeg' + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 8305d6043d..692dad03bb 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -522,6 +522,7 @@ export { default as RainDropFansub } from './RainDropFansub'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawSenManga } from './RawSenManga'; export { default as RawXZ } from './RawXZ'; diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 0e67c20551..c7369bd2ac 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -54,7 +54,6 @@ export const queryPages = [ /** * A class decorator that adds the ability to extract all chapters for a given manga from this website using the given CSS {@link query}. - * This method utilizes the HTML pages provided by the **MadTheme Admin AJAX endpoint** to extract the chapters. * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted */ export function ChaptersSinglePageCSS(query = queryChapters) { @@ -71,7 +70,6 @@ export function ChaptersSinglePageCSS(query = queryChapters) { /** * An extension method for extracting all chapters for the given {@link manga} using the given CSS {@link query}. - * This method utilizes the HTML pages provided by the **MadTheme Admin AJAX endpoint** to extract the chapters. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param manga - A reference to the {@link Manga} which shall be assigned as parent for the extracted chapters * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted From 4af6d03f5c8ff1fa93ca3fd65a9f88848dda85f8 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 19 Apr 2024 18:25:19 +0200 Subject: [PATCH 36/83] Add MangaGun --- web/src/engine/websites/MangaGun.ts | 52 ++++++++++++++++++++++++ web/src/engine/websites/MangaGun.webp | Bin 0 -> 2078 bytes web/src/engine/websites/MangaGun_e2e.ts | 25 ++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 78 insertions(+) create mode 100644 web/src/engine/websites/MangaGun.ts create mode 100644 web/src/engine/websites/MangaGun.webp create mode 100644 web/src/engine/websites/MangaGun_e2e.ts diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts new file mode 100644 index 0000000000..925e5a7b6b --- /dev/null +++ b/web/src/engine/websites/MangaGun.ts @@ -0,0 +1,52 @@ +import { Tags } from '../Tags'; +import icon from './MangaGun.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as FlatManga from './decorators/FlatManga'; + +const chapterScript = ` + new Promise(async resolve => { + const uri = new URL('app/manga/controllers/cont.Listchapter.php', window.location.origin); + uri.searchParams.set('slug', sLugs); + const response = await fetch(uri); + data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('a')]; + const chapters= nodes.map(chapter => { + return { + id : chapter.pathname, + title : chapter.title.trim() + }; + }); + resolve(chapters); + }); +`; + +const pageScript = ` + new Promise(async resolve => { + const chapId = document.querySelector('input#chapter').value; + const uri = new URL('app/manga/controllers/cont.Showimage.php', window.location.origin); + uri.searchParams.set('cid', chapId); + const response = await fetch(uri); + const data = await response.text(); + const dom = new DOMParser().parseFromString(data, "text/html"); + const nodes = [...dom.querySelectorAll('img')]; + resolve(nodes.map(picture => picture.dataset.src)); + }); +`; + +@Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@Common.ChaptersSinglePageJS(chapterScript, 1000) +@Common.PagesSinglePageJS(pageScript, 1000) +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('mangagun', `MangaGun`, 'https://mangagun.net', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); + } + + public override get Icon() { + return icon; + } +} diff --git a/web/src/engine/websites/MangaGun.webp b/web/src/engine/websites/MangaGun.webp new file mode 100644 index 0000000000000000000000000000000000000000..ff56c9a30538cd60a6411948b08d69cb42e98e35 GIT binary patch literal 2078 zcmV+(2;uiqNk&E%2mk# znL^TWX*vamWCZN}@*|I1@z`@y4Lan21NJ{?&xYMRj~QDO8WDLn&Szxg+3>KRo7j#< zz`C!K3krqFW)@Z)m(U?uhMU!Oy}vj4b%Lw_l%OH>KH& z$DMv^HBP=@nfeDT#+}7d=*X`r!hCjHTmlYd&dAFV5=5M-{CX-HnE`c7`3pt(^Az@5 zJm!cL;g`eVY+7BxIF1~IEFt6XRhsQ+(=1>y^{03Hq=;Bc@jO>IY8IXtcOutI;pzFN zvTQkt{6A=r$X z;SY-Ny9rZx7F2%ucz{*Jjq3M3lSDkMG~3k5v%HGv>)li6Cb}epscU*&%>`FU5z+qx z78EXQrMoDf+yS2;;z$+N%W%?*k3Md|qd$?tu31tFZkpdI!e54tzsv+7bDo+Y!s8kx z;s88rZJI*imqSx{mR4bTADgn3ThZe72_n#ZLGi5A|9gAOFZg0Jt7RI7E2qjy;co*L zx$fKxG%h;r*yB3mnA2wM#N%A`htn1J865)SFylsRuhSW8Z@S$!8e8o=Q>9pk;a{nC zJ1c5oJTeUWlm+cBe69vpotTQ;Su!ZYQT!vfqh)A}4viNT^J?lVkLmuPkYWQV{A!qi ztf&jK2i*8`JtHYhNa52EQW`_Rvg%K*@4mO-yDn8iv%#Cjz3_*L;L&(aIbq#wV83b% z40|x@2vtisuGARo*ior=x2;SZ8ZVS1RH@LQPbm~GfC<&?jI$v)3u>hn_F9ihvodU@ z%zXr#bVy1T3yR@}XOWZR_lG z=<_yjDn;mggleO%R314Lck|i0jb=EUZ7$RJTt#TU%9qEKzfy$1jh@yzJ3XfQm65Mt zbL$ArIxHqDceA#~tCeF`gO1Sp1_}M%Q~y~UHIuBY6qvUMlvap$`WVV@1IBUZNe^e@ z2~U?2qmIj!0}e)3t=ogjrP~Kv$!xE5x*yJCieJ>6n8F}o0afl@_L41a4jB%zu5bYt zB({vma}ZPlzQcmT#S9WA{vn}d35DNJph6O`o{ms3q~<B4?Ia%u~s(l*5EK-g?W;w_V@gP#z%# zzQRL)HC)M(|9=2hP&gn01ONb#6abw8DnI~006v96p-`nGqN1h%pb&rq2M%AF_`7-v zIByqk5AI&THqZHz{cin$_w4jH=mGl~))(kY<-6?9UBHF?(RYv_kM7wQxOdw0z^+yc0Q)${#84iUfTbJH$^P@HbmN#i=!YE50Q4xaOP zd!FrEG=M<;9Rr1T~t$g5X^SC~;N% zf?OJ~<#9$&VrMX=Ngagf^-iG?bp0T)>f~CnKS(n|!Pyp9%Vs?=J;8c|U983rwHp z)q;NJJP`o@y`R>0$Y}lV332p~uMDMbKjIx`gsGzaeR^5%ML_2@UHQn1$_H(UIigouNt9a{MJqrWfW*`o$(Dm*&sF9PBGBO9;( zR4!jHy#XtpnAZsTPSbJLw(% zsF)ORCpm?YFll9=ugs(~m)pD`(8q~E&eKhN?DG+ofdy@yo4$-u6;$P=0Vd)f*}1*d zCkos5r^uTZSJf6&IjHLA{y7k4D2{dHsT#(NJ3M96-=HlvbGrdc)FjVFoSLshI|#3k2t95vTF5dQ)G|hm6Q(tDpS`*PX*W@dB5iT8s4_Y2G?&)e)fRv{SOP_C~rA;rdRi%7JkNb z^GZ*8{|DE3rG=V~bw7R*HaOXxe=j9fGMTY1b5b+WF-;EdzdXHapav)#d&4MEp*WOb ITM*g+0GxgWp#T5? literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/MangaGun_e2e.ts b/web/src/engine/websites/MangaGun_e2e.ts new file mode 100644 index 0000000000..f049b4a0b1 --- /dev/null +++ b/web/src/engine/websites/MangaGun_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'mangagun', + title: 'MangaGun' + }, + container: { + url: 'https://mangagun.net/manga-oshi-no-ko-raw.html', + id: '/manga-oshi-no-ko-raw.html', + title: 'OSHI NO KO' + }, + child: { + id: '/gunchap-146-shmg-oshi-no-ko-raw.html', + title: 'Chapter 146' + }, + entry: { + index: 0, + size: 297_654, + type: 'image/jpeg', + } +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 692dad03bb..494528067e 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -314,6 +314,7 @@ export { default as MangaFreak } from './MangaFreak'; export { default as MangaGecko } from './MangaGecko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; From 10d1d216ae582e933b051f0ed787bdbc284aaf20 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Apr 2024 14:16:49 +0200 Subject: [PATCH 37/83] Update _index.ts --- web/src/engine/websites/_index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 190e19d91e..7018d1fd3a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -218,6 +218,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -276,6 +277,7 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -321,6 +323,7 @@ export { default as MangaFreak } from './MangaFreak'; export { default as MangaGecko } from './MangaGecko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -392,6 +395,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -481,6 +485,7 @@ export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -495,6 +500,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -534,6 +540,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawMangatop } from './RawMangatop'; export { default as RawSenManga } from './RawSenManga'; @@ -650,6 +657,7 @@ export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; export { default as TruyenTranhtuan } from './TruyenTranhtuan'; @@ -686,6 +694,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -763,7 +773,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -780,7 +789,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; @@ -801,7 +809,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -867,7 +874,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; export { default as VerMangasPorno } from './legacy/VerMangasPorno'; @@ -878,8 +884,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 80f4bc0cd5c0c373c649d71c43570840345c4325 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Apr 2024 14:19:20 +0200 Subject: [PATCH 38/83] use pascal case --- web/src/engine/websites/KLManga.ts | 1 - web/src/engine/websites/MangaGun.ts | 1 - web/src/engine/websites/MangaTR.ts | 5 ++--- web/src/engine/websites/NicoManga.ts | 1 - web/src/engine/websites/OlimpoScans.ts | 9 ++++----- web/src/engine/websites/RawInu.ts | 1 - web/src/engine/websites/TruyenChapVn.ts | 3 --- web/src/engine/websites/WeLoMa.ts | 1 - web/src/engine/websites/WeLoveManga.ts | 2 -- 9 files changed, 6 insertions(+), 18 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 241e134124..2987060a7e 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -40,7 +40,6 @@ const pageScript = ` @Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index 925e5a7b6b..4d31663265 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -41,7 +41,6 @@ const pageScript = ` @Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { super('mangagun', `MangaGun`, 'https://mangagun.net', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); } diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 1468faf24b..64cdc266b2 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -13,7 +13,6 @@ function MangaLabelExtractor(element: HTMLTitleElement) { @Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) @FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { super('mangatr', `Manga-TR`, 'https://manga-tr.com', Tags.Language.Turkish, Tags.Media.Manga, Tags.Source.Aggregator); @@ -30,12 +29,12 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const chapterList = []; for (let page = 1, run = true; run; page++) { - const chapters = await this.getChaptersFromPage(manga, page); + const chapters = await this.GetChaptersFromPage(manga, page); chapters.length > 0 ? chapterList.push(...chapters) : run = false; } return chapterList.distinct(); } - private async getChaptersFromPage(manga: Manga, page: number): Promise{ + private async GetChaptersFromPage(manga: Manga, page: number): Promise{ const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); const request = new Request(url, { diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 724fa13141..d4c765dddc 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -31,7 +31,6 @@ const chapterScript = ` @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/OlimpoScans.ts b/web/src/engine/websites/OlimpoScans.ts index e22d429927..8038e5ab8b 100644 --- a/web/src/engine/websites/OlimpoScans.ts +++ b/web/src/engine/websites/OlimpoScans.ts @@ -9,7 +9,6 @@ import * as FlatManga from './decorators/FlatManga'; @FlatManga.ChaptersSinglePageCSS() @Common.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { super('olimposcans', `OlimpoScans`, 'https://olimposcans.com', Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Language.Spanish, Tags.Source.Scanlator); } @@ -20,12 +19,12 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { const pages = await FlatManga.FetchPagesSinglePageCSS.call(this, chapter); - return pages.map(page => new Page(this, chapter, this.stripSearch(page.Link))); + return pages.map(page => new Page(this, chapter, this.StripSearch(page.Link))); } - stripSearch(Link: URL): URL { - Link.pathname = Link.pathname.replace(/&.*/g, ''); - return Link; + StripSearch(link: URL): URL { + link.pathname = link.pathname.replace(/&.*/g, ''); + return link; } } diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index 88fc10fbdc..c58f08bb3f 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -42,7 +42,6 @@ const pageScript = ` @Common.PagesSinglePageJS(pageScript, 500) @Common.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { super('rawinu', `RawInu`, 'https://rawinu.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Aggregator); } diff --git a/web/src/engine/websites/TruyenChapVn.ts b/web/src/engine/websites/TruyenChapVn.ts index aad297ff9d..2b0d6ef760 100644 --- a/web/src/engine/websites/TruyenChapVn.ts +++ b/web/src/engine/websites/TruyenChapVn.ts @@ -3,14 +3,12 @@ import icon from './TruyenChapVn.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; - function MangaExtractor(anchor: HTMLAnchorElement) { return { id: anchor.pathname, title: anchor.text.replace(/\(chap.vn\)/i, '').trim() }; } - function MangaLabelExtractor(element: HTMLElement) { return element.textContent.replace(/\(chap.vn\)/i, '').trim(); } @@ -19,7 +17,6 @@ function MangaLabelExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, MangaExtractor) @Common.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index acac833e12..f1360f6c89 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -10,7 +10,6 @@ import * as FlatManga from './decorators/FlatManga'; @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { super('weloma', `WeLoMa`, 'https://weloma.art', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Aggregator); } diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index a36b6a2b93..9a3ee26964 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -23,9 +23,7 @@ const chapterScript = ` @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() - export default class extends DecoratableMangaScraper { - public constructor() { super('welovemanga', `WeloveManga`, 'https://welovemanga.one', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Aggregator); } From 082dc5226234df140585e3c73ccc2acca5ae2b35 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 7 May 2024 12:31:13 +0200 Subject: [PATCH 39/83] update e2e tests to use vitest --- web/src/engine/websites/KLManga_e2e.ts | 3 ++- web/src/engine/websites/Manga33_e2e.ts | 5 +++-- web/src/engine/websites/MangaGun_e2e.ts | 5 +++-- web/src/engine/websites/MangaTR_e2e.ts | 5 +++-- web/src/engine/websites/NicoManga_e2e.ts | 5 +++-- web/src/engine/websites/OlimpoScans_e2e.ts | 5 +++-- web/src/engine/websites/RawInu_e2e.ts | 3 ++- web/src/engine/websites/TruyenChapVn_e2e.ts | 5 +++-- web/src/engine/websites/WeLoMa_e2e.ts | 5 +++-- web/src/engine/websites/WeLoveManga_e2e.ts | 5 +++-- 10 files changed, 28 insertions(+), 18 deletions(-) diff --git a/web/src/engine/websites/KLManga_e2e.ts b/web/src/engine/websites/KLManga_e2e.ts index b583fe2449..10c98e5501 100644 --- a/web/src/engine/websites/KLManga_e2e.ts +++ b/web/src/engine/websites/KLManga_e2e.ts @@ -1,3 +1,4 @@ +import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -22,4 +23,4 @@ const config: Config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/Manga33_e2e.ts b/web/src/engine/websites/Manga33_e2e.ts index d867d8c0e9..a8b93fdda0 100644 --- a/web/src/engine/websites/Manga33_e2e.ts +++ b/web/src/engine/websites/Manga33_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/MangaGun_e2e.ts b/web/src/engine/websites/MangaGun_e2e.ts index f049b4a0b1..d69dfcffb4 100644 --- a/web/src/engine/websites/MangaGun_e2e.ts +++ b/web/src/engine/websites/MangaGun_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/MangaTR_e2e.ts b/web/src/engine/websites/MangaTR_e2e.ts index 19f11d40f3..040301f251 100644 --- a/web/src/engine/websites/MangaTR_e2e.ts +++ b/web/src/engine/websites/MangaTR_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga_e2e.ts b/web/src/engine/websites/NicoManga_e2e.ts index aa53d1d41b..a158847ca9 100644 --- a/web/src/engine/websites/NicoManga_e2e.ts +++ b/web/src/engine/websites/NicoManga_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/OlimpoScans_e2e.ts b/web/src/engine/websites/OlimpoScans_e2e.ts index 6da263d277..468fcfe40b 100644 --- a/web/src/engine/websites/OlimpoScans_e2e.ts +++ b/web/src/engine/websites/OlimpoScans_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/RawInu_e2e.ts b/web/src/engine/websites/RawInu_e2e.ts index f6681b8732..9151563d77 100644 --- a/web/src/engine/websites/RawInu_e2e.ts +++ b/web/src/engine/websites/RawInu_e2e.ts @@ -1,3 +1,4 @@ +import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -22,4 +23,4 @@ const config: Config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/TruyenChapVn_e2e.ts b/web/src/engine/websites/TruyenChapVn_e2e.ts index de56deb5b1..ba96ce1ac2 100644 --- a/web/src/engine/websites/TruyenChapVn_e2e.ts +++ b/web/src/engine/websites/TruyenChapVn_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoMa_e2e.ts b/web/src/engine/websites/WeLoMa_e2e.ts index c03cf2fdd3..495768684d 100644 --- a/web/src/engine/websites/WeLoMa_e2e.ts +++ b/web/src/engine/websites/WeLoMa_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -22,4 +23,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts index 7994bfe7c0..bef45bc0c5 100644 --- a/web/src/engine/websites/WeLoveManga_e2e.ts +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file From 745c309d9b9df2f245d181a33129c4f698e0f852 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 18 May 2024 13:17:23 +0200 Subject: [PATCH 40/83] Update _index.ts --- web/src/engine/websites/_index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 0aeb6002e2..19e21fa532 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -226,6 +226,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -288,6 +289,7 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -332,6 +334,7 @@ export { default as MangaFreak } from './MangaFreak'; export { default as MangaGecko } from './MangaGecko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -404,6 +407,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -496,6 +500,7 @@ export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -510,6 +515,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -550,6 +556,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawMangatop } from './RawMangatop'; export { default as RawSenManga } from './RawSenManga'; @@ -669,6 +676,7 @@ export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TritiniaScans } from './TritiniaScans'; export { default as TrueManga } from './TrueManga'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenQQ } from './TruyenQQ'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; @@ -706,6 +714,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -783,7 +793,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -800,7 +809,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; @@ -821,7 +829,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -886,7 +893,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; export { default as VerMangasPorno } from './legacy/VerMangasPorno'; @@ -897,8 +903,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 3c14d8ee0bf492c5149fffd4072d0d3352fb2e5a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 18 May 2024 14:04:39 +0200 Subject: [PATCH 41/83] weloma : fix test --- web/src/engine/websites/WeLoMa_e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/WeLoMa_e2e.ts b/web/src/engine/websites/WeLoMa_e2e.ts index 495768684d..f8cd7d0153 100644 --- a/web/src/engine/websites/WeLoMa_e2e.ts +++ b/web/src/engine/websites/WeLoMa_e2e.ts @@ -17,8 +17,8 @@ const config = { }, entry: { index: 0, - size: 546_228, - type: 'image/png' + size: 100_474, + type: 'image/webp' } }; From 3a90282966361faff1f1ec5a7c0c5b2431ed9242 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 26 May 2024 11:34:44 +0200 Subject: [PATCH 42/83] KLManga : fix getting chapters & pages --- web/src/engine/websites/KLManga.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 2987060a7e..ff5e6fb8e6 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -6,7 +6,10 @@ import * as FlatManga from './decorators/FlatManga'; const chapterScript = ` new Promise(async resolve => { - const uri = new URL('app/manga/controllers/cont.listChapter.php', window.location.origin); + const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let randomEndpoint = ''; + for (let o = 0; o < 25; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); + const uri = new URL(randomEndpoint + '.lstc', window.location.origin); uri.searchParams.set('slug', dataL); const response = await fetch(uri); data = await response.text(); @@ -25,7 +28,10 @@ const chapterScript = ` const pageScript = ` new Promise(async resolve => { const chapId = document.querySelector('input#chapter').value; - const uri = new URL('app/manga/controllers/cont.listImg.php', window.location.origin); + const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let randomEndpoint = ''; + for (let o = 0; o < 30; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); + const uri = new URL(randomEndpoint + '.iog', window.location.origin); uri.searchParams.set('cid', chapId); const response = await fetch(uri); const data = await response.text(); From 03b39a45e33dbd8f0cd6e123ae183e177a60d980 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 1 Jun 2024 18:01:07 +0200 Subject: [PATCH 43/83] filter olimposcans ads --- web/src/engine/websites/KLManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index ff5e6fb8e6..2cb1e22f4f 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -37,7 +37,7 @@ const pageScript = ` const data = await response.text(); const dom = new DOMParser().parseFromString(data, "text/html"); const nodes = [...dom.querySelectorAll('img.chapter-img[alt*="Page"]')]; - resolve(nodes.map(picture => picture.src)); + resolve(nodes.map(picture => picture.src).filter(image => !image.match(/olimposcan/))); }); `; From 4f91a34ef5b8ddbf64e4977505e1a4dcf2778136 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 2 Jun 2024 10:04:28 +0200 Subject: [PATCH 44/83] Update _index.ts --- web/src/engine/websites/_index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d670cf0079..02b3843a6a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -229,6 +229,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -291,6 +292,7 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -336,6 +338,7 @@ export { default as MangaFreak } from './MangaFreak'; export { default as MangaGecko } from './MangaGecko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -409,6 +412,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -501,6 +505,7 @@ export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -515,6 +520,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -555,6 +561,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawMangatop } from './RawMangatop'; export { default as RawSenManga } from './RawSenManga'; @@ -673,6 +680,7 @@ export { default as Toti } from './Toti'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TritiniaScans } from './TritiniaScans'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenQQ } from './TruyenQQ'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; @@ -710,6 +718,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -784,7 +794,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -801,7 +810,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as Manga1001 } from './legacy/Manga1001'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; @@ -822,7 +830,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -887,7 +894,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; export { default as VerMangasPorno } from './legacy/VerMangasPorno'; @@ -898,8 +904,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From e04a4c7650a9849286881ef3730528ac8767bc5c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 15 Jun 2024 20:29:46 +0200 Subject: [PATCH 45/83] Update _index.ts --- web/src/engine/websites/_index.ts | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index b19c7247b1..862f260abb 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -232,6 +232,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -293,6 +294,7 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -338,6 +340,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -411,6 +414,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -504,6 +508,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -518,6 +523,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -558,6 +564,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawMangatop } from './RawMangatop'; export { default as RawSenManga } from './RawSenManga'; @@ -676,6 +683,7 @@ export { default as Toti } from './Toti'; export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TritiniaScans } from './TritiniaScans'; +export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenQQ } from './TruyenQQ'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; @@ -713,6 +721,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -788,7 +798,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -805,7 +814,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; export { default as MangaHereFun } from './legacy/MangaHereFun'; @@ -824,7 +832,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -888,7 +895,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VerComicsPorno } from './legacy/VerComicsPorno'; export { default as VerMangasPorno } from './legacy/VerMangasPorno'; @@ -899,8 +905,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 9eaed81839b7a61aec9cf7d1d0bb9a8a959922d5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 6 Jul 2024 20:12:59 +0200 Subject: [PATCH 46/83] add bookmarks mapping --- web/src/engine/transformers/BookmarkConverter.ts | 1 + web/src/engine/transformers/BookmarkConverter_test.ts | 2 ++ 2 files changed, 3 insertions(+) diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index 7cd3f48a18..705a306d30 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -25,6 +25,7 @@ const legacyWebsiteIdentifierMap = { 'kisscomic': 'readcomiconline', 'komikav': 'apkomik', 'kumascans': 'retsu', + 'lovehug': 'welovemanga', 'lyrascans': 'quantumscans', //https://www.mangaupdates.com/groups.html?id=35005683580 'Formerly known as LyraScans' 'mangamx': 'mangaoni', 'manganel': 'manganato', diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index ab7ea4a67e..7d4d311d7d 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -77,10 +77,12 @@ describe('BookmarkConverter', () => { { sourceID: 'flamescans-org', targetID: 'flamecomics' }, { sourceID: 'galaxyaction', targetID: 'galaxymanga' }, { sourceID: 'gateanimemanga', targetID: 'gatemanga' }, + { sourceID: 'kissaway', targetID: 'klmanga' }, { sourceID: 'kisscomic', targetID: 'readcomiconline' }, { sourceID: 'komikav', targetID: 'apkomik' }, { sourceID: 'kumascans', targetID: 'retsu' }, { sourceID: 'imperioscans', targetID: 'neroxus' }, + { sourceID: 'lovehug', targetID: 'welovemanga' }, { sourceID: 'lyrascans', targetID: 'quantumscans' }, { sourceID: 'mangamx', targetID: 'mangaoni' }, { sourceID: 'manganel', targetID: 'manganato' }, From e5679e7409ca4f9e297ed2efeb612c83f3b6cbd2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 15:41:22 +0200 Subject: [PATCH 47/83] Remove TruyenChapVN dead --- web/src/engine/websites/TruyenChapVn.ts | 34 -------------------- web/src/engine/websites/TruyenChapVn.webp | Bin 460 -> 0 bytes web/src/engine/websites/TruyenChapVn_e2e.ts | 26 --------------- web/src/engine/websites/_index.ts | 1 - 4 files changed, 61 deletions(-) delete mode 100644 web/src/engine/websites/TruyenChapVn.ts delete mode 100644 web/src/engine/websites/TruyenChapVn.webp delete mode 100644 web/src/engine/websites/TruyenChapVn_e2e.ts diff --git a/web/src/engine/websites/TruyenChapVn.ts b/web/src/engine/websites/TruyenChapVn.ts deleted file mode 100644 index 2b0d6ef760..0000000000 --- a/web/src/engine/websites/TruyenChapVn.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './TruyenChapVn.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import * as FlatManga from './decorators/FlatManga'; -function MangaExtractor(anchor: HTMLAnchorElement) { - return { - id: anchor.pathname, - title: anchor.text.replace(/\(chap.vn\)/i, '').trim() - }; -} -function MangaLabelExtractor(element: HTMLElement) { - return element.textContent.replace(/\(chap.vn\)/i, '').trim(); -} - -@Common.MangaCSS(/^{origin}\/truyen\/[^/]+\/$/, 'div.page-header h1#tables', MangaLabelExtractor) -@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, MangaExtractor) -@Common.PagesSinglePageCSS('img.chapter-img') -@Common.ImageAjax() -export default class extends DecoratableMangaScraper { - - public constructor() { - super('truyenchapvn', `TruyenChapVn`, 'https://truyen.chap.vn', Tags.Language.Vietnamese, Tags.Media.Manga, Tags.Source.Aggregator); - } - - public override get Icon() { - return icon; - } - - public override async FetchChapters(manga: Manga): Promise { - const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga); - return chapters.map(chapter => new Chapter(this, manga, chapter.Identifier, chapter.Title.replace(/\(chap.vn\)/i, '').trim())); - } -} \ No newline at end of file diff --git a/web/src/engine/websites/TruyenChapVn.webp b/web/src/engine/websites/TruyenChapVn.webp deleted file mode 100644 index 1c7d49f435413c0afb15a9c23d9123d97159b924..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 460 zcmV;-0WvaJxva2zyjAnUkWTw5{~;Avso$*ZVgv=!M$Z=X z^Q{o&x6)kzlP_f#)cC;fx$N`+0RFhdPjsJ741fG9Ss(tu_yhm-27koa{z0FgW@l~O z+eo7`S){S`9Ef(%SYkCLF}a^y-+y#zqi_Uw%XN9#LZNOmh1Q{bNl01w zh0ooTD{NxLwk28EXN4MzM56w3hMgu`GQXj$C!0p7(MBAcEhP7OH3<)YZbM)NtN&t1 zew_|YXkv>#X{5JGn_YJU@*T|>g;~R6-A2GZacW)r4%KcjtM1xvrdIdyJ~YGPfWB6E zV$0MDO0`A (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 81a968ff07..c3ed139066 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -693,7 +693,6 @@ export { default as TraduccionesAmistosas } from './TraduccionesAmistosas'; export { default as TraduccionesMoonlight } from './TraduccionesMoonlight'; export { default as TresDaos } from './TresDaos'; export { default as TritiniaScans } from './TritiniaScans'; -export { default as TruyenChapVn } from './TruyenChapVn'; export { default as TruyenQQ } from './TruyenQQ'; export { default as TruyenTranhDammy } from './TruyenTranhDammy'; export { default as TruyenTranhOnline } from './TruyenTranhOnline'; From f5fdf6a393db4b588f945b780b04f81dc9333b02 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 16:16:05 +0200 Subject: [PATCH 48/83] Update _index.ts --- web/src/engine/websites/_index.ts | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 392e5b25b9..aa7c81f065 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -238,6 +238,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -302,6 +303,7 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; +export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; @@ -346,6 +348,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -424,6 +427,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -519,6 +523,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; @@ -534,6 +539,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -576,6 +582,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangatop } from './RawMangatop'; @@ -739,6 +746,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -812,7 +821,6 @@ export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -828,7 +836,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as MangaCat } from './legacy/MangaCat'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; export { default as MangaHereFun } from './legacy/MangaHereFun'; @@ -846,7 +853,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -908,7 +914,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VizShonenJump } from './legacy/VizShonenJump'; export { default as VRVCrunchyroll } from './legacy/VRVCrunchyroll'; @@ -917,8 +922,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From 76965a04f9a6cf26bf1dd3149858cf9da92bde31 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 16:23:15 +0200 Subject: [PATCH 49/83] KLmanga : get rid of scripts --- web/src/engine/websites/KLManga.ts | 90 +++++++++++++++------------- web/src/engine/websites/NicoManga.ts | 3 +- 2 files changed, 50 insertions(+), 43 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 2cb1e22f4f..711356ecd8 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -1,50 +1,12 @@ import { Tags } from '../Tags'; import icon from './KLManga.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; - -const chapterScript = ` - new Promise(async resolve => { - const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - let randomEndpoint = ''; - for (let o = 0; o < 25; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); - const uri = new URL(randomEndpoint + '.lstc', window.location.origin); - uri.searchParams.set('slug', dataL); - const response = await fetch(uri); - data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('a.chapter[title]')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title - }; - }); - resolve(chapters); - }); -`; - -const pageScript = ` - new Promise(async resolve => { - const chapId = document.querySelector('input#chapter').value; - const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - let randomEndpoint = ''; - for (let o = 0; o < 30; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); - const uri = new URL(randomEndpoint + '.iog', window.location.origin); - uri.searchParams.set('cid', chapId); - const response = await fetch(uri); - const data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('img.chapter-img[alt*="Page"]')]; - resolve(nodes.map(picture => picture.src).filter(image => !image.match(/olimposcan/))); - }); -`; +import { FetchCSS, FetchHTML } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) -@Common.ChaptersSinglePageJS(chapterScript, 1000) -@Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { @@ -56,4 +18,50 @@ export default class extends DecoratableMangaScraper { return icon; } -} + public override async FetchChapters(manga: Manga): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var dataL\s*=\s*['"](.*)['"]/)[1]; + const apiUrl = this.GenerateRandomEndPoint(25, '.lstc'); + apiUrl.searchParams.set('slug', mangaSlug); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'a.chapter[title]'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); + } + + public override async FetchPages(chapter: Chapter): Promise { + let request = new Request(new URL(chapter.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + + const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; + const apiUrl = this.GenerateRandomEndPoint(30, '.iog'); + apiUrl.searchParams.set('cid', chapterid); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'img.chapter-img[alt*="Page"]'); + return data + .map(picture => new Page(this, chapter, new URL(picture.getAttribute('src'), this.URI), { Referer: this.URI.origin })) + .filter(page => !page.Link.href.match(/olimposcan/)); + } + + private GenerateRandomEndPoint(length: number, suffix: string): URL { + const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let randomEndpoint = ''; + for (let o = 0; o < length; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); + return new URL(randomEndpoint + suffix, this.URI); + } + +} \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index d4c765dddc..c640e94fe1 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -42,8 +42,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchPages(chapter: Chapter): Promise { - const url = new URL(chapter.Identifier, this.URI); - let request = new Request(url, { + let request = new Request(new URL(chapter.Identifier, this.URI), { headers: { 'Referer': this.URI.origin } From 47eb799c2f4c4eeefe5d3ef0173618ff05876290 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:08:27 +0200 Subject: [PATCH 50/83] Mangagun : no scripts and handle antiDdoSS --- web/src/engine/websites/MangaGun.ts | 78 ++++++++++++++----------- web/src/engine/websites/MangaGun_e2e.ts | 2 +- 2 files changed, 46 insertions(+), 34 deletions(-) diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index 4d31663265..485785a729 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -1,44 +1,18 @@ import { Tags } from '../Tags'; import icon from './MangaGun.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; +import { FetchCSS, FetchHTML, FetchWindowScript, } from '../platform/FetchProvider'; +import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; -const chapterScript = ` - new Promise(async resolve => { - const uri = new URL('app/manga/controllers/cont.Listchapter.php', window.location.origin); - uri.searchParams.set('slug', sLugs); - const response = await fetch(uri); - data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('a')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title.trim() - }; - }); - resolve(chapters); - }); -`; - -const pageScript = ` - new Promise(async resolve => { - const chapId = document.querySelector('input#chapter').value; - const uri = new URL('app/manga/controllers/cont.Showimage.php', window.location.origin); - uri.searchParams.set('cid', chapId); - const response = await fetch(uri); - const data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('img')]; - resolve(nodes.map(picture => picture.dataset.src)); - }); -`; +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; +}); @Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@Common.ChaptersSinglePageJS(chapterScript, 1000) -@Common.PagesSinglePageJS(pageScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -48,4 +22,42 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async FetchChapters(manga: Manga): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"](.*)['"]/)[1]; + const apiUrl = new URL('/app/manga/controllers/cont.Listchapter.php', this.URI); + apiUrl.searchParams.set('slug', mangaSlug); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'a'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); + } + + public override async FetchPages(chapter: Chapter): Promise { + let request = new Request(new URL(chapter.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + + const chapterid = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//increased delay for AntiScrapper + const apiUrl = new URL('/app/manga/controllers/cont.Showimage.php', this.URI); + apiUrl.searchParams.set('cid', chapterid); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'img'); + return data.map(picture => new Page(this, chapter, new URL(picture.dataset.src, this.URI), { Referer: this.URI.origin })); + } } diff --git a/web/src/engine/websites/MangaGun_e2e.ts b/web/src/engine/websites/MangaGun_e2e.ts index d69dfcffb4..aed168e391 100644 --- a/web/src/engine/websites/MangaGun_e2e.ts +++ b/web/src/engine/websites/MangaGun_e2e.ts @@ -12,7 +12,7 @@ const config = { title: 'OSHI NO KO' }, child: { - id: '/gunchap-146-shmg-oshi-no-ko-raw.html', + id: '/read-oshi-no-ko-raw-chapter-146.html', title: 'Chapter 146' }, entry: { From 5036bf746016dd2939bbc67281343f5c0a9e58b6 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:17:12 +0200 Subject: [PATCH 51/83] Manga-TR : filter manga without title in list --- web/src/engine/websites/MangaTR.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 64cdc266b2..fe620d346a 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -1,6 +1,6 @@ import { Tags } from '../Tags'; import icon from './MangaTR.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type MangaPlugin, type Manga } from '../providers/MangaPlugin'; import { FetchCSS, FetchWindowScript } from '../platform/FetchProvider'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; @@ -10,7 +10,6 @@ function MangaLabelExtractor(element: HTMLTitleElement) { } @Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, 'body title', MangaLabelExtractor) -@Common.MangasSinglePageCSS('/manga-list.html', FlatManga.queryMangas) @FlatManga.PagesSinglePageCSS('img.chapter-img') @Common.ImageAjax() export default class extends DecoratableMangaScraper { @@ -26,13 +25,17 @@ export default class extends DecoratableMangaScraper { return FetchWindowScript(request, `window.cookieStore.set('read_type', '1')`, 0, 30000); } + public override async FetchMangas(provider: MangaPlugin): Promise { + return (await Common.FetchMangasSinglePageCSS.call(this, provider, '/manga-list.html', FlatManga.queryMangas)).filter(manga => manga.Title); + } + public override async FetchChapters(manga: Manga): Promise { const chapterList = []; for (let page = 1, run = true; run; page++) { const chapters = await this.GetChaptersFromPage(manga, page); chapters.length > 0 ? chapterList.push(...chapters) : run = false; } - return chapterList.distinct(); + return chapterList; } private async GetChaptersFromPage(manga: Manga, page: number): Promise{ const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; From 85e6ebcb71e12c627de91512e36114dd5c7062ee Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:32:40 +0200 Subject: [PATCH 52/83] fix test --- web/src/engine/websites/MangaTR_e2e.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/MangaTR_e2e.ts b/web/src/engine/websites/MangaTR_e2e.ts index 040301f251..177f0a9c07 100644 --- a/web/src/engine/websites/MangaTR_e2e.ts +++ b/web/src/engine/websites/MangaTR_e2e.ts @@ -17,8 +17,8 @@ const config = { }, entry: { index: 1, - size: 376_632, - type: 'image/jpeg' + size: 342_746, + type: 'image/webp' } }; From fce396fe4856a13379d96a43db69faed913b8c48 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:33:03 +0200 Subject: [PATCH 53/83] minor code changes --- web/src/engine/websites/MangaGun.ts | 6 ++---- web/src/engine/websites/MangaTR.ts | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index 485785a729..8b2300b260 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -31,8 +31,7 @@ export default class extends DecoratableMangaScraper { }); const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"](.*)['"]/)[1]; - const apiUrl = new URL('/app/manga/controllers/cont.Listchapter.php', this.URI); - apiUrl.searchParams.set('slug', mangaSlug); + const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?slug=${mangaSlug}`, this.URI); request = new Request(apiUrl, { headers: { 'Referer': this.URI.origin @@ -50,8 +49,7 @@ export default class extends DecoratableMangaScraper { }); const chapterid = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//increased delay for AntiScrapper - const apiUrl = new URL('/app/manga/controllers/cont.Showimage.php', this.URI); - apiUrl.searchParams.set('cid', chapterid); + const apiUrl = new URL(`/app/manga/controllers/cont.Showimage.php?cid=${chapterid}`, this.URI); request = new Request(apiUrl, { headers: { 'Referer': this.URI.origin diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index fe620d346a..ea7c103c74 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -38,8 +38,8 @@ export default class extends DecoratableMangaScraper { return chapterList; } private async GetChaptersFromPage(manga: Manga, page: number): Promise{ - const mangaslug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; - const url = new URL('/cek/fetch_pages_manga.php?manga_cek=' + mangaslug, this.URI); + const mangaSlug = manga.Identifier.match(/manga-([^/]+)\.html/)[1]; + const url = new URL(`/cek/fetch_pages_manga.php?manga_cek=${mangaSlug}`, this.URI); const request = new Request(url, { method: 'POST', body: 'page=' + page, From 290c5c564bb43dc8d00dbc2166d418f03210d048 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:56:10 +0200 Subject: [PATCH 54/83] fix type --- web/src/engine/websites/KLManga.ts | 2 +- web/src/engine/websites/MangaGun.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 711356ecd8..033b35837c 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -51,7 +51,7 @@ export default class extends DecoratableMangaScraper { 'Referer': this.URI.origin } }); - const data = await FetchCSS(request, 'img.chapter-img[alt*="Page"]'); + const data = await FetchCSS(request, 'img.chapter-img[alt*="Page"]'); return data .map(picture => new Page(this, chapter, new URL(picture.getAttribute('src'), this.URI), { Referer: this.URI.origin })) .filter(page => !page.Link.href.match(/olimposcan/)); diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index 8b2300b260..ac2ef3b525 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -55,7 +55,7 @@ export default class extends DecoratableMangaScraper { 'Referer': this.URI.origin } }); - const data = await FetchCSS(request, 'img'); + const data = await FetchCSS(request, 'img'); return data.map(picture => new Page(this, chapter, new URL(picture.dataset.src, this.URI), { Referer: this.URI.origin })); } } From b4b457cc0300e333f0906cedd33076567a18bacb Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 17:58:25 +0200 Subject: [PATCH 55/83] Nicomanga : handle antiddoss, remove scripts --- web/src/engine/websites/NicoManga.ts | 54 ++++++++++++------------ web/src/engine/websites/NicoManga_e2e.ts | 3 +- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index c640e94fe1..9a42e82a00 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -1,35 +1,18 @@ import { Tags } from '../Tags'; import icon from './NicoManga.webp'; -import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS } from '../platform/FetchProvider'; +import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; +import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; -const chapterScript = ` - new Promise(async (resolve, reject) => { - try { - const uri = new URL('app/manga/controllers/cont.Listchapterapi.php', window.location.origin); - uri.searchParams.set('slug', sLugs); - const response = await fetch(uri); - data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('ul > a')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title - }; - }); - resolve(chapters); - } catch (error) { - reject(error); - } - }); -`; +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; +}); @Common.MangaCSS(/^{origin}\/manga[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { @@ -41,19 +24,36 @@ export default class extends DecoratableMangaScraper { return icon; } + public override async FetchChapters(manga: Manga): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"](.*)['"]/)[1]; + const apiUrl = new URL(`/app/manga/controllers/cont.Listchapterapi.php?slug=${mangaSlug}`, this.URI); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'ul > a'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); + } + public override async FetchPages(chapter: Chapter): Promise { let request = new Request(new URL(chapter.Identifier, this.URI), { headers: { 'Referer': this.URI.origin } }); - const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; + const chapterid = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//increased delay for AntiScrapper request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI), { headers: { 'Referer': this.URI.origin } }); - const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.src.replace(/\n/g, ''), this.URI))); + const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.srcset.replace(/\n/g, ''), this.URI), { Referer: this.URI.origin })); } } \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga_e2e.ts b/web/src/engine/websites/NicoManga_e2e.ts index a158847ca9..a1d1d047bb 100644 --- a/web/src/engine/websites/NicoManga_e2e.ts +++ b/web/src/engine/websites/NicoManga_e2e.ts @@ -13,7 +13,8 @@ const config = { }, child: { id: '/read-kage-no-jitsuryokusha-ni-naritakute-raw-chapter-60.2.html', - title: 'Chapter 60.2' + title: 'Chapter 60.2', + timeout: 15000 }, entry: { index: 0, From 4a92af287ec6331e2539228dca16c8e31d188faf Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 18:29:40 +0200 Subject: [PATCH 56/83] fix variable regexp --- web/src/engine/websites/KLManga.ts | 2 +- web/src/engine/websites/MangaGun.ts | 2 +- web/src/engine/websites/NicoManga.ts | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 033b35837c..7f589ac83f 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { 'Referer': this.URI.origin } }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var dataL\s*=\s*['"](.*)['"]/)[1]; + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var dataL\s*=\s*['"]([^'"]+)['"]/)[1]; const apiUrl = this.GenerateRandomEndPoint(25, '.lstc'); apiUrl.searchParams.set('slug', mangaSlug); request = new Request(apiUrl, { diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index ac2ef3b525..e08169cc68 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -30,7 +30,7 @@ export default class extends DecoratableMangaScraper { } }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"](.*)['"]/)[1]; + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?slug=${mangaSlug}`, this.URI); request = new Request(apiUrl, { headers: { diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 9a42e82a00..2d4fcd5995 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -30,7 +30,7 @@ export default class extends DecoratableMangaScraper { 'Referer': this.URI.origin } }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"](.*)['"]/)[1]; + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; const apiUrl = new URL(`/app/manga/controllers/cont.Listchapterapi.php?slug=${mangaSlug}`, this.URI); request = new Request(apiUrl, { headers: { From 42cbb4d6eb8405108f035197cb702a94aa725882 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 18:37:26 +0200 Subject: [PATCH 57/83] Rawinu : handle antiddoss and remove scripts --- web/src/engine/websites/RawInu.ts | 81 ++++++++++++++++++------------- 1 file changed, 46 insertions(+), 35 deletions(-) diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index c58f08bb3f..8a1d83846a 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -1,45 +1,18 @@ import { Tags } from '../Tags'; import icon from './RawInu.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; +import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; +import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; -const chapterScript = ` - new Promise(async resolve => { - const uri = new URL('app/manga/controllers/cont.Listchapter.php', window.location.origin); - const slug = document.documentElement.innerHTML.match(/var slugs\\s*=\\s*'([^']+)/i)[1]; - uri.searchParams.set('slug', slug); - const response = await fetch(uri); - data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('a')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title.trim() - }; - }); - resolve(chapters); - }); -`; - -const pageScript = ` - new Promise(async resolve => { - const chapId = document.querySelector('input#chapter').value; - const uri = new URL('app/manga/controllers/cont.imagesChap.php', window.location.origin); - uri.searchParams.set('cid', chapId); - const response = await fetch(uri); - const data = await response.text(); - const dom = new DOMParser().parseFromString(data, "text/html"); - const nodes = [...dom.querySelectorAll('img')]; - resolve(nodes.map(picture => picture.dataset.src.trim())); - }); -`; +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; +}); -@Common.MangaCSS(/^{origin}\/[^.]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangaCSS(/^{origin}\/[^.]+\.html$/, 'li.breadcrumb-item.active', FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@Common.ChaptersSinglePageJS(chapterScript, 500) -@Common.PagesSinglePageJS(pageScript, 500) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -49,4 +22,42 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async Initialize(): Promise { + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), `window`, 3000, 30000);//trigger antiDDOSS + } + + public override async FetchChapters(manga: Manga): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; + const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?slug=${mangaSlug}`, this.URI); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'a'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); + } + + public override async FetchPages(chapter: Chapter): Promise { + let request = new Request(new URL(chapter.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; + request = new Request(new URL(`/app/manga/controllers/cont.imagesChap.php?cid=${chapterid}`, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const nodes = await FetchCSS(request, 'img'); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.src, this.URI), { Referer: this.URI.origin })); + } + } \ No newline at end of file From 5327e2e13f23f0a5ccf3df8cad0d4791ee5d7ecb Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 18:46:56 +0200 Subject: [PATCH 58/83] Weloma: handle AntiDDoss --- web/src/engine/websites/RawInu.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index 8a1d83846a..0f7e33a550 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), `window`, 3000, 30000);//trigger antiDDOSS + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 30000);//trigger antiDDOSS } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index f1360f6c89..bf1ec34a4f 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -3,6 +3,13 @@ import icon from './WeLoMa.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; +import { FetchWindowScript } from '../platform/FetchProvider'; +import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; + +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; +}); @Common.MangaCSS(/^{origin}\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @@ -17,4 +24,8 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async Initialize(): Promise { + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 30000);//trigger antiDDOSS + } } \ No newline at end of file From 263c1b8d5392805bc8505570887d618092496e6c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 18:59:01 +0200 Subject: [PATCH 59/83] reduce initial timeout --- web/src/engine/websites/RawInu.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index 0f7e33a550..0feb59d3eb 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 30000);//trigger antiDDOSS + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 15000);//trigger antiDDOSS } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index bf1ec34a4f..d09f8045f0 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -26,6 +26,6 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 30000);//trigger antiDDOSS + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 15000);//trigger antiDDOSS } } \ No newline at end of file From 7589b6d250d61ed12669f45332ac15af687c6874 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 18:59:49 +0200 Subject: [PATCH 60/83] WeloveManga : handle anti ddoss & remove scripts --- web/src/engine/websites/WeLoveManga.ts | 46 ++++++++++++++++---------- 1 file changed, 29 insertions(+), 17 deletions(-) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index 9a3ee26964..db4c2c4347 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -1,27 +1,18 @@ import { Tags } from '../Tags'; import icon from './WeLoveManga.webp'; -import { type Chapter, DecoratableMangaScraper, Page } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS } from '../platform/FetchProvider'; +import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; +import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; -const chapterScript = ` - new Promise(async resolve => { - loadChapterData(mIds); - const nodes = [...document.querySelectorAll('ul.list-chapters a[title]')]; - const chapters= nodes.map(chapter => { - return { - id : chapter.pathname, - title : chapter.title - }; - }); - resolve(chapters); - }); -`; +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; +}); @Common.MangaCSS(/^{origin}\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@Common.ChaptersSinglePageJS(chapterScript, 1000) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -32,6 +23,27 @@ export default class extends DecoratableMangaScraper { return icon; } + public override async Initialize(): Promise { + return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 15000);//trigger antiDDOSS + } + + public override async FetchChapters(manga: Manga): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var mIds\s*=\s*['"]([^'"]+)['"]/)[1]; + const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?mid=${mangaSlug}`, this.URI); + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, 'a'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); + } + public override async FetchPages(chapter: Chapter): Promise { const url = new URL(chapter.Identifier, this.URI); let request = new Request(url.href, { @@ -46,7 +58,7 @@ export default class extends DecoratableMangaScraper { } }); const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.original.replace(/\n/g, ''), this.URI))); + return nodes.map(image => new Page(this, chapter, new URL(image.dataset.srcset.replace(/\n/g, ''), this.URI), { Referer: this.URI.origin })); } } \ No newline at end of file From 5589a4b7ff5c881e85e2643ea4f55c55cf540344 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 19:58:30 +0200 Subject: [PATCH 61/83] remove useless code --- web/src/engine/websites/MangaGun.ts | 6 ------ web/src/engine/websites/NicoManga.ts | 6 ------ web/src/engine/websites/RawInu.ts | 6 ------ web/src/engine/websites/WeLoMa.ts | 6 ------ web/src/engine/websites/WeLoveManga.ts | 6 ------ 5 files changed, 30 deletions(-) diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index e08169cc68..c2746a0c42 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -4,12 +4,6 @@ import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; import { FetchCSS, FetchHTML, FetchWindowScript, } from '../platform/FetchProvider'; -import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; - -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; -}); @Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 2d4fcd5995..97dfaecc15 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -4,12 +4,6 @@ import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; -import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; - -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; -}); @Common.MangaCSS(/^{origin}\/manga[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index 0feb59d3eb..a2b6fc2392 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -4,12 +4,6 @@ import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; -import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; - -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; -}); @Common.MangaCSS(/^{origin}\/[^.]+\.html$/, 'li.breadcrumb-item.active', FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index d09f8045f0..04eabdd6a8 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -4,12 +4,6 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; import { FetchWindowScript } from '../platform/FetchProvider'; -import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; - -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; -}); @Common.MangaCSS(/^{origin}\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index db4c2c4347..e2fa522a1f 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -4,12 +4,6 @@ import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; -import { AddAntiScrapingDetection, FetchRedirection } from '../platform/AntiScrapingDetection'; - -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - return dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`) ? FetchRedirection.Automatic : undefined; -}); @Common.MangaCSS(/^{origin}\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) From 06a71c1fffbc39b3deb782a24b004effdcdaad7a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 22 Jul 2024 20:06:11 +0200 Subject: [PATCH 62/83] Update WeLoveManga.ts --- web/src/engine/websites/WeLoveManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index e2fa522a1f..f42f8b9130 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -46,7 +46,7 @@ export default class extends DecoratableMangaScraper { } }); const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - request = new Request(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI).href, { + request = new Request(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI), { headers: { 'Referer': this.URI.origin, } From 177a96de2743fbd5e189c4af07f4657a610e3790 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Jul 2024 12:37:04 +0200 Subject: [PATCH 63/83] remove Manga33 dead website --- web/src/engine/websites/Manga33.ts | 25 ------------------------ web/src/engine/websites/Manga33.webp | Bin 540 -> 0 bytes web/src/engine/websites/Manga33_e2e.ts | 26 ------------------------- web/src/engine/websites/_index.ts | 1 - 4 files changed, 52 deletions(-) delete mode 100644 web/src/engine/websites/Manga33.ts delete mode 100644 web/src/engine/websites/Manga33.webp delete mode 100644 web/src/engine/websites/Manga33_e2e.ts diff --git a/web/src/engine/websites/Manga33.ts b/web/src/engine/websites/Manga33.ts deleted file mode 100644 index 7472a7976e..0000000000 --- a/web/src/engine/websites/Manga33.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './Manga33.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import * as FlatManga from './decorators/FlatManga'; - -@Common.MangaCSS(/^{origin}\/manga\/[^/]+\.html$/, FlatManga.queryMangaTitle) -@Common.MangasMultiPageCSS('/list/lastdotime-{page}.html', FlatManga.queryMangas, 0) -@Common.PagesSinglePageCSS(FlatManga.queryPages) -@Common.ImageAjax() -export default class extends DecoratableMangaScraper { - - public constructor() { - super('manga33', `Manga33`, 'https://www.manga333.com', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); - } - - public override get Icon() { - return icon; - } - - public override async FetchChapters(manga: Manga): Promise { - const chapters = await FlatManga.FetchChaptersSinglePageCSS.call(this, manga, FlatManga.queryChapters); - return chapters.map(chapter => new Chapter(this, manga, chapter.Identifier.replace(/-\d+.html$/, '-all.html'), chapter.Title)); - } -} diff --git a/web/src/engine/websites/Manga33.webp b/web/src/engine/websites/Manga33.webp deleted file mode 100644 index 218b76c513f53b0641a116f3b6ca1d38842f9f8d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 540 zcmV+%0^|KsNk&E#0ssJ4MM6+kP&gn60ssJT4FH`1DnI~006x7=olB=AqM^I92!pJ7~anQ-BRT1s_jl3F4 z<`aUyBuY>9JBn7tnG6T9fI38iF@fh#4%Wi-*!-0(hOhfePKf{j{+%M#d?%WjCA&i+ za@vc({PLe9*zYL#1#$oMi~VqG@eaxR%iuZ6labXCYIrG_PCj|+VTCBuSN8f$ksuDe znK}On+hQOfhULBJT??t$O>r+he+k2)swVO-|C8chc9Y~Eb7l6(D!H38o%`Qo-t|ka zA@LQj>M=?31N9JJh#gB>F`B)x&J;Z26$2b|@EwRCij)M5*p0Gy8ZsQ``v!;<2QU$U zt1J_IvFKO8?>X<6W~#0E(6yAslcqg99DH|0!HzkL&Pk&FwABUJx4dgUXVM$8??8Sc zLX8D_?<0N@_4*|@<$F6;U(x>3G5NO_xN8%rbM2l@7dR#0|0I+{iYe>meJ zY2jxe*fEg$C?FMl7FnoHqn33i7KbZM4`Cg7)la()YZej)Po%#kcoLxR{L~1^{!pCY z#=2RnRUx)N=^`u{;T0A}9>+zu{L;l@G3>lWaCBIO(%|E)7G3|4i}&0f+EOuZIhTOt e0V!%&>oou)>u<0-oWta)=0#cPJ>e_c0002wR{-e% diff --git a/web/src/engine/websites/Manga33_e2e.ts b/web/src/engine/websites/Manga33_e2e.ts deleted file mode 100644 index a8b93fdda0..0000000000 --- a/web/src/engine/websites/Manga33_e2e.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { describe } from 'vitest'; -import { TestFixture } from '../../../test/WebsitesFixture'; - -const config = { - plugin: { - id: 'manga33', - title: 'Manga33' - }, - container: { - url: 'https://www.manga333.com/manga/black-clover.html', - id: '/manga/black-clover.html', - title: 'Black Clover' - }, - child: { - id: '/manga/black-clover-368-all.html', - title: 'Chapter 368' - }, - entry: { - index: 0, - size: 516_711, - type: 'image/jpeg', - } -}; - -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index aa7c81f065..5a3f10aa50 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -303,7 +303,6 @@ export { default as MaidScan } from './MaidScan'; export { default as MajorScans } from './MajorScans'; export { default as Manga3S } from './Manga3S'; export { default as Manga18FX } from './Manga18FX'; -export { default as Manga33 } from './Manga33'; export { default as Manga68 } from './Manga68'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; From d61080a3d1383fcaf07e6bfdb7e2ee3b9c779a7e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Jul 2024 12:41:05 +0200 Subject: [PATCH 64/83] OlimpoScans : change domain --- web/src/engine/websites/OlimpoScans.ts | 2 +- web/src/engine/websites/OlimpoScans_e2e.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/OlimpoScans.ts b/web/src/engine/websites/OlimpoScans.ts index 8038e5ab8b..182ad038c6 100644 --- a/web/src/engine/websites/OlimpoScans.ts +++ b/web/src/engine/websites/OlimpoScans.ts @@ -10,7 +10,7 @@ import * as FlatManga from './decorators/FlatManga'; @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { - super('olimposcans', `OlimpoScans`, 'https://olimposcans.com', Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Language.Spanish, Tags.Source.Scanlator); + super('olimposcans', `OlimpoScans`, 'https://leerolimpo.com', Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Language.Spanish, Tags.Source.Scanlator); } public override get Icon() { diff --git a/web/src/engine/websites/OlimpoScans_e2e.ts b/web/src/engine/websites/OlimpoScans_e2e.ts index 468fcfe40b..c4725f70c6 100644 --- a/web/src/engine/websites/OlimpoScans_e2e.ts +++ b/web/src/engine/websites/OlimpoScans_e2e.ts @@ -7,7 +7,7 @@ const config = { title: 'OlimpoScans' }, container: { - url: 'https://olimposcans.com/comic-bjorn-el-barbaro.html', + url: 'https://leerolimpo.com/comic-bjorn-el-barbaro.html', id: '/comic-bjorn-el-barbaro.html', title: 'BJORN EL BARBARO' }, From 5bd680fac67dbaf5425279e1c9d3b5c30d9ffa89 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Jul 2024 12:45:39 +0200 Subject: [PATCH 65/83] Update MangaTR.ts --- web/src/engine/websites/MangaTR.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index ea7c103c74..b73ad6a674 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -52,7 +52,7 @@ export default class extends DecoratableMangaScraper { const data = await FetchCSS(request, 'table.table tr td.table-bordered:first-of-type > a'); const escapedMangaTitle = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); const regexp = new RegExp(escapedMangaTitle, 'i'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(regexp, '').trim())); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(regexp, '').trim() || chapter.text.trim())); } } \ No newline at end of file From cab102af66d91d5313ca5079ea3f70badd527c7b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Jul 2024 14:26:39 +0200 Subject: [PATCH 66/83] Rewrite of FlatManga websites Using Ajax decorators for chapters & pages --- web/src/engine/websites/KLManga.ts | 60 +----- web/src/engine/websites/MangaGun.ts | 44 +--- web/src/engine/websites/NicoManga.ts | 38 +--- web/src/engine/websites/RawInu.ts | 40 +--- web/src/engine/websites/WeLoveManga.ts | 41 +--- .../engine/websites/decorators/FlatManga.ts | 204 ++++++++++++++---- 6 files changed, 184 insertions(+), 243 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 7f589ac83f..911e636573 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -1,12 +1,21 @@ import { Tags } from '../Tags'; import icon from './KLManga.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchHTML } from '../platform/FetchProvider'; + +function GenerateRandomEndPoint(length: number, suffix: string): string { + const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; + let randomEndpoint = ''; + for (let o = 0; o < length; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); + return randomEndpoint + suffix; +} @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) +@FlatManga.ChaptersSinglePageAJAX(GenerateRandomEndPoint(25, '.lstc?slug='), 'dataL', 'a.chapter[title]') +@FlatManga.PagesSinglePageAJAX(GenerateRandomEndPoint(30, '.iog?cid='), 'img.chapter-img[alt*="Page"]', [/olimposcan/] ) + @Common.ImageAjax() export default class extends DecoratableMangaScraper { @@ -17,51 +26,4 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } - - public override async FetchChapters(manga: Manga): Promise { - let request = new Request(new URL(manga.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var dataL\s*=\s*['"]([^'"]+)['"]/)[1]; - const apiUrl = this.GenerateRandomEndPoint(25, '.lstc'); - apiUrl.searchParams.set('slug', mangaSlug); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'a.chapter[title]'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); - } - - public override async FetchPages(chapter: Chapter): Promise { - let request = new Request(new URL(chapter.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - - const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - const apiUrl = this.GenerateRandomEndPoint(30, '.iog'); - apiUrl.searchParams.set('cid', chapterid); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'img.chapter-img[alt*="Page"]'); - return data - .map(picture => new Page(this, chapter, new URL(picture.getAttribute('src'), this.URI), { Referer: this.URI.origin })) - .filter(page => !page.Link.href.match(/olimposcan/)); - } - - private GenerateRandomEndPoint(length: number, suffix: string): URL { - const r = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'; - let randomEndpoint = ''; - for (let o = 0; o < length; o++) randomEndpoint += r.charAt(Math.floor(Math.random() * r.length)); - return new URL(randomEndpoint + suffix, this.URI); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/MangaGun.ts b/web/src/engine/websites/MangaGun.ts index c2746a0c42..2e9648ac0f 100644 --- a/web/src/engine/websites/MangaGun.ts +++ b/web/src/engine/websites/MangaGun.ts @@ -1,14 +1,16 @@ import { Tags } from '../Tags'; import icon from './MangaGun.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchHTML, FetchWindowScript, } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/manga-[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageAJAX('/app/manga/controllers/cont.Listchapter.php?slug=', 'sLugs') +@FlatManga.PagesSinglePageAJAX('/app/manga/controllers/cont.Showimage.php?cid=') @Common.ImageAjax() export default class extends DecoratableMangaScraper { + public constructor() { super('mangagun', `MangaGun`, 'https://mangagun.net', Tags.Language.English, Tags.Media.Manga, Tags.Media.Manhua, Tags.Media.Manhwa, Tags.Source.Aggregator); } @@ -16,40 +18,4 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } - - public override async FetchChapters(manga: Manga): Promise { - let request = new Request(new URL(manga.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; - const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?slug=${mangaSlug}`, this.URI); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'a'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); - } - - public override async FetchPages(chapter: Chapter): Promise { - let request = new Request(new URL(chapter.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - - const chapterid = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//increased delay for AntiScrapper - const apiUrl = new URL(`/app/manga/controllers/cont.Showimage.php?cid=${chapterid}`, this.URI); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'img'); - return data.map(picture => new Page(this, chapter, new URL(picture.dataset.src, this.URI), { Referer: this.URI.origin })); - } -} +} \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 97dfaecc15..06e06a772c 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -1,12 +1,13 @@ import { Tags } from '../Tags'; import icon from './NicoManga.webp'; -import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/manga[^/]+\.html$/, FlatManga.queryMangaTitle) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageAJAX('/app/manga/controllers/cont.Listchapterapi.php?slug=', 'sLugs', 'ul > a', Common.AnchorInfoExtractor(true)) +@FlatManga.PagesSinglePageAJAX('/app/manga/controllers/cont.imgsList.php?cid=', 'img.chapter-img:not([alt*="nicoscan"])') @Common.ImageAjax() export default class extends DecoratableMangaScraper { @@ -17,37 +18,4 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } - - public override async FetchChapters(manga: Manga): Promise { - let request = new Request(new URL(manga.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; - const apiUrl = new URL(`/app/manga/controllers/cont.Listchapterapi.php?slug=${mangaSlug}`, this.URI); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'ul > a'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); - } - - public override async FetchPages(chapter: Chapter): Promise { - let request = new Request(new URL(chapter.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const chapterid = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//increased delay for AntiScrapper - request = new Request(new URL(`/app/manga/controllers/cont.imgsList.php?cid=${chapterid}`, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.srcset.replace(/\n/g, ''), this.URI), { Referer: this.URI.origin })); - } } \ No newline at end of file diff --git a/web/src/engine/websites/RawInu.ts b/web/src/engine/websites/RawInu.ts index a2b6fc2392..4104c5d6ee 100644 --- a/web/src/engine/websites/RawInu.ts +++ b/web/src/engine/websites/RawInu.ts @@ -1,12 +1,14 @@ import { Tags } from '../Tags'; import icon from './RawInu.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; +import { FetchWindowScript } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/[^.]+\.html$/, 'li.breadcrumb-item.active', FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageAJAX('/app/manga/controllers/cont.Listchapter.php?slug=', 'sLugs') +@FlatManga.PagesSinglePageAJAX('/app/manga/controllers/cont.imagesChap.php?cid=') @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -20,38 +22,4 @@ export default class extends DecoratableMangaScraper { public override async Initialize(): Promise { return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 15000);//trigger antiDDOSS } - - public override async FetchChapters(manga: Manga): Promise { - let request = new Request(new URL(manga.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var sLugs\s*=\s*['"]([^'"]+)['"]/)[1]; - const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?slug=${mangaSlug}`, this.URI); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'a'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); - } - - public override async FetchPages(chapter: Chapter): Promise { - let request = new Request(new URL(chapter.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - request = new Request(new URL(`/app/manga/controllers/cont.imagesChap.php?cid=${chapterid}`, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const nodes = await FetchCSS(request, 'img'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.src, this.URI), { Referer: this.URI.origin })); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga.ts b/web/src/engine/websites/WeLoveManga.ts index f42f8b9130..88657d8566 100644 --- a/web/src/engine/websites/WeLoveManga.ts +++ b/web/src/engine/websites/WeLoveManga.ts @@ -1,12 +1,14 @@ import { Tags } from '../Tags'; import icon from './WeLoveManga.webp'; -import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; -import { FetchCSS, FetchHTML, FetchWindowScript } from '../platform/FetchProvider'; +import { FetchWindowScript } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/(mgraw-)?\d+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) +@FlatManga.ChaptersSinglePageAJAX('/app/manga/controllers/cont.Listchapter.php?mid=', 'mIds') +@FlatManga.PagesSinglePageAJAX('/app/manga/controllers/cont.listImg.php?cid=', 'img.chapter-img:not([alt*="nicoscan"])') @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -20,39 +22,4 @@ export default class extends DecoratableMangaScraper { public override async Initialize(): Promise { return await FetchWindowScript(new Request(new URL('/manga-list.html', this.URI)), 'true', 3000, 15000);//trigger antiDDOSS } - - public override async FetchChapters(manga: Manga): Promise { - let request = new Request(new URL(manga.Identifier, this.URI), { - headers: { - 'Referer': this.URI.origin - } - }); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(/var mIds\s*=\s*['"]([^'"]+)['"]/)[1]; - const apiUrl = new URL(`/app/manga/controllers/cont.Listchapter.php?mid=${mangaSlug}`, this.URI); - request = new Request(apiUrl, { - headers: { - 'Referer': this.URI.origin - } - }); - const data = await FetchCSS(request, 'a'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.title.trim())); - } - - public override async FetchPages(chapter: Chapter): Promise { - const url = new URL(chapter.Identifier, this.URI); - let request = new Request(url.href, { - headers: { - 'Referer': this.URI.origin, - } - }); - const chapterid = (await FetchCSS(request, 'input#chapter'))[0].value; - request = new Request(new URL(`/app/manga/controllers/cont.listImg.php?cid=${chapterid}`, this.URI), { - headers: { - 'Referer': this.URI.origin, - } - }); - const nodes = await FetchCSS(request, 'img.chapter-img:not([alt*="nicoscan"])'); - return nodes.map(image => new Page(this, chapter, new URL(image.dataset.srcset.replace(/\n/g, ''), this.URI), { Referer: this.URI.origin })); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index c7369bd2ac..98320bc019 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,4 +1,4 @@ -import { FetchCSS } from "../../platform/FetchProvider"; +import { FetchCSS, FetchHTML, FetchWindowScript } from "../../platform/FetchProvider"; import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; import * as Common from './Common'; @@ -15,7 +15,45 @@ export function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -export const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; +function ChapterExtractor(anchor: HTMLAnchorElement) { + if (anchor.dataset.href) { + anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); + } + const id = anchor.pathname; + const titleElement = anchor.querySelector('div.chapter-name'); + const title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); + return { + id, title + }; +} + +function CleanChaptertitle(manga: Manga, title: string): string { + const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, '').replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&'); + title = title.replace(new RegExp(mangaTitle, 'i'), ''); + title = title.replace(/^\s*-\s*/, ''); + return title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); +} + +export function PageLinkExtractor(this: MangaScraper, element: E): string { + try { + element.dataset.src = window.atob(element.dataset.src); + } catch (_) { /* ignore */ } + try { + element.dataset.src = window.atob(element.dataset.srcset); + } catch (_) { /* ignore */ } + try { + element.dataset.original = window.atob(element.dataset.original); + } catch (_) { /* ignore */ } + try { + element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc); + } catch (_) { /* ignore */ } + try { + element.dataset.aload = window.atob(element.dataset.aload); + } catch (_) { /* ignore */ } + return element.dataset.aload || element.dataset.src || element.dataset.srcset?.replace(/\n/g, '') || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; +} + +const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; export const pathSinglePageManga = '/manga-list.html?listType=allABC'; export const pathMultiPageManga = '/manga-list.html?page={page}'; @@ -38,9 +76,7 @@ export const queryChapters = [ 'div#tab-chapper div#list-chapters span.title a.chapter' ].join(','); -export const queryChapterTitle = [ - 'div.chapter-name', -].join(','); +const queryChaptersAjax = 'a'; export const queryPages = [ 'img.chapter-img', @@ -55,14 +91,15 @@ export const queryPages = [ /** * A class decorator that adds the ability to extract all chapters for a given manga from this website using the given CSS {@link query}. * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted + * @param extractor - A function to extract chapter info from an HTML node */ -export function ChaptersSinglePageCSS(query = queryChapters) { +export function ChaptersSinglePageCSS(query: string = queryChapters, extractor = ChapterExtractor) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { Common.ThrowOnUnsupportedDecoratorContext(context); return class extends ctor { public async FetchChapters(this: MangaScraper, manga: Manga): Promise { - return FetchChaptersSinglePageCSS.call(this, manga, query); + return FetchChaptersSinglePageCSS.call(this, manga, query, extractor); } }; }; @@ -73,28 +110,68 @@ export function ChaptersSinglePageCSS(query = queryChapters) { * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param manga - A reference to the {@link Manga} which shall be assigned as parent for the extracted chapters * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted - */ -export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters): Promise { + * @param extractor - A function to extract chapter info from an HTML node + */ +export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters, extractor = ChapterExtractor): Promise { const url = new URL(manga.Identifier, this.URI); const request = new Request(url.href); const data = await FetchCSS(request, query); - return data.map(anchor => { - if (anchor.dataset.href) { - anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); - } - const id = anchor.pathname; - const titleElement = anchor.querySelector(queryChapterTitle); - let title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); - //escape all special characters used in Javascript regexes - const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, '').replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&'); - title = title.replace(new RegExp(mangaTitle, 'i'), ''); - title = title.replace(/^\s*-\s*/, ''); - title = title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); - return new Chapter(this, manga, id, title); + const { id, title } = extractor.call(this, anchor); + return new Chapter(this, manga, id, CleanChaptertitle(manga, title)); }).distinct(); } +/** + * A class decorator that adds the ability to extract all chapters for a given manga from this website using FlatManga AJAX call. + * @param endpoint - the api endpoint used to query chapters list. I.e /app/controller/listchapters.php?slug= . Must end with ?= + * @param mangaIdVariable - the name of the javascript variable containing the mangaid value. The value be appended to {@link endpoint} + * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted (from the api call) + * @param extractor - A function to extract chapter info from an HTML node + */ +export function ChaptersSinglePageAJAX(endpoint: string, mangaIdVariable: string, query = queryChapters, extractor = ChapterExtractor) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); + + return class extends ctor { + public async FetchChapters(this: MangaScraper, manga: Manga): Promise { + return FetchChaptersSinglePageAJAX.call(this, manga, endpoint, mangaIdVariable, query, extractor); + } + }; + }; + +} +/** Extract all chapters for a given manga from this website using FlatManga AJAX call. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param manga - A reference to the {@link Manga} which shall be assigned as parent for the extracted chapters + * @param endpoint - the api endpoint used to query chapters list. I.e "/app/controller/listchapters.php?slug=". Must end with a query string ?=. + * @param mangaIdVariable - the name of the javascript variable containing the mangaid value. The value will be appended to {@link endpoint} + * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted (from the api call) + * @param extractor - A function to extract chapter info from an HTML node + * @returns + */ +export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Manga, endpoint: string, mangaIdVariable: string, query = queryChaptersAjax, extractor = ChapterExtractor): Promise { + let request = new Request(new URL(manga.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin + } + }); + const mangaRegexp = new RegExp(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(mangaRegexp)[1]; + const apiUrl = new URL(`${endpoint}${mangaSlug}`, this.URI); + + request = new Request(apiUrl, { + headers: { + 'Referer': this.URI.origin + } + }); + const data = await FetchCSS(request, query); + return data.map(chapter => { + const { id, title } = extractor.call(this, chapter); + return new Chapter(this, manga, id, CleanChaptertitle(manga, title)); + }); +} + /********************************************** ******** Page List Extraction Methods ******** **********************************************/ @@ -104,47 +181,80 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages - * @param query - CSS query to get chapter link + * @param query - CSS query to get page link + * @param exclude - a Regexp array to exclude page pattern + * @param extractor - A function to extract page link from an HTML node */ -export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query: string = queryPages, exclude: RegExp[] = DefaultExcludes): Promise { +export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query: string = queryPages, exclude: RegExp[] = DefaultExcludes, extractor = PageLinkExtractor): Promise { const uri = new URL(chapter.Identifier, this.URI); const request = new Request(uri.href); const data = await FetchCSS(request, query); - const pages = data - .map(element => { - try { - element.dataset.src = window.atob(element.dataset.src); - } catch (_) { /* ignore */ } - try { - element.dataset.src = window.atob(element.dataset.srcset); - } catch (_) { /* ignore */ } - try { - element.dataset.original = window.atob(element.dataset.original); - } catch (_) { /* ignore */ } - try { - element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc); - } catch (_) { /* ignore */ } - try { - element.dataset.aload = window.atob(element.dataset.aload); - } catch (_) { /* ignore */ } - return element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; - }); - return pages.filter(url => !exclude.some(pattern => pattern.test(url))).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.href })); + const pages = data.map(page => extractor.call(this, page)); + return pages.filter(url => !exclude.some(pattern => pattern.test(url))).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.origin })); } /** * A class decorator that adds the ability to extract all pages for the given {@link chapter} using the first match of the given regular expression {@link matchers}. * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. - * @param query - CSS query to get chapter link + * @param query - CSS query to get page link + * @param exclude - a Regexp array to exclude page pattern + * @param extractor - A function to extract page link from an HTML node */ -export function PagesSinglePageCSS(query : string = queryPages, excludes : RegExp[] = DefaultExcludes) { +export function PagesSinglePageCSS(query: string = queryPages, excludes: RegExp[] = DefaultExcludes, extractor = PageLinkExtractor) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { Common.ThrowOnUnsupportedDecoratorContext(context); return class extends ctor { public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageCSS.call(this, chapter, query, excludes); + return FetchPagesSinglePageCSS.call(this, chapter, query, excludes, extractor); } }; }; } + +/** + * An extension method for extracting all pages for extracting all pages for the given {@link chapter} using the FlatManga AJAX API. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages + * @param endpoint - the api endpoint used to query pages list. I.e "/app/controller/cont.listimg.php?cid=". Must end with a query string ?=. + * @param query - CSS query to get page link + * @param exclude - a Regexp array to exclude page pattern + * @param extractor - A function to extract page link from an HTML node + */ +export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chapter, endpoint: string, query: string = 'img', exclude: RegExp[] = DefaultExcludes, extractor = PageLinkExtractor): Promise { + let request = new Request(new URL(chapter.Identifier, this.URI), { + headers: { + 'Referer': this.URI.origin, + } + }); + + const chapterId = await FetchWindowScript(request, `document.querySelector('input#chapter').value`, 3000);//use script in case of antiDdoSS/PageSpeed + request = new Request(new URL(`${endpoint}${chapterId}`, this.URI), { + headers: { + 'Referer': this.URI.origin, + } + }); + + const data = await FetchCSS(request, query); + const pages = data.map(page => extractor.call(this, page)); + return pages.filter(url => !exclude.some(pattern => pattern.test(url))).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.origin })); +} + +/** + * A class decorator that adds the ability to extract all pages for the given {@link chapter} using the FlatManga AJAX API. + * @param endpoint - the api endpoint used to query pages list. I.e "/app/controller/cont.listimg.php?cid=". Must end with a query string ?=. + * @param query - CSS query to get page link + * @param exclude - a Regexp array to exclude page pattern + * @param extractor - A function to extract page link from an HTML node + */ +export function PagesSinglePageAJAX(endpoint: string, query: string = queryPages, excludes: RegExp[] = DefaultExcludes, extractor = PageLinkExtractor) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); + + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageAJAX.call(this, chapter, endpoint, query, excludes, extractor); + } + }; + }; +} \ No newline at end of file From 2e28a879645e51b404beaa8e37b92b0ddae37c4f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Jul 2024 14:27:32 +0200 Subject: [PATCH 67/83] Update _index.ts --- web/src/engine/websites/_index.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 36f0b10866..e5ff11763a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -238,6 +238,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -346,6 +347,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -423,6 +425,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -517,6 +520,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; @@ -532,6 +536,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -574,6 +579,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangatop } from './RawMangatop'; @@ -737,6 +743,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -803,7 +811,6 @@ export { default as HolyManga } from './legacy/HolyManga'; export { default as ImiTui } from './legacy/ImiTui'; export { default as JokerFansub } from './legacy/JokerFansub'; export { default as KanMan } from './legacy/KanMan'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -819,7 +826,6 @@ export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; -export { default as Manga33 } from './legacy/Manga33'; export { default as MangaFoxFun } from './legacy/MangaFoxFun'; export { default as MangaHereFun } from './legacy/MangaHereFun'; export { default as MangaHub } from './legacy/MangaHub'; @@ -836,7 +842,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -896,7 +901,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VizShonenJump } from './legacy/VizShonenJump'; export { default as VRVCrunchyroll } from './legacy/VRVCrunchyroll'; @@ -905,8 +909,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WieManga } from './legacy/WieManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; From ee27f07388440f4a2aac6eede703ea25319e8ce3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 26 Jul 2024 16:13:02 +0200 Subject: [PATCH 68/83] Nicomanga : use API for manga list --- web/src/engine/websites/NicoManga.ts | 35 ++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index 06e06a772c..ce3150b745 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -1,11 +1,22 @@ import { Tags } from '../Tags'; import icon from './NicoManga.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as FlatManga from './decorators/FlatManga'; +import { FetchJSON } from '../platform/FetchProvider'; + +type APIMangas = { + manga_list: { + name: string, + slug: string + }[], + lang: { + manga_slug: string + } + +} @Common.MangaCSS(/^{origin}\/manga[^/]+\.html$/, FlatManga.queryMangaTitle) -@Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageAJAX('/app/manga/controllers/cont.Listchapterapi.php?slug=', 'sLugs', 'ul > a', Common.AnchorInfoExtractor(true)) @FlatManga.PagesSinglePageAJAX('/app/manga/controllers/cont.imgsList.php?cid=', 'img.chapter-img:not([alt*="nicoscan"])') @Common.ImageAjax() @@ -18,4 +29,24 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async FetchMangas(provider: MangaPlugin): Promise { + const mangaList: Manga[] = []; + for (let page = 1, run = true; run; page++) { + const mangas = await this.GetMangasFromPageAJAX(provider, page); + mangaList.isMissingLastItemFrom(mangas) ? mangaList.push(...mangas) : run = false; + } + return mangaList.distinct(); + } + private async GetMangasFromPageAJAX(provider: MangaPlugin, page: number): Promise { + const request = new Request(new URL(`/app/manga/controllers/cont.display.homeTopday.php?page=${page}`, this.URI), { + headers: { + 'Referer': new URL('/manga-list.html', this.URI.origin).href, + 'X-Requested-With': 'XMLHttpRequest' + } + }); + const { manga_list, lang: { manga_slug } } = await FetchJSON(request); + return manga_list.map(manga => new Manga(this, provider, `/${manga_slug}-${manga.slug}.html`, manga.name.trim())); + } + } \ No newline at end of file From d4dad6f5dfe6245be5068f71fd32783535e00fdc Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 26 Jul 2024 16:18:57 +0200 Subject: [PATCH 69/83] FlatManga: add Anti scraping detection --- web/src/engine/websites/decorators/FlatManga.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 98320bc019..157e940af7 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,8 +1,18 @@ +import { AddAntiScrapingDetection, FetchRedirection } from "../../platform/AntiScrapingDetection"; import { FetchCSS, FetchHTML, FetchWindowScript } from "../../platform/FetchProvider"; import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; import * as Common from './Common'; +AddAntiScrapingDetection(async (render) => { + const dom = await render(); + if (dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`)) { // Sample => Mangagun, NicoManga, Rawinu, Weloma, WeloveManga + await new Promise(resolve => setTimeout(resolve, 3000)); + return FetchRedirection.Automatic; + } + return undefined; +}); + export function MangaLabelExtractor(element: HTMLElement) { let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; title = title.replace(/\s*-\s*RAW$/i, ''); From ebe4a40e534296756a1d3d4fa01bf3cb2f34389e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 26 Jul 2024 16:26:32 +0200 Subject: [PATCH 70/83] Update FlatManga.ts --- web/src/engine/websites/decorators/FlatManga.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 157e940af7..cae0246198 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -196,11 +196,8 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man * @param extractor - A function to extract page link from an HTML node */ export async function FetchPagesSinglePageCSS(this: MangaScraper, chapter: Chapter, query: string = queryPages, exclude: RegExp[] = DefaultExcludes, extractor = PageLinkExtractor): Promise { - const uri = new URL(chapter.Identifier, this.URI); - const request = new Request(uri.href); - const data = await FetchCSS(request, query); - const pages = data.map(page => extractor.call(this, page)); - return pages.filter(url => !exclude.some(pattern => pattern.test(url))).map(page => new Page(this, chapter, new URL(page, this.URI), { Referer: this.URI.origin })); + const pages = await Common.FetchPagesSinglePageCSS.call(this, chapter, query, extractor); + return pages.filter(page => !exclude.some(pattern => pattern.test(page.Link.href))).map(page => new Page(this, chapter, page.Link, { Referer: this.URI.origin })); } /** From 6d7fa8191c5a781c1df07407abe71a84adce95dd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Aug 2024 20:38:04 +0200 Subject: [PATCH 71/83] fix bookmarkconverter after mastermerge --- web/src/engine/transformers/BookmarkConverter.ts | 2 ++ web/src/engine/transformers/BookmarkConverter_test.ts | 2 ++ 2 files changed, 4 insertions(+) diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index db37b35998..d19e77f0d1 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -26,9 +26,11 @@ export const legacyWebsiteIdentifierMap = new Map([ [ 'gateanimemanga', 'gatemanga' ], [ 'imperioscans', 'neroxus' ], [ 'instamanhwa', 'xmanhwa' ], + [ 'kissaway', 'klmanga' ], [ 'kisscomic', 'readcomiconline' ], [ 'komikav', 'apkomik' ], [ 'kumascans', 'retsu' ], + [ 'lovehug', 'welovemanga' ], [ 'lyrascans', 'quantumscans' ], [ 'mangamx', 'mangaoni' ], [ 'manganel', 'manganato' ], diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index 7a5e9dbeff..6e2cbd5ce9 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -28,9 +28,11 @@ const legacyWebsiteIdentifierMapTestCases = [ { sourceID: 'gateanimemanga', targetID: 'gatemanga' }, { sourceID: 'imperioscans', targetID: 'neroxus' }, { sourceID: 'instamanhwa', targetID: 'xmanhwa' }, + { sourceID: 'kissaway', targetID: 'klmanga' }, { sourceID: 'kisscomic', targetID: 'readcomiconline' }, { sourceID: 'komikav', targetID: 'apkomik' }, { sourceID: 'kumascans', targetID: 'retsu' }, + { sourceID: 'lovehug', targetID: 'welovemanga' }, { sourceID: 'lyrascans', targetID: 'quantumscans' }, { sourceID: 'mangamx', targetID: 'mangaoni' }, { sourceID: 'manganel', targetID: 'manganato' }, From 020459be83e5b8b99b2275cbece838713b06ded5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Aug 2024 20:47:05 +0200 Subject: [PATCH 72/83] ignore unused var in catch --- .../engine/websites/decorators/FlatManga.ts | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index cae0246198..d41a439238 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -46,20 +46,20 @@ function CleanChaptertitle(manga: Manga, title: string): string { export function PageLinkExtractor(this: MangaScraper, element: E): string { try { - element.dataset.src = window.atob(element.dataset.src); - } catch (_) { /* ignore */ } + element.dataset.src = window.atob(element.dataset.src);// eslint-disable-next-line + } catch (_) { } try { - element.dataset.src = window.atob(element.dataset.srcset); - } catch (_) { /* ignore */ } + element.dataset.src = window.atob(element.dataset.srcset);// eslint-disable-next-line + } catch (_) { } try { - element.dataset.original = window.atob(element.dataset.original); - } catch (_) { /* ignore */ } + element.dataset.original = window.atob(element.dataset.original);// eslint-disable-next-line + } catch (_) { } try { - element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc); - } catch (_) { /* ignore */ } + element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc);// eslint-disable-next-line + } catch (_) { } try { - element.dataset.aload = window.atob(element.dataset.aload); - } catch (_) { /* ignore */ } + element.dataset.aload = window.atob(element.dataset.aload);// eslint-disable-next-line + } catch (_) { } return element.dataset.aload || element.dataset.src || element.dataset.srcset?.replace(/\n/g, '') || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; } From ad82535ce4785c34c36c4c47f9fc627074cd6e63 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 10 Aug 2024 20:58:05 +0200 Subject: [PATCH 73/83] use RegExpSafe on safe regexp --- web/src/engine/websites/decorators/FlatManga.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index d41a439238..e58d106cf2 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -123,9 +123,7 @@ export function ChaptersSinglePageCSS(query: string = queryChapters, extractor = * @param extractor - A function to extract chapter info from an HTML node */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters, extractor = ChapterExtractor): Promise { - const url = new URL(manga.Identifier, this.URI); - const request = new Request(url.href); - const data = await FetchCSS(request, query); + const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), query); return data.map(anchor => { const { id, title } = extractor.call(this, anchor); return new Chapter(this, manga, id, CleanChaptertitle(manga, title)); @@ -166,7 +164,7 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man 'Referer': this.URI.origin } }); - const mangaRegexp = new RegExp(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); + const mangaRegexp = new RegExpSafe(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(mangaRegexp)[1]; const apiUrl = new URL(`${endpoint}${mangaSlug}`, this.URI); From 9d9f8d5d9939cbd50ff60d1879f3db8be1314a27 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 14 Aug 2024 12:45:09 +0200 Subject: [PATCH 74/83] Update _index.ts --- web/src/engine/websites/_index.ts | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d2870126a8..266f4589c3 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -224,6 +224,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomikCast } from './KomikCast'; @@ -324,6 +325,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -396,6 +398,7 @@ export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -486,6 +489,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; @@ -501,6 +505,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -543,6 +548,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangatop } from './RawMangatop'; @@ -694,6 +700,8 @@ export { default as WebtoonTR } from './WebtoonTR'; export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WhimSubs } from './WhimSubs'; export { default as WinterScan } from './WinterScan'; @@ -756,7 +764,6 @@ export { default as HeavenManga } from './legacy/HeavenManga'; export { default as HoduComics } from './legacy/HoduComics'; export { default as HolyManga } from './legacy/HolyManga'; export { default as KanMan } from './legacy/KanMan'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -787,7 +794,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManHua1359 } from './legacy/ManHua1359'; export { default as ManHuaFen } from './legacy/ManHuaFen'; @@ -845,7 +851,6 @@ export { default as ToomicsPT } from './legacy/ToomicsPT'; export { default as ToomicsSC } from './legacy/ToomicsSC'; export { default as ToomicsTC } from './legacy/ToomicsTC'; export { default as Toonkor } from './legacy/Toonkor'; -export { default as TruyenTranhLH } from './legacy/TruyenTranhLH'; export { default as TsundokuTraducoes } from './legacy/TsundokuTraducoes'; export { default as VizShonenJump } from './legacy/VizShonenJump'; export { default as VRVCrunchyroll } from './legacy/VRVCrunchyroll'; @@ -854,8 +859,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; From 810c162dbb49d559bccecdda865e05a0b0d4de53 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 15 Aug 2024 13:38:15 +0200 Subject: [PATCH 75/83] rewrite titles cleaning --- web/src/engine/websites/KLManga.ts | 4 +- web/src/engine/websites/MangaTR.ts | 7 +-- web/src/engine/websites/NicoManga.ts | 2 +- .../engine/websites/decorators/FlatManga.ts | 49 ++++++++----------- 4 files changed, 28 insertions(+), 34 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index 911e636573..b8bd1f7288 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -11,8 +11,8 @@ function GenerateRandomEndPoint(length: number, suffix: string): string { return randomEndpoint + suffix; } -@Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle) -@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas) +@Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) +@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageAJAX(GenerateRandomEndPoint(25, '.lstc?slug='), 'dataL', 'a.chapter[title]') @FlatManga.PagesSinglePageAJAX(GenerateRandomEndPoint(30, '.iog?cid='), 'img.chapter-img[alt*="Page"]', [/olimposcan/] ) diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index b73ad6a674..97df36a944 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -50,9 +50,10 @@ export default class extends DecoratableMangaScraper { }); const data = await FetchCSS(request, 'table.table tr td.table-bordered:first-of-type > a'); - const escapedMangaTitle = manga.Title.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); - const regexp = new RegExp(escapedMangaTitle, 'i'); - return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.text.replace(regexp, '').trim() || chapter.text.trim())); + return data.map(chapter => { + const title = FlatManga.CleanTitle(chapter.text.replace(manga.Title, '')) || chapter.text.trim(); + return new Chapter(this, manga, chapter.pathname, title); + }); } } \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga.ts b/web/src/engine/websites/NicoManga.ts index ce3150b745..facfaad3c1 100644 --- a/web/src/engine/websites/NicoManga.ts +++ b/web/src/engine/websites/NicoManga.ts @@ -46,7 +46,7 @@ export default class extends DecoratableMangaScraper { } }); const { manga_list, lang: { manga_slug } } = await FetchJSON(request); - return manga_list.map(manga => new Manga(this, provider, `/${manga_slug}-${manga.slug}.html`, manga.name.trim())); + return manga_list.map(manga => new Manga(this, provider, `/${manga_slug}-${manga.slug}.html`, FlatManga.CleanTitle(manga.name.trim()))); } } \ No newline at end of file diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index e58d106cf2..176bab9866 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -1,4 +1,4 @@ -import { AddAntiScrapingDetection, FetchRedirection } from "../../platform/AntiScrapingDetection"; +import { AddAntiScrapingDetection, FetchRedirection } from "../../platform/AntiScrapingDetection"; import { FetchCSS, FetchHTML, FetchWindowScript } from "../../platform/FetchProvider"; import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlugin"; import { Page } from "../../providers/MangaPlugin"; @@ -15,18 +15,16 @@ AddAntiScrapingDetection(async (render) => { export function MangaLabelExtractor(element: HTMLElement) { let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; - title = title.replace(/\s*-\s*RAW$/i, ''); - return title.trim(); + return CleanTitle(title); } export function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; let title = anchor.getAttribute('text') ? anchor.getAttribute('text') : anchor.textContent; - title = title.replace(/\s*-\s*RAW$/i, '').trim(); - return { id, title }; + return { id, title: CleanTitle(title) }; } function ChapterExtractor(anchor: HTMLAnchorElement) { - if (anchor.dataset.href) { + if (anchor.dataset?.href) { anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); } const id = anchor.pathname; @@ -37,30 +35,23 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { }; } -function CleanChaptertitle(manga: Manga, title: string): string { - const mangaTitle = manga.Title.replace(/\s*-\s*RAW$/i, '').replace(/[*^.|$?+\-()[\]{}\\/]/g, '\\$&'); - title = title.replace(new RegExp(mangaTitle, 'i'), ''); - title = title.replace(/^\s*-\s*/, ''); - return title.replace(/-\s*-\s*Read\s*Online\s*$/, '').trim(); +export function CleanTitle(title: string): string { + title = title.replace(/\s*[~\-―〜]\s*RAW\s*\(MANGA\)\s*$/i, '').trim(); + title = title.replace(/\s*[~\-―〜]\s*(MANGA)?\s*RAW\s*$/i, '').trim(); + title = title.replace(/\(raw\)/i, '').trim(); + return title.replace(/\(manga\)/i, '').trim(); } export function PageLinkExtractor(this: MangaScraper, element: E): string { + + let page = element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; try { - element.dataset.src = window.atob(element.dataset.src);// eslint-disable-next-line - } catch (_) { } - try { - element.dataset.src = window.atob(element.dataset.srcset);// eslint-disable-next-line - } catch (_) { } - try { - element.dataset.original = window.atob(element.dataset.original);// eslint-disable-next-line - } catch (_) { } - try { - element.dataset.pagespeedLazySrc = window.atob(element.dataset.pagespeedLazySrc);// eslint-disable-next-line - } catch (_) { } - try { - element.dataset.aload = window.atob(element.dataset.aload);// eslint-disable-next-line - } catch (_) { } - return element.dataset.aload || element.dataset.src || element.dataset.srcset?.replace(/\n/g, '') || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; + page = window.atob(page);/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ + } catch (error) { + // + } + return page.replace(/\n/g, ''); + } const DefaultExcludes = [/3282f6a4b7_o/, /donate/]; @@ -126,7 +117,8 @@ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Mang const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), query); return data.map(anchor => { const { id, title } = extractor.call(this, anchor); - return new Chapter(this, manga, id, CleanChaptertitle(manga, title)); + let finaltitle = title.replace(manga.Title, '').trim() ?? title; + return new Chapter(this, manga, id, CleanTitle(finaltitle)); }).distinct(); } @@ -176,7 +168,8 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man const data = await FetchCSS(request, query); return data.map(chapter => { const { id, title } = extractor.call(this, chapter); - return new Chapter(this, manga, id, CleanChaptertitle(manga, title)); + let finaltitle = title.replace(manga.Title, '').trim() ?? title; + return new Chapter(this, manga, id, CleanTitle(finaltitle)); }); } From cc4f91c14dab34e04116651b1adc68182dcd7c3a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 23 Sep 2024 12:14:17 +0200 Subject: [PATCH 76/83] minor code changes --- web/src/engine/websites/KLManga.ts | 1 - web/src/engine/websites/decorators/FlatManga.ts | 6 ++---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index b8bd1f7288..b4222c17aa 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -15,7 +15,6 @@ function GenerateRandomEndPoint(length: number, suffix: string): string { @Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageAJAX(GenerateRandomEndPoint(25, '.lstc?slug='), 'dataL', 'a.chapter[title]') @FlatManga.PagesSinglePageAJAX(GenerateRandomEndPoint(30, '.iog?cid='), 'img.chapter-img[alt*="Page"]', [/olimposcan/] ) - @Common.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 176bab9866..79dcbec30d 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -46,10 +46,8 @@ export function PageLinkExtractor(this: MangaScraper let page = element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; try { - page = window.atob(page);/* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - } catch (error) { - // - } + page = window.atob(page); + } catch { } return page.replace(/\n/g, ''); } From 5af35c73f97df5df70cb0f9e9cad7d9840ce1ad1 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 7 Oct 2024 11:37:04 +0200 Subject: [PATCH 77/83] Update AntiScraping --- web/src/engine/websites/decorators/FlatManga.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 79dcbec30d..e4602e6030 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -4,13 +4,14 @@ import { Chapter, type Manga, type MangaScraper} from "../../providers/MangaPlug import { Page } from "../../providers/MangaPlugin"; import * as Common from './Common'; -AddAntiScrapingDetection(async (render) => { - const dom = await render(); - if (dom.documentElement.innerHTML.includes(`ct_anti_ddos_key`)) { // Sample => Mangagun, NicoManga, Rawinu, Weloma, WeloveManga +AddAntiScrapingDetection(async (invoke) => { + + const result = await invoke(`document.documentElement.innerHTML.includes('ct_anti_ddos_key')`);// Sample => Mangagun, NicoManga, Rawinu, Weloma, WeloveManga + if (result) { await new Promise(resolve => setTimeout(resolve, 3000)); return FetchRedirection.Automatic; - } - return undefined; + } else return undefined; + }); export function MangaLabelExtractor(element: HTMLElement) { From 0f0e84ce79f960fc0a9d56ac646c866071450bcd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 27 Oct 2024 10:09:35 +0100 Subject: [PATCH 78/83] update tests --- web/src/engine/websites/KLManga_e2e.ts | 4 +--- web/src/engine/websites/MangaGun_e2e.ts | 4 +--- web/src/engine/websites/MangaTR_e2e.ts | 4 +--- web/src/engine/websites/NicoManga_e2e.ts | 4 +--- web/src/engine/websites/OlimpoScans_e2e.ts | 4 +--- web/src/engine/websites/RawInu_e2e.ts | 4 +--- web/src/engine/websites/WeLoMa_e2e.ts | 4 +--- web/src/engine/websites/WeLoveManga_e2e.ts | 4 +--- web/src/engine/websites/_index.ts | 12 ++++++++---- 9 files changed, 16 insertions(+), 28 deletions(-) diff --git a/web/src/engine/websites/KLManga_e2e.ts b/web/src/engine/websites/KLManga_e2e.ts index 10c98e5501..bd8d377830 100644 --- a/web/src/engine/websites/KLManga_e2e.ts +++ b/web/src/engine/websites/KLManga_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -22,5 +21,4 @@ const config: Config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/MangaGun_e2e.ts b/web/src/engine/websites/MangaGun_e2e.ts index aed168e391..521be06817 100644 --- a/web/src/engine/websites/MangaGun_e2e.ts +++ b/web/src/engine/websites/MangaGun_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -22,5 +21,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/MangaTR_e2e.ts b/web/src/engine/websites/MangaTR_e2e.ts index 177f0a9c07..0bc90c8827 100644 --- a/web/src/engine/websites/MangaTR_e2e.ts +++ b/web/src/engine/websites/MangaTR_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -22,5 +21,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/NicoManga_e2e.ts b/web/src/engine/websites/NicoManga_e2e.ts index a1d1d047bb..d14a885b9e 100644 --- a/web/src/engine/websites/NicoManga_e2e.ts +++ b/web/src/engine/websites/NicoManga_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/OlimpoScans_e2e.ts b/web/src/engine/websites/OlimpoScans_e2e.ts index c4725f70c6..dd8d0e95a7 100644 --- a/web/src/engine/websites/OlimpoScans_e2e.ts +++ b/web/src/engine/websites/OlimpoScans_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -22,5 +21,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/RawInu_e2e.ts b/web/src/engine/websites/RawInu_e2e.ts index 9151563d77..d9e68a7849 100644 --- a/web/src/engine/websites/RawInu_e2e.ts +++ b/web/src/engine/websites/RawInu_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -22,5 +21,4 @@ const config: Config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoMa_e2e.ts b/web/src/engine/websites/WeLoMa_e2e.ts index f8cd7d0153..e6f7b0681f 100644 --- a/web/src/engine/websites/WeLoMa_e2e.ts +++ b/web/src/engine/websites/WeLoMa_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -22,5 +21,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/WeLoveManga_e2e.ts b/web/src/engine/websites/WeLoveManga_e2e.ts index bef45bc0c5..043d3d4170 100644 --- a/web/src/engine/websites/WeLoveManga_e2e.ts +++ b/web/src/engine/websites/WeLoveManga_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index b07b22eada..94524a836d 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -227,6 +227,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomBatch } from './KomBatch'; @@ -316,6 +317,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -386,6 +388,7 @@ export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTilkisi } from './MangaTilkisi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaTX } from './MangaTX'; @@ -474,6 +477,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -489,6 +493,7 @@ export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; export { default as OkToon } from './OkToon'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -531,6 +536,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangatop } from './RawMangatop'; @@ -693,6 +699,8 @@ export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeebCentral } from './WeebCentral'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WinterScan } from './WinterScan'; export { default as Wnacg } from './Wnacg'; @@ -750,7 +758,6 @@ export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; export { default as HolyManga } from './legacy/HolyManga'; export { default as KanMan } from './legacy/KanMan'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -780,7 +787,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManhuaTai } from './legacy/ManhuaTai'; export { default as MeioNovel } from './legacy/MeioNovel'; @@ -841,8 +847,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; From af7f5546b36a0caa6f247559f8d05d82e748a66b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 17 Nov 2024 11:06:43 +0100 Subject: [PATCH 79/83] Update _index.ts --- web/src/engine/websites/_index.ts | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index c28499fd32..5a1c451ec6 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -229,6 +229,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomBatch } from './KomBatch'; @@ -316,6 +317,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -388,6 +390,7 @@ export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTilkisi } from './MangaTilkisi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaUpGlobal } from './MangaUpGlobal'; @@ -474,6 +477,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -487,6 +491,7 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -528,6 +533,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangaSU } from './RawMangaSU'; @@ -694,6 +700,8 @@ export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeebCentral } from './WeebCentral'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WinterScan } from './WinterScan'; export { default as Wnacg } from './Wnacg'; @@ -750,7 +758,6 @@ export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; export { default as HolyManga } from './legacy/HolyManga'; export { default as KanMan } from './legacy/KanMan'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -773,7 +780,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManhuaTai } from './legacy/ManhuaTai'; export { default as MeioNovel } from './legacy/MeioNovel'; @@ -834,8 +840,6 @@ export { default as VRVRoosterteeth } from './legacy/VRVRoosterteeth'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; From 6965add60af5a08723e5e1c95578a5f6057537c3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 17 Nov 2024 11:14:32 +0100 Subject: [PATCH 80/83] Update FlatManga.ts --- .../engine/websites/decorators/FlatManga.ts | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index e4602e6030..73a80be4ec 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -5,7 +5,6 @@ import { Page } from "../../providers/MangaPlugin"; import * as Common from './Common'; AddAntiScrapingDetection(async (invoke) => { - const result = await invoke(`document.documentElement.innerHTML.includes('ct_anti_ddos_key')`);// Sample => Mangagun, NicoManga, Rawinu, Weloma, WeloveManga if (result) { await new Promise(resolve => setTimeout(resolve, 3000)); @@ -15,24 +14,22 @@ AddAntiScrapingDetection(async (invoke) => { }); export function MangaLabelExtractor(element: HTMLElement) { - let title = element.getAttribute('text') ? element.getAttribute('text') : element.textContent; - return CleanTitle(title); + return CleanTitle(element.getAttribute('text') ? element.getAttribute('text') : element.textContent); } export function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - let title = anchor.getAttribute('text') ? anchor.getAttribute('text') : anchor.textContent; - return { id, title: CleanTitle(title) }; + return { + id: anchor.pathname, + title: CleanTitle(anchor.getAttribute('text') ? anchor.getAttribute('text') : anchor.textContent) + }; } function ChapterExtractor(anchor: HTMLAnchorElement) { if (anchor.dataset?.href) { anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); } - const id = anchor.pathname; - const titleElement = anchor.querySelector('div.chapter-name'); - const title = titleElement ? titleElement.textContent.trim() : anchor.text.trim(); return { - id, title + id: anchor.pathname, + title: anchor.querySelector('div.chapter-name') ? anchor.querySelector('div.chapter-name').textContent.trim() : anchor.text.trim() }; } @@ -44,7 +41,6 @@ export function CleanTitle(title: string): string { } export function PageLinkExtractor(this: MangaScraper, element: E): string { - let page = element.dataset.aload || element.dataset.src || element.dataset.srcset || element.dataset.original || element.dataset.pagespeedLazySrc || element.src; try { page = window.atob(page); @@ -167,8 +163,7 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man const data = await FetchCSS(request, query); return data.map(chapter => { const { id, title } = extractor.call(this, chapter); - let finaltitle = title.replace(manga.Title, '').trim() ?? title; - return new Chapter(this, manga, id, CleanTitle(finaltitle)); + return new Chapter(this, manga, id, CleanTitle(title.replace(manga.Title, '').trim() ?? title)); }); } From 9a8b8114b893ef5854d683bd4e07186edb106ef2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 28 Nov 2024 21:17:40 +0100 Subject: [PATCH 81/83] remove useless decorator --- web/src/engine/websites/OlimpoScans.ts | 2 +- web/src/engine/websites/WeLoMa.ts | 2 +- .../engine/websites/decorators/FlatManga.ts | 37 +------------------ 3 files changed, 4 insertions(+), 37 deletions(-) diff --git a/web/src/engine/websites/OlimpoScans.ts b/web/src/engine/websites/OlimpoScans.ts index 182ad038c6..80c65026d6 100644 --- a/web/src/engine/websites/OlimpoScans.ts +++ b/web/src/engine/websites/OlimpoScans.ts @@ -6,7 +6,7 @@ import * as FlatManga from './decorators/FlatManga'; @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@FlatManga.ChaptersSinglePageCSS() +@Common.ChaptersSinglePageCSS(FlatManga.queryChapters, FlatManga.ChapterExtractor) @Common.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/WeLoMa.ts b/web/src/engine/websites/WeLoMa.ts index 04eabdd6a8..02260c7686 100644 --- a/web/src/engine/websites/WeLoMa.ts +++ b/web/src/engine/websites/WeLoMa.ts @@ -7,7 +7,7 @@ import { FetchWindowScript } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/[^/]+\/$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) @Common.MangasMultiPageCSS(FlatManga.pathMultiPageManga, FlatManga.queryMangas, 1, 1, 0, FlatManga.MangaExtractor) -@FlatManga.ChaptersSinglePageCSS() +@Common.ChaptersSinglePageCSS(FlatManga.queryChapters, FlatManga.ChapterExtractor) @Common.PagesSinglePageCSS(FlatManga.queryPages) @Common.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 73a80be4ec..62cdc2b706 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -23,13 +23,13 @@ export function MangaExtractor(anchor: HTMLAnchorElement) { }; } -function ChapterExtractor(anchor: HTMLAnchorElement) { +export function ChapterExtractor(anchor: HTMLAnchorElement) { if (anchor.dataset?.href) { anchor.setAttribute('href', anchor.dataset.href + anchor.getAttribute('href')); } return { id: anchor.pathname, - title: anchor.querySelector('div.chapter-name') ? anchor.querySelector('div.chapter-name').textContent.trim() : anchor.text.trim() + title: CleanTitle(anchor.querySelector('div.chapter-name') ? anchor.querySelector('div.chapter-name').textContent.trim() : anchor.text.trim()) }; } @@ -84,39 +84,6 @@ export const queryPages = [ ******** Chapters List Extraction Methods ****** **********************************************/ -/** - * A class decorator that adds the ability to extract all chapters for a given manga from this website using the given CSS {@link query}. - * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted - * @param extractor - A function to extract chapter info from an HTML node - */ -export function ChaptersSinglePageCSS(query: string = queryChapters, extractor = ChapterExtractor) { - return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - Common.ThrowOnUnsupportedDecoratorContext(context); - - return class extends ctor { - public async FetchChapters(this: MangaScraper, manga: Manga): Promise { - return FetchChaptersSinglePageCSS.call(this, manga, query, extractor); - } - }; - }; -} - -/** - * An extension method for extracting all chapters for the given {@link manga} using the given CSS {@link query}. - * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method - * @param manga - A reference to the {@link Manga} which shall be assigned as parent for the extracted chapters - * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted - * @param extractor - A function to extract chapter info from an HTML node - */ -export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query = queryChapters, extractor = ChapterExtractor): Promise { - const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), query); - return data.map(anchor => { - const { id, title } = extractor.call(this, anchor); - let finaltitle = title.replace(manga.Title, '').trim() ?? title; - return new Chapter(this, manga, id, CleanTitle(finaltitle)); - }).distinct(); -} - /** * A class decorator that adds the ability to extract all chapters for a given manga from this website using FlatManga AJAX call. * @param endpoint - the api endpoint used to query chapters list. I.e /app/controller/listchapters.php?slug= . Must end with ?= From fe4f586eeb4fb7cb6e7f78146576d17682a859f3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Dec 2024 11:37:17 +0100 Subject: [PATCH 82/83] reflect Common changes --- web/src/engine/websites/KLManga.ts | 4 ++-- web/src/engine/websites/MangaTR.ts | 2 +- web/src/engine/websites/_index.ts | 12 ++++++++---- web/src/engine/websites/decorators/FlatManga.ts | 4 ++-- 4 files changed, 13 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/KLManga.ts b/web/src/engine/websites/KLManga.ts index b4222c17aa..f3d7a794c9 100644 --- a/web/src/engine/websites/KLManga.ts +++ b/web/src/engine/websites/KLManga.ts @@ -12,9 +12,9 @@ function GenerateRandomEndPoint(length: number, suffix: string): string { } @Common.MangaCSS(/^{origin}\/[^/]+\.html$/, FlatManga.queryMangaTitle, FlatManga.MangaLabelExtractor) -@Common.MangasSinglePageCSS(FlatManga.pathSinglePageManga, FlatManga.queryMangas, FlatManga.MangaExtractor) +@Common.MangasSinglePagesCSS([FlatManga.pathSinglePageManga], FlatManga.queryMangas, FlatManga.MangaExtractor) @FlatManga.ChaptersSinglePageAJAX(GenerateRandomEndPoint(25, '.lstc?slug='), 'dataL', 'a.chapter[title]') -@FlatManga.PagesSinglePageAJAX(GenerateRandomEndPoint(30, '.iog?cid='), 'img.chapter-img[alt*="Page"]', [/olimposcan/] ) +@FlatManga.PagesSinglePageAJAX(GenerateRandomEndPoint(30, '.iog?cid='), 'img.chapter-img[alt*="Page"]', [/olimposcan/]) @Common.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/MangaTR.ts b/web/src/engine/websites/MangaTR.ts index 97df36a944..e0199428fb 100644 --- a/web/src/engine/websites/MangaTR.ts +++ b/web/src/engine/websites/MangaTR.ts @@ -26,7 +26,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchMangas(provider: MangaPlugin): Promise { - return (await Common.FetchMangasSinglePageCSS.call(this, provider, '/manga-list.html', FlatManga.queryMangas)).filter(manga => manga.Title); + return (await Common.FetchMangasSinglePagesCSS.call(this, provider, ['/manga-list.html'], FlatManga.queryMangas)).filter(manga => manga.Title); } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 9f72c71025..27aee33e80 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -233,6 +233,7 @@ export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; export { default as KlikManga } from './KlikManga'; +export { default as KLManga } from './KLManga'; export { default as KnightNoFansub } from './KnightNoFansub'; export { default as KolNovel } from './KolNovel'; export { default as KomBatch } from './KomBatch'; @@ -321,6 +322,7 @@ export { default as MangaGeko } from './MangaGeko'; export { default as MangaGezgini } from './MangaGezgini'; export { default as MangaGG } from './MangaGG'; export { default as MangaGo } from './MangaGo'; +export { default as MangaGun } from './MangaGun'; export { default as MangaHack } from './MangaHack'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; @@ -392,6 +394,7 @@ export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTilkisi } from './MangaTilkisi'; export { default as MangaTitan } from './MangaTitan'; export { default as MangaTown } from './MangaTown'; +export { default as MangaTR } from './MangaTR'; export { default as MangaTRNet } from './MangaTRNet'; export { default as MangaTube } from './MangaTube'; export { default as MangaUpGlobal } from './MangaUpGlobal'; @@ -478,6 +481,7 @@ export { default as Ngomik } from './Ngomik'; export { default as NHentai } from './NHentai'; export { default as NHentaiCom } from './NHentaiCom'; export { default as NiceOppai } from './NiceOppai'; +export { default as NicoManga } from './NicoManga'; export { default as NicoNicoSeiga } from './NicoNicoSeiga'; export { default as Nightow } from './Nightow'; export { default as NightScans } from './NightScans'; @@ -490,6 +494,7 @@ export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; +export { default as OlimpoScans } from './OlimpoScans'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -530,6 +535,7 @@ export { default as RavenSeries } from './RavenSeries'; export { default as RavensScansEN } from './RavensScansEN'; export { default as RavensScansES } from './RavensScansES'; export { default as RawDevart } from './RawDevart'; +export { default as RawInu } from './RawInu'; export { default as Rawkuma } from './Rawkuma'; export { default as RawLazy } from './RawLazy'; export { default as RawMangaSU } from './RawMangaSU'; @@ -698,6 +704,8 @@ export { default as WebtoonTRNET } from './WebtoonTRNET'; export { default as WebtoonXYZ } from './WebtoonXYZ'; export { default as WeebCentral } from './WeebCentral'; export { default as WeiboManhua } from './WeiboManhua'; +export { default as WeLoMa } from './WeLoMa'; +export { default as WeLoveManga } from './WeLoveManga'; export { default as WestManga } from './WestManga'; export { default as WinterScan } from './WinterScan'; export { default as Wnacg } from './Wnacg'; @@ -750,7 +758,6 @@ export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; export { default as HolyManga } from './legacy/HolyManga'; export { default as KanMan } from './legacy/KanMan'; -export { default as KissAway } from './legacy/KissAway'; export { default as kuman5 } from './legacy/kuman5'; export { default as LectorManga } from './legacy/LectorManga'; export { default as LezhinEN } from './legacy/LezhinEN'; @@ -772,7 +779,6 @@ export { default as MangaToonES } from './legacy/MangaToonES'; export { default as MangaToonID } from './legacy/MangaToonID'; export { default as MangaToonTH } from './legacy/MangaToonTH'; export { default as MangaToonVI } from './legacy/MangaToonVI'; -export { default as MangaTR } from './legacy/MangaTR'; export { default as MangaZukiRAWS } from './legacy/MangaZukiRAWS'; export { default as ManhuaTai } from './legacy/ManhuaTai'; export { default as MeioNovel } from './legacy/MeioNovel'; @@ -826,8 +832,6 @@ export { default as VizShonenJump } from './legacy/VizShonenJump'; export { default as WanPaMan } from './legacy/WanPaMan'; export { default as WBNovel } from './legacy/WBNovel'; export { default as WebComicGamma } from './legacy/WebComicGamma'; -export { default as WeLoMa } from './legacy/WeLoMa'; -export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 62cdc2b706..0a95b06d7a 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -118,8 +118,8 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man 'Referer': this.URI.origin } }); - const mangaRegexp = new RegExpSafe(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); - const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(mangaRegexp)[1]; + const mangaRegexp = new RegExp(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); + const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(mangaRegexp).at(1); const apiUrl = new URL(`${endpoint}${mangaSlug}`, this.URI); request = new Request(apiUrl, { From f2b00bf06ebb61be6d5324559224284121e0964b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Dec 2024 11:46:53 +0100 Subject: [PATCH 83/83] Update FlatManga.ts --- web/src/engine/websites/decorators/FlatManga.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/decorators/FlatManga.ts b/web/src/engine/websites/decorators/FlatManga.ts index 0a95b06d7a..87b7e69e13 100644 --- a/web/src/engine/websites/decorators/FlatManga.ts +++ b/web/src/engine/websites/decorators/FlatManga.ts @@ -118,7 +118,7 @@ export async function FetchChaptersSinglePageAJAX(this: MangaScraper, manga: Man 'Referer': this.URI.origin } }); - const mangaRegexp = new RegExp(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); + const mangaRegexp = new RegExpSafe(`var ${mangaIdVariable}\\s*=\\s*['"]([^'"]+)['"]`); const mangaSlug = (await FetchHTML(request)).documentElement.innerHTML.match(mangaRegexp).at(1); const apiUrl = new URL(`${endpoint}${mangaSlug}`, this.URI);