diff --git a/web/src/engine/websites/WeebCentral.ts b/web/src/engine/websites/WeebCentral.ts new file mode 100644 index 000000000..2edea3d89 --- /dev/null +++ b/web/src/engine/websites/WeebCentral.ts @@ -0,0 +1,58 @@ +import { Tags } from '../Tags'; +import icon from './WeebCentral.webp'; +import { Chapter, DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import { FetchCSS } from '../platform/FetchProvider'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/[^/]+$/, 'section > section > h1.text-center') +@Common.PagesSinglePageCSS('main#chapter-main section img') +@Common.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('weebcentral', 'WeebCentral', 'https://weebcentral.com', Tags.Media.Manhwa, Tags.Media.Manhua, Tags.Media.Manga, Tags.Language.English, Tags.Source.Aggregator); + } + + public override get Icon() { + return icon; + } + + public override async FetchMangas(provider: MangaPlugin): Promise { + const mangaList : Manga[] = []; + for (let page = 0, run = true; run; page++) { + const mangas = await this.GetMangasFromPage(page, provider); + mangas.length > 0 ? mangaList.push(...mangas) : run = false; + } + return mangaList; + } + + private async GetMangasFromPage(page: number, provider: MangaPlugin): Promise { + const mangasperPage = 24; + const searchURL = new URL('/search', this.URI).href; + const data = await FetchCSS(new Request(new URL(`/search?limit=${mangasperPage}&offset=${page * mangasperPage}`, this.URI), { + headers: { + 'HX-Request': 'true', + 'HX-Current-URL': searchURL, + 'HX-Target': 'search-more-container', + Referer: searchURL + + } + }), 'a.link.link-hover[href*="/series/"]'); + return data.map(manga => new Manga(this, provider, manga.pathname, manga.textContent.trim())); + } + + public override async FetchChapters(manga: Manga): Promise { + const serieId = manga.Identifier.match(/(\/series\/[^/]+)\//)[1]; + const chapterUrl = new URL(manga.Identifier, this.URI).href; + const data = await FetchCSS(new Request(new URL(`${serieId}/full-chapter-list`, this.URI), { + headers: { + 'HX-Request': 'true', + 'HX-Current-URL': chapterUrl, + 'HX-Target': 'chapter-list', + Referer: chapterUrl + } + }), 'a'); + return data.map(chapter => new Chapter(this, manga, chapter.pathname, chapter.querySelector('span.grow').textContent.trim())); + } + +} \ No newline at end of file diff --git a/web/src/engine/websites/WeebCentral.webp b/web/src/engine/websites/WeebCentral.webp new file mode 100644 index 000000000..13db2c936 Binary files /dev/null and b/web/src/engine/websites/WeebCentral.webp differ diff --git a/web/src/engine/websites/WeebCentral_e2e.ts b/web/src/engine/websites/WeebCentral_e2e.ts new file mode 100644 index 000000000..dfdd5ca83 --- /dev/null +++ b/web/src/engine/websites/WeebCentral_e2e.ts @@ -0,0 +1,26 @@ +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'weebcentral', + title: 'WeebCentral' + }, + container: { + url: 'https://weebcentral.com/series/01J76XY7E5E1C5Y9J0M2FCVQ8H/Fairy-Tail', + id: '/series/01J76XY7E5E1C5Y9J0M2FCVQ8H/Fairy-Tail', + title: 'Fairy Tail' + }, + child: { + id: '/chapters/01J76XZ8VTT3V8J44VAX442FRN', + title: 'Chapter 545.5' + }, + entry: { + index: 0, + size: 258_254, + type: 'image/png' + } +}; + +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 db33fcd24..cace4c762 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -688,6 +688,7 @@ export { default as WebtoonHatti } from './WebtoonHatti'; export { default as WebtoonTR } from './WebtoonTR'; 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 WestManga } from './WestManga'; export { default as WinterScan } from './WinterScan';