From 8f2c3b046bca194538750a7ab8e761244a867784 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 20 Feb 2024 17:22:37 +0100 Subject: [PATCH 01/28] Add ComiciViewer decorator & websites tests will come later --- web/src/engine/websites/BigComics.ts | 22 ++ web/src/engine/websites/BigComics.webp | Bin 0 -> 978 bytes web/src/engine/websites/COMICMeDu.ts | 22 ++ .../websites/{legacy => }/COMICMeDu.webp | Bin web/src/engine/websites/ComicRide.ts | 22 ++ web/src/engine/websites/ComicRide.webp | Bin 0 -> 936 bytes web/src/engine/websites/YoungAnimal.ts | 22 ++ web/src/engine/websites/YoungAnimal.webp | Bin 0 -> 1392 bytes web/src/engine/websites/YoungChampion.ts | 22 ++ web/src/engine/websites/YoungChampion.webp | Bin 0 -> 982 bytes web/src/engine/websites/_index.ts | 6 +- .../websites/decorators/ComiciViewer.ts | 226 ++++++++++++++++++ web/src/engine/websites/legacy/COMICMeDu.ts | 98 -------- 13 files changed, 341 insertions(+), 99 deletions(-) create mode 100644 web/src/engine/websites/BigComics.ts create mode 100644 web/src/engine/websites/BigComics.webp create mode 100644 web/src/engine/websites/COMICMeDu.ts rename web/src/engine/websites/{legacy => }/COMICMeDu.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/ComicRide.ts create mode 100644 web/src/engine/websites/ComicRide.webp create mode 100644 web/src/engine/websites/YoungAnimal.ts create mode 100644 web/src/engine/websites/YoungAnimal.webp create mode 100644 web/src/engine/websites/YoungChampion.ts create mode 100644 web/src/engine/websites/YoungChampion.webp create mode 100644 web/src/engine/websites/decorators/ComiciViewer.ts delete mode 100755 web/src/engine/websites/legacy/COMICMeDu.ts diff --git a/web/src/engine/websites/BigComics.ts b/web/src/engine/websites/BigComics.ts new file mode 100644 index 0000000000..bd5ecea2d2 --- /dev/null +++ b/web/src/engine/websites/BigComics.ts @@ -0,0 +1,22 @@ +import { Tags } from '../Tags'; +import icon from './BigComics.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('bigcomics', `Big Comics`, 'https://bigcomics.jp', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/BigComics.webp b/web/src/engine/websites/BigComics.webp new file mode 100644 index 0000000000000000000000000000000000000000..610862e4eadec26b63a760c4319854a4be029889 GIT binary patch literal 978 zcmV;@110{{S5MM6+kP&gpI0{{T96#$(9DnI~006v96p-`nGBBHDq0H6?n z129jJIbz!M=G^}s>_5a)qz9M}*x%L!eV0agk7T_{PRONe)7`W{wQ)5Xl`rHNKug*mJc%vzm*Wy>fPBeWvor*7!` zzySW#1TVdv4arC;NV zg1tG*D0*uCAKqS0yD-fJD*ok{43Yd-YP0$-xXQ6%{}TBe?71~n&9)Q&*RNfxfpv#6 zcm%z)leI*j%H(j@)cLiOJ}rSw3W8;sU)-~CE`YiCPz9&77pS_cdl_>PyR^K25`6ea zJqwM{j87ak7y?bu>dIH4URE?mg7c-(e|hj;8TiNfop2IX?$w3E3z57>U>VvF zmrcX}eb?GhnSG^IZE3COKlgk+4y%NOBJt(3i4COM)IDl(z&Vhoen5;)uLv)t$xAw- z)fS_>dStyNMJS6YMK9ywd%^-B1g4#BPiqja!2Zgr)tB9f>v^+PUr%4RCU(=47tzeT zDe}LGMUK`Mz=zjURp8|Z;GsI#GT-R_ko5{f=J{2+CXYr>wr5)KQdtQjXYe<(Hkr1y z$191bHO~Ltt&jNZMV)_16>p&Zfg7&7VUeRaD_rZ_oBbW*WX|+R*_K+%z)OCwN5g^c z_E9{avb4jx`1w_sJm$XpCFW~(SmpTpc8dO=DO?#6Z~s?Wp~UwHiy`eXH+(3Tr$_Is zLcp8-O_$kT(>YvKxz(=#13iIbc#yiACsGysVTtzNuzl-~1*8w?&>N*L3GO#LwT*i% zf2vrsdZOGAvN6uvppox-(THymdGw7x&ZiDm)3rO$uMTrV z+u) zuC`l_f9SUz0uXwY;lXTg!ULygYLx%FSbMl4FtQn{7w8&|**0Kp3=Y#hB02Kpz~iznSjkMm5d8ride0C`CE A-v9sr literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/COMICMeDu.ts b/web/src/engine/websites/COMICMeDu.ts new file mode 100644 index 0000000000..0cfbfa1e49 --- /dev/null +++ b/web/src/engine/websites/COMICMeDu.ts @@ -0,0 +1,22 @@ +import { Tags } from '../Tags'; +import icon from './COMICMeDu.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('comicmedu', `COMIC MeDu (こみっくめづ)`, 'https://comic-medu.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/COMICMeDu.webp b/web/src/engine/websites/COMICMeDu.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/COMICMeDu.webp rename to web/src/engine/websites/COMICMeDu.webp diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts new file mode 100644 index 0000000000..463e9143a9 --- /dev/null +++ b/web/src/engine/websites/ComicRide.ts @@ -0,0 +1,22 @@ +import { Tags } from '../Tags'; +import icon from './ComicRide.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('comicride', `Comic Ride`, 'https://comicride.jp', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/ComicRide.webp b/web/src/engine/websites/ComicRide.webp new file mode 100644 index 0000000000000000000000000000000000000000..c1f74d493041eb0df54d7917dd1b7600e7b031b5 GIT binary patch literal 936 zcmV;Z16TY~Nk&GX0{{S5MM6+kP&goz0{{RJ69An7DnI~006v96p-`nGqav;polu|< zfCDrn0O{uSPj6z*Lg#(rLDKuo2IvR$kM&(+et;fn-|)SZzjXa0GeA2R{~=mug@1&p zw>Z^asMY2WmqZz51D9RV^kbK)xqMuYM{%_ZW;W3=)XSi*UI$|_q5T0!8vRiO{OFJ* zVcUA*ishNM8Ho@lce}}}YY|8Q0RHRh)PoKja9ft8|B!|2i5{@C z3XK#QW642z&4u(}*3Qtqkyf`S_%p2>w*}v!zsqGavZF4;Wm`7wSNvpILz|Spk>o|^ zo~Mv&y+2`2T2|XZ@l738g9qxBmR!MMepDW;R|nLx;l2n}e8^su400t}-HRbqdVr!I zDCp@JcmMC?w680r)Rq2(DlNO7%O4WPX7+ln+lxhX=d6$xFxOQOZ|Zdg6F^iBKn>ZX zVd!Ce8?V;(qTBV~Wdm|M;sg*CW~?NZE=#rb=cDN0t1Zr^-gH+mn%#b#!d0V>5eAdi zZ>83#DqG|x&0pqqI^xNit1#JAul&oSz1gc4wZoJEu{V?!*j6BQKsC^xVrbUzKP<9< zR!g^nUpv%m1z9`EWvzhj>x3D3bXTk1YK>4XGr|@tcjeX|-(F{Je*LsiDlrMKi}C}u z9aQiAm4w|xnpo;deUy$Wmj0yl6ZZu5_Ttxv5@!gh(pO+_ClWutNTlIJ7DHT zsGIC?u5SFb z?mp!|6x6zAVq*mTJR;=1WyIDIC<>z$2C04k+4v?g^Li;L!DC#@%8!0y`1R_-#O%7UWO&v|dGgTkLB>Q-A8IH3cjO9r;AWt{)|7 zK_MRG1FgwA<;Zdpo)s{h3X#% zB#z4*I&cZ{RzCuPyCM?w0#q`GhHJt4E>#pTg!Nh2QgXYMUuYmqkc=I9FQKKpDeYMt z26&ZwHfKxN)+BRH*%1^wH8}j)WZ<3)BTs_vvsO8+Z@hscpQesg@NA4<-gUv4a=XkB Kd?TRVfB*mxM!@j^ literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/YoungAnimal.ts b/web/src/engine/websites/YoungAnimal.ts new file mode 100644 index 0000000000..54bf04e76d --- /dev/null +++ b/web/src/engine/websites/YoungAnimal.ts @@ -0,0 +1,22 @@ +import { Tags } from '../Tags'; +import icon from './YoungAnimal.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('younganimal', `Young Animal`, 'https://younganimal.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/YoungAnimal.webp b/web/src/engine/websites/YoungAnimal.webp new file mode 100644 index 0000000000000000000000000000000000000000..a45b2dd58e6ba1bd5f7dfbed750e1dad1f13ce7f GIT binary patch literal 1392 zcmV-$1&{htNk&F!1pok7MM6+kP&go51pokW8vvaFDnI~006v96p-`nGqN1)A(4Y{2 z0_@Da^Pa)^5$t0~ew+B4frcydFyjyOpVI#;{oVh7_C@9a`h)&M`X5-&FdxW2r2e>j z!+tY+fb;Z2)A0W*js$lW zaY;;j%)>$-N_z(Ms8UEq1Fh~mb8Zple!%qnuJOoZ4_3&QTAG&U!t*}at!x9DI;+>k z_l#Q4lJ&(4t%!<943j}`29hb!%sc^^XXcB}vZ{_w_2 z6P&^ZcU_(HkKg?Mg|3Ih(VB&%e@15}>D9Ff-62}+Z@>NnR6Um?k3b!VbMrLP|G)jQ zq%s|wN8Xm5Vff!kzLT=vN$qxHM_rM6Nu)df7tAiM#R!7FOm?=J3z22fH8#<{5o~au z_&wi-`Q(JxqlNZ7&{IDt`hLyB=im=t61m*hG8JQbX+Puq|9ZeqQ8z?8O@~oJvPxheqT1%p|daU3ONl`jjWBkXe z2I9OQ7P(Jm#xGNL>=md*e(nGCH_iW3YDadf=nUCMIxIg7!Dk8^>(Kjt28q#KQvKxF zutLmm7Tg;8`0kx*spef*G1e#%LUkwyb6Gs;JRJgzM)IU^prQ=6%10EB0oX2NpduUT_9TL8!PnE(jN8#_)S4sDV;x%n|I8@%q;LzvTuUSG{TU%mwR?h-0+xKyje%f`;vdp)9GxURAxbo|l z#X0qH9yDq!nBVncAxZWQx-@#jJmAJUfUP^n`01bpawJ!mmg~we-ieFqi-wVy*4i%r zHTdM{Q#k3xKFk$SX|jU>`VD|FlB3#>4R5KXz>7S}}ZqmByAZ1s1wg?|0I>w!~En z$GOWXV+d6nx*DGRY*xW@%ikR49JCe-!8vL8x$@vJ=hRB#y5fP}YQ-lNQQWUb zUR;)Gi^#407wE8m%n%yQ-E#H^Lwsh+ty-_|s9KR@_B;Jtke>|oy{=vhYD_$ol%HRA zKl)}rWMbTv`>hU?(^00xIifti?v*FCPqUi)V>q5dN1+ae!=@O^2PHW9i)@D)Wyj(v z^Ys`Q>M)e7sP60PVx)Qb(IR9%IoLklrsW($+QZ2#U!z^P z-08;455d?E)ARNVl(_bZT}GxeLrE>*pAD9n*X$=vv0Z=O)66y=GbTu@Fr&MGUer>i z2}ggNsM%?pjy3SoJv^A~;5plI0(rm?Mj^;c@hRh-S7=o`$$Jqd?nF;((Z;JX6r#~L z*>xfmL>?fNTUex-Im@%C=4WY{^8LpT+^ol%w&^{Y`cEDFV;&R z|K=3jErzBEp&Umt;`;P7Mc8Lgapuvtyqx5D4aS_*ahC)g4x&A8HL{_TpWCg4_w<=? ypkM*kQMJ5WQZL+NWm}-Rzf=Aho#82^OU;R z0a~MP^6P)i_RfVEFrfY*eXyVXN`6XYqEO*y>+u`>tDI}mdmtd9t+6rcmM<@*VUzK>gVPAJ*;PBRitJrI6_KwXCx;=G`)asY?C8}{PK-AHj zxE-{31Kuhq%iSVW2kHI-a1`jjUN|t^o1R@CD?3Y+>gFKr;wyIoF;tPpp_wb@JAv3S zi^yAQIA{%V-hXv+lPG8U#Cz{i7zLtwoYt~xeibi%X-MX&f=h_{VpkEgF4y1lPX~KS zM0 zBgWiWT|G`vQo#_`^H!~PvDAE+`%UOSpcETyrf)Q?X3p?)&MB|)ybYcZuJ&iHQ5R^` z3uOMO3dzq6$;Kreg{)8Y*n`JtvE^KgPx6fBO(WQwJKYqXsyPqoHSD4c-Q_|V%^=-SP)wb(=ZN)bls1zn+zPLbn@LPPuLHh&_J4d#i0>^xmvS5xNyvY|7McqRCOb zMdQc4qwqcYPLtX;P0JySH_j3Gz=aRB9YS{l=dHCyZ^-P`v^dEed)>5hev%fb*t3?>8jK3l=*7iZb)yi&&K-?y=c}^C|7S-Eaq44?d1CE>~~w7?VeYb zeqA4!Es5(RNQ-IK$D(eMUlN=YhwX%ri@zv3{|nCXY|~=yGU)`^C!kwYkI>e<4P+kD zJDB8>6%MEW0C}#B&rb1KGFSn&f00ut0lZy8kx8`WTn_$&F@Jlc4cROc3RQWi=H^py zW7;atV0s4~ysL|b`;%MOVBC(icS{fyfG3;CXkCw{Yv7o=hT6pU16ydUN<`|47MK74 E0Pb4&X8-^I literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 605ee1d3d8..a6393020c1 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -40,6 +40,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; export { default as Boosei } from './Boosei'; @@ -64,8 +65,10 @@ export { default as ComicFX } from './ComicFX'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; @@ -680,6 +683,8 @@ export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as Yurineko } from './Yurineko'; @@ -706,7 +711,6 @@ export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts new file mode 100644 index 0000000000..267f39cc9d --- /dev/null +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -0,0 +1,226 @@ +//Comici viewer based websites : BigComics, YoungChampion, YoungAnimal, ComicMedu, ComicRide + +import { Exception } from "../../Error"; +import { FetchCSS, FetchJSON } from "../../platform/FetchProvider"; +import { Page, Chapter, type MangaScraper, type Manga } from "../../providers/MangaPlugin"; +import type { Priority } from "../../taskpool/DeferredTask"; +import DeScramble from "../../transformers/ImageDescrambler"; +import * as Common from "./Common"; +import { WebsiteResourceKey as R } from '../../../i18n/ILocale'; + +export const mangaListPath = '/series/list?page={page}'; +export const queryMangaTitleURI = 'h1.series-h-title span:not([class])'; +export const queryManga = 'div.series-box-vertical a'; +const queryMangaTitle = 'h2.title-text'; +export const queryChapter = 'div.series-ep-list a[data-href]'; +const queryChapterTitle = 'span.series-ep-list-item-h-text'; + +const defaultOrder: Array> = []; +for (let i = 0; i < 4; i++) { + for (let j = 0; j < 4; j++) { + defaultOrder.push([i, j]); + } +} + +type APIResult = { + code: number, + message: string, + result: T, + totalPages: number +} + +type APIPage = { + imageUrl: string, + scramble: string +} + +export function MangaExtractor(element: HTMLAnchorElement) { + const titleElement = element.querySelector(queryMangaTitle); + return { + id: element.pathname, + title: titleElement ? titleElement.textContent.trim() : element.text.trim() + }; +} + +export function ChapterExtractor(element: HTMLAnchorElement) { + const titleElement = element.querySelector(queryChapterTitle); + return { + id: new URL(element.dataset['href']).pathname, + title: titleElement ? titleElement.textContent .trim() : element.text.trim() + }; +} + +/************************************************* + ******** Chapter List Extraction Methods ******** + *************************************************/ + +/** + * An extension method for extracting all chapters for the given {@link manga} using the given CSS {@link query}. + * The chapters are extracted from the composed url based on the `Identifier` of the {@link manga} 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 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 extract - A function to extract the chapter identifier and title from a single element (found with {@link query}) + */ +export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query: string = queryChapter, extract = ChapterExtractor): Promise { + const uri = new URL(manga.Identifier+ '/list', this.URI); + const request = new Request(uri.href, { + headers: { + Referer: this.URI.href + } + }); + const data = await FetchCSS(request, query); + return data.map(element => { + const { id, title } = extract.call(this, element); + return new Chapter(this, manga, id, title.replace(manga.Title, '').trim() || manga.Title); + }).distinct(); +} + +/** + * A class decorator that adds the ability to extract all chapters for a given manga from this website using the given CSS {@link query}. + * The chapters are extracted from the composed url based on the `Identifier` of the manga and the `URI` of the website. + * @param query - A CSS query to locate the elements from which the chapter identifier and title shall be extracted + * @param extract - A function to extract the chapter identifier and title from a single element (found with {@link query}) + */ +export function ChaptersSinglePageCSS(query: string = queryChapter, extract = 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, extract); + } + }; + }; +} + +/********************************************** + ******** Page List Extraction Methods ******** + **********************************************/ + +/** + * An extension method for extracting all pages for the given {@link chapter}. + * 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 + */ +export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chapter): Promise { + const uri = new URL(chapter.Identifier, this.URI); + const request = new Request(uri.href, { + headers: { + Referer: this.URI.origin + } + }); + const [viewer] = await FetchCSS(request, '#comici-viewer'); + if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); + + const coord = await fetchCoordInfo(this, viewer); + return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble })); +} + +/** + * A class decorator that adds the ability to extract all pages for a given chapter. + * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. + */ +export function PagesSinglePageAJAX() { + 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); + } + }; + }; +} + +async function fetchCoordInfo(scraper: MangaScraper, viewer: HTMLElement): Promise> { + //first request get page count + let uri = new URL('/book/contentsInfo', scraper.URI); + let params = new URLSearchParams({ + 'comici-viewer-id': viewer.getAttribute('comici-viewer-id'), + 'user-id': viewer.dataset['memberJwt'], + 'page-from': '0', + 'page-to': '1', + }); + + uri.search = params.toString(); + let request = new Request(uri, { + headers: { + Origin: scraper.URI.origin, + Referer: scraper.URI.origin + } + }); + const data = await FetchJSON < APIResult>(request); + + //second request fetch actual pages data + const numbers = data.totalPages; + + uri = new URL('/book/contentsInfo', scraper.URI); + params = new URLSearchParams({ + 'comici-viewer-id': viewer.getAttribute('comici-viewer-id'), + 'user-id': viewer.dataset['memberJwt'], + 'page-from': '0', + 'page-to': numbers.toString() + }); + uri.search = params.toString(); + request = new Request(uri, { + headers: { + Origin: scraper.URI.origin, + Referer: scraper.URI.origin + } + }); + return await FetchJSON>(request); +} + +/*********************************************** + ******** Image Data Extraction Methods ******** + ***********************************************/ + +/** + * An extension method to get the image data for the given {@link page}. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param page - A reference to the {@link Page} containing the necessary information to acquire the image data + * @param priority - The importance level for ordering the request for the image data within the internal task pool + * @param signal - An abort signal that can be used to cancel the request for the image data + * @param detectMimeType - Force a fingerprint check of the image data to detect its mime-type (instead of relying on the Content-Type header) + */ +async function FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { + const data = await Common.FetchImageAjax.call(this, page, priority, signal, detectMimeType); + return !page.Parameters?.scramble ? data : DeScramble(data, async (image, ctx) => { + + const decodedArray = decodeScrambleArray(page.Parameters.scramble as string); + const tileWidth = Math.floor(image.width / 4); + const tileHeight = Math.floor(image.height / 4); + for (let k = 0, i = 0; i < 4; i++) { + for (let j = 0; j < 4; j++) { + const x = decodedArray[k][0], y = decodedArray[k][1]; + ctx.drawImage(image, tileWidth * x, tileHeight * y, tileWidth, tileHeight, tileWidth * i, tileHeight * j, tileWidth, tileHeight); + k++; + } + } + }); + +} + +/** + * A class decorator that adds the ability to get the image data for a given page by loading the source asynchronous with the `Fetch API`. + * @param detectMimeType - Force a fingerprint check of the image data to detect its mime-type (instead of relying on the Content-Type header) + */ +export function ImageAjax(detectMimeType = false) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); + return class extends ctor { + public async FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal): Promise { + return FetchImage.call(this, page, priority, signal, detectMimeType); + } + }; + }; +} + +function decodeScrambleArray(scramble: string): number[][] { + const decoded : number[][]= []; + const encoded = scramble.replace(/\s+/g, '').slice(1).slice(0, -1).split(','); + for (let i = 0; i < defaultOrder.length; i++) { + decoded.push(defaultOrder[encoded[i]]); + } + return decoded; +} diff --git a/web/src/engine/websites/legacy/COMICMeDu.ts b/web/src/engine/websites/legacy/COMICMeDu.ts deleted file mode 100755 index b7cf9568cb..0000000000 --- a/web/src/engine/websites/legacy/COMICMeDu.ts +++ /dev/null @@ -1,98 +0,0 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; -import icon from './COMICMeDu.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; - -export default class extends DecoratableMangaScraper { - - public constructor() { - super('comicmedu', `COMIC MeDu (こみっくめづ)`, 'http://comic-medu.com' /*, Tags.Language.English, Tags ... */); - } - - public override get Icon() { - return icon; - } -} - -// Original Source -/* -class COMICMeDu extends Connector { - - constructor() { - super(); - super.id = 'comicmedu'; - super.label = 'COMIC MeDu (こみっくめづ)'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'http://comic-medu.com'; - - this.path = [ '/wk' ]; - this.queryMangaListCount = 'article div#conMain div.conDoc ul.pagination li'; - this.queryManga = 'article div#conMain div.conDoc div#listB div.listM'; - this.queryMangaLink = 'a'; - this.queryMangaTitle = 'h3.listTtl'; - - this.queryChapters = 'article div#conMain div.conDoc ul.episode li a'; - this.queryShortChapter = 'article div#conMain div.conDoc div.btDetail a.btDetailR'; - - this.queryPages = 'article div.swiper-container div.swiper-wrapper div.swiper-slide source[class*="storyImg"]'; - } - - async _getMangaFromURI(uri) { - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'head title'); - let id = uri.pathname; - let title = data[0].text.split('|')[0].trim(); - return new Manga(this, id, title); - } - - async _mapMangas(mangas) { - return mangas.map(series => { - return { - id: this.getRootRelativeOrAbsoluteLink(series.querySelector(this.queryMangaLink), this.url), - title: series.querySelector(this.queryMangaTitle).textContent - }; - }); - } - - async _getMangas() { - let uri = new URL(this.url + this.path[0]); - let request = new Request(uri, this.requestOptions); - let seriesPages = await this.fetchDOM(request, this.queryMangaListCount); - let totalPages = seriesPages.length; - let mangas = await this.fetchDOM(request, this.queryManga); - let mangaList = await this._mapMangas(mangas); - for(let page = 2; page <= totalPages; page++) { - uri.searchParams.set('page', page); - request = new Request(uri, this.requestOptions); - mangas = await this._mapMangas(await this.fetchDOM(request, this.queryManga)); - mangaList.push(...mangas); - } - return mangaList; - } - - async _getChapters(manga) { - let uri = new URL(this.url + manga.id); - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, this.queryChapters); - if(data.length == 0) { // series is a short story; only one chapter - data = await this.fetchDOM(request, this.queryShortChapter); - data[0].textContent = manga.title; - } - return data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, request.url), - title: element.textContent - }; - }); - } - - async _getPages(chapter) { - let uri = new URL(this.url + chapter.id); - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, this.queryPages); - return data.map(element => this.getAbsolutePath(element, request.url)); - } -} -*/ \ No newline at end of file From 90aa318a59897dde3eb435061f28e240a22803c7 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 22 Feb 2024 13:48:22 +0100 Subject: [PATCH 02/28] add tests & tiny fixes --- web/src/engine/websites/BigComics.ts | 2 +- web/src/engine/websites/BigComics_e2e.ts | 25 +++++++++++++++++++ web/src/engine/websites/COMICMeDu.ts | 2 +- web/src/engine/websites/COMICMeDu_e2e.ts | 25 +++++++++++++++++++ web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/ComicRide_e2e.ts | 25 +++++++++++++++++++ web/src/engine/websites/YoungAnimal.ts | 2 +- web/src/engine/websites/YoungAnimal_e2e.ts | 25 +++++++++++++++++++ web/src/engine/websites/YoungChampion.ts | 2 +- web/src/engine/websites/YoungChampion_e2e.ts | 25 +++++++++++++++++++ .../websites/decorators/ComiciViewer.ts | 4 +-- 11 files changed, 132 insertions(+), 7 deletions(-) create mode 100644 web/src/engine/websites/BigComics_e2e.ts create mode 100644 web/src/engine/websites/COMICMeDu_e2e.ts create mode 100644 web/src/engine/websites/ComicRide_e2e.ts create mode 100644 web/src/engine/websites/YoungAnimal_e2e.ts create mode 100644 web/src/engine/websites/YoungChampion_e2e.ts diff --git a/web/src/engine/websites/BigComics.ts b/web/src/engine/websites/BigComics.ts index bd5ecea2d2..dc59ec986f 100644 --- a/web/src/engine/websites/BigComics.ts +++ b/web/src/engine/websites/BigComics.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/BigComics_e2e.ts b/web/src/engine/websites/BigComics_e2e.ts new file mode 100644 index 0000000000..140bd04fef --- /dev/null +++ b/web/src/engine/websites/BigComics_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'bigcomics', + title: 'Big Comics' + }, + container: { + url: 'https://bigcomics.jp/series/48eef350d364a', + id: '/series/48eef350d364a', + title: '岳' + }, + child: { + id: '/episodes/4b87f55986ccc', + title: '1巻-第0歩 お家' + }, + entry: { + index: 0, + size: 670_778, + 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/COMICMeDu.ts b/web/src/engine/websites/COMICMeDu.ts index 0cfbfa1e49..2b16073117 100644 --- a/web/src/engine/websites/COMICMeDu.ts +++ b/web/src/engine/websites/COMICMeDu.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/COMICMeDu_e2e.ts b/web/src/engine/websites/COMICMeDu_e2e.ts new file mode 100644 index 0000000000..1f4c8b1a3d --- /dev/null +++ b/web/src/engine/websites/COMICMeDu_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'comicmedu', + title: 'COMIC MeDu (こみっくめづ)' + }, + container: { + url: 'https://comic-medu.com/series/c2f3978c40eea/', + id: '/series/c2f3978c40eea/', + title: 'ぱらのいあけ〜じ' + }, + child: { + id: '/episodes/beaa305e9cf32', + title: 'その(1)' + }, + entry: { + index: 0, + size: 760_096, + 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/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index 463e9143a9..e45b014321 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts new file mode 100644 index 0000000000..6ed1a6bf71 --- /dev/null +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'comicride', + title: 'Comic Ride' + }, + container: { + url: 'https://comicride.jp/series/24a2c5eb2d433/', + id: '/series/24a2c5eb2d433/', + title: '呪われ侯爵様の訳ありメイド' + }, + child: { + id: '/episodes/48d531d8140b5', + title: '第1話' + }, + entry: { + index: 0, + size: 3_298_112, + 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/YoungAnimal.ts b/web/src/engine/websites/YoungAnimal.ts index 54bf04e76d..00947e3812 100644 --- a/web/src/engine/websites/YoungAnimal.ts +++ b/web/src/engine/websites/YoungAnimal.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts new file mode 100644 index 0000000000..462c1e8736 --- /dev/null +++ b/web/src/engine/websites/YoungAnimal_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'younganimal', + title: 'Young Animal' + }, + container: { + url: 'https://younganimal.com/series/8f24a114d125e/', + id: '/series/8f24a114d125e/', + title: '拷問バイトくんの日常' + }, + child: { + id: '/episodes/c44e40bd07ed7', + title: '第1話' + }, + entry: { + index: 0, + size: 933_886, + 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/YoungChampion.ts b/web/src/engine/websites/YoungChampion.ts index b2d8389a9b..ee68e59654 100644 --- a/web/src/engine/websites/YoungChampion.ts +++ b/web/src/engine/websites/YoungChampion.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungChampion_e2e.ts b/web/src/engine/websites/YoungChampion_e2e.ts new file mode 100644 index 0000000000..d889a3d891 --- /dev/null +++ b/web/src/engine/websites/YoungChampion_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'youngchampion', + title: 'Young Champion' + }, + container: { + url: 'https://youngchampion.jp/series/b20f6fa2cc69a/', + id: '/series/b20f6fa2cc69a/', + title: '惨家' + }, + child: { + id: '/episodes/2aa2386bccbcd', + title: '第1話' + }, + entry: { + index: 0, + size: 2_649_022, + 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/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 267f39cc9d..fbbefeb49d 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -37,7 +37,7 @@ type APIPage = { export function MangaExtractor(element: HTMLAnchorElement) { const titleElement = element.querySelector(queryMangaTitle); return { - id: element.pathname, + id: element.pathname.endsWith('/') ? element.pathname : `${element.pathname}/`, title: titleElement ? titleElement.textContent.trim() : element.text.trim() }; } @@ -63,7 +63,7 @@ export function ChapterExtractor(element: HTMLAnchorElement) { * @param extract - A function to extract the chapter identifier and title from a single element (found with {@link query}) */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query: string = queryChapter, extract = ChapterExtractor): Promise { - const uri = new URL(manga.Identifier+ '/list', this.URI); + const uri = new URL(manga.Identifier+ 'list', this.URI);//we enforced a trailing / const request = new Request(uri.href, { headers: { Referer: this.URI.href From 15aeaaa721a971697b5a030cc2dd99f1952add2f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 6 Mar 2024 21:59:33 +0100 Subject: [PATCH 03/28] Comici : use site for pages referer and fixes trailing '/' handling --- web/src/engine/websites/BigComics.ts | 2 +- web/src/engine/websites/COMICMeDu.ts | 2 +- web/src/engine/websites/COMICMeDu_e2e.ts | 4 ++-- web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/ComicRide_e2e.ts | 4 ++-- web/src/engine/websites/YoungAnimal.ts | 2 +- web/src/engine/websites/YoungAnimal_e2e.ts | 4 ++-- web/src/engine/websites/YoungChampion.ts | 2 +- web/src/engine/websites/YoungChampion_e2e.ts | 4 ++-- web/src/engine/websites/decorators/ComiciViewer.ts | 6 +++--- 10 files changed, 16 insertions(+), 16 deletions(-) diff --git a/web/src/engine/websites/BigComics.ts b/web/src/engine/websites/BigComics.ts index dc59ec986f..3eed3fa48e 100644 --- a/web/src/engine/websites/BigComics.ts +++ b/web/src/engine/websites/BigComics.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/COMICMeDu.ts b/web/src/engine/websites/COMICMeDu.ts index 2b16073117..e1b709ec0d 100644 --- a/web/src/engine/websites/COMICMeDu.ts +++ b/web/src/engine/websites/COMICMeDu.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/COMICMeDu_e2e.ts b/web/src/engine/websites/COMICMeDu_e2e.ts index 1f4c8b1a3d..badd19efac 100644 --- a/web/src/engine/websites/COMICMeDu_e2e.ts +++ b/web/src/engine/websites/COMICMeDu_e2e.ts @@ -6,8 +6,8 @@ const config = { title: 'COMIC MeDu (こみっくめづ)' }, container: { - url: 'https://comic-medu.com/series/c2f3978c40eea/', - id: '/series/c2f3978c40eea/', + url: 'https://comic-medu.com/series/c2f3978c40eea', + id: '/series/c2f3978c40eea', title: 'ぱらのいあけ〜じ' }, child: { diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index e45b014321..c917489a83 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index 6ed1a6bf71..e5573e63b1 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -6,8 +6,8 @@ const config = { title: 'Comic Ride' }, container: { - url: 'https://comicride.jp/series/24a2c5eb2d433/', - id: '/series/24a2c5eb2d433/', + url: 'https://comicride.jp/series/24a2c5eb2d433', + id: '/series/24a2c5eb2d433', title: '呪われ侯爵様の訳ありメイド' }, child: { diff --git a/web/src/engine/websites/YoungAnimal.ts b/web/src/engine/websites/YoungAnimal.ts index 00947e3812..343de455d5 100644 --- a/web/src/engine/websites/YoungAnimal.ts +++ b/web/src/engine/websites/YoungAnimal.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts index 462c1e8736..81916f2ef1 100644 --- a/web/src/engine/websites/YoungAnimal_e2e.ts +++ b/web/src/engine/websites/YoungAnimal_e2e.ts @@ -6,8 +6,8 @@ const config = { title: 'Young Animal' }, container: { - url: 'https://younganimal.com/series/8f24a114d125e/', - id: '/series/8f24a114d125e/', + url: 'https://younganimal.com/series/8f24a114d125e', + id: '/series/8f24a114d125e', title: '拷問バイトくんの日常' }, child: { diff --git a/web/src/engine/websites/YoungChampion.ts b/web/src/engine/websites/YoungChampion.ts index ee68e59654..6ff617659d 100644 --- a/web/src/engine/websites/YoungChampion.ts +++ b/web/src/engine/websites/YoungChampion.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+\/$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungChampion_e2e.ts b/web/src/engine/websites/YoungChampion_e2e.ts index d889a3d891..a83ad6dd4c 100644 --- a/web/src/engine/websites/YoungChampion_e2e.ts +++ b/web/src/engine/websites/YoungChampion_e2e.ts @@ -6,8 +6,8 @@ const config = { title: 'Young Champion' }, container: { - url: 'https://youngchampion.jp/series/b20f6fa2cc69a/', - id: '/series/b20f6fa2cc69a/', + url: 'https://youngchampion.jp/series/b20f6fa2cc69a', + id: '/series/b20f6fa2cc69a', title: '惨家' }, child: { diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index fbbefeb49d..1a22f60cb1 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -37,7 +37,7 @@ type APIPage = { export function MangaExtractor(element: HTMLAnchorElement) { const titleElement = element.querySelector(queryMangaTitle); return { - id: element.pathname.endsWith('/') ? element.pathname : `${element.pathname}/`, + id: element.pathname.replace(/\/$/, ''), title: titleElement ? titleElement.textContent.trim() : element.text.trim() }; } @@ -63,7 +63,7 @@ export function ChapterExtractor(element: HTMLAnchorElement) { * @param extract - A function to extract the chapter identifier and title from a single element (found with {@link query}) */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query: string = queryChapter, extract = ChapterExtractor): Promise { - const uri = new URL(manga.Identifier+ 'list', this.URI);//we enforced a trailing / + const uri = new URL(manga.Identifier+ '/list', this.URI); const request = new Request(uri.href, { headers: { Referer: this.URI.href @@ -114,7 +114,7 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); const coord = await fetchCoordInfo(this, viewer); - return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble })); + return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } /** From 3d065fe2941ebd40dabb0ff0f9a918c188657131 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 6 Mar 2024 21:59:59 +0100 Subject: [PATCH 04/28] Add MangaBANG https://github.com/manga-download/hakuneko/issues/6859 --- web/src/engine/websites/MangaBANG.ts | 22 ++++++++++++++++++++ web/src/engine/websites/MangaBANG.webp | Bin 0 -> 1178 bytes web/src/engine/websites/MangaBANG_e2e.ts | 25 +++++++++++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 48 insertions(+) create mode 100644 web/src/engine/websites/MangaBANG.ts create mode 100644 web/src/engine/websites/MangaBANG.webp create mode 100644 web/src/engine/websites/MangaBANG_e2e.ts diff --git a/web/src/engine/websites/MangaBANG.ts b/web/src/engine/websites/MangaBANG.ts new file mode 100644 index 0000000000..1dfcd0ded6 --- /dev/null +++ b/web/src/engine/websites/MangaBANG.ts @@ -0,0 +1,22 @@ +import { Tags } from '../Tags'; +import icon from './MangaBANG.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() + +export default class extends DecoratableMangaScraper { + + public constructor() { + super('mangabang', `MangaBANG Comics (マンガBANG コミックス)`, 'https://comics.manga-bang.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/MangaBANG.webp b/web/src/engine/websites/MangaBANG.webp new file mode 100644 index 0000000000000000000000000000000000000000..fad58d4bf6838e1018ae6ce8a5bed9091eed94df GIT binary patch literal 1178 zcmV;L1ZDeDNk&GJ1ONb6MM6+kP&gol1ONaK7yz9CDnI~006v96p-`nGqavsb0H6?n z0pjjpcfB}ofs6*&4=^8S93UU8-DDns9$CM%e+XZDEb{~NDQqFYn_ z!$kd|OT$@a75vySl~}6J+w7DEWd1V^4fnD2B+Ir5?*kL#A&Dhghmaqo_{J&)l~mws+9TfZ)R#l}{QgXint z{{PJP{L)cx4OM2VPs27nqkxOv$iIQ`PMho#5`$Rpko#Y8jXC{?VFv0zskBPq%u#_| z=0S)J3HtOWAHteOD9+h^_3(UJ%a$A=i9mY-zJZ&n9WEL+(12){kCu znTj8)+?DWSz6PS1pipb~Ei3;;sN)oA@>MpLc3L7|=)7lVPO|?dy@DtHmpwMNoE19I zg)5W(vpxqp{i*ol5QyuA9A@^aCe=j3mUX*8UFNZx7&`?UhB!vocZ0VNE17?a!UtpT zkpI`cg6AT1r5|QKH&;H`ViITP1Q$eth_@+imluyj5;ypGt+ym)&~YdGM+oJ8PS<^K z-0lmYZey#3)Yg$O#yWJLkcYJ?Fd^&8=PryZUa*@?9Q_a#`NW%<*}OZk2rQbeoN+J@;FodQVS%1|mB$4t_ zjnn>-H?6gp!{HAWhJLf#P3RquG!b}Cdp16T{E8tj3r`xG^O!XR?4YFXmwm98mUht& zmEi{2ECf@SxlBo%8$6=6f+hFL(qGE&rEp%$SNfpaw_{DeKmkp>zZQKy|1JT*qxV{R zEsS0mCZ+-r-o65qP#ft}L;7=Uj3A~^ot2NN^8#C_uE 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 a6393020c1..066067c7de 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -283,6 +283,7 @@ export { default as Manga1001top } from './Manga1001top'; export { default as MangaAction } from './MangaAction'; export { default as MangaArab } from './MangaArab'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabaz } from './Mangabaz'; export { default as MangaBob } from './MangaBob'; From fb0b692a816bee586b348993d807aad61477a7b3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 9 Mar 2024 14:08:11 +0100 Subject: [PATCH 05/28] minor code changes --- web/src/engine/websites/decorators/ComiciViewer.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 1a22f60cb1..1232f38167 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -64,9 +64,9 @@ export function ChapterExtractor(element: HTMLAnchorElement) { */ export async function FetchChaptersSinglePageCSS(this: MangaScraper, manga: Manga, query: string = queryChapter, extract = ChapterExtractor): Promise { const uri = new URL(manga.Identifier+ '/list', this.URI); - const request = new Request(uri.href, { + const request = new Request(uri, { headers: { - Referer: this.URI.href + Referer: this.URI.origin } }); const data = await FetchCSS(request, query); @@ -104,8 +104,7 @@ export function ChaptersSinglePageCSS(query: string = queryChapter, extract = Ch * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages */ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chapter): Promise { - const uri = new URL(chapter.Identifier, this.URI); - const request = new Request(uri.href, { + const request = new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } @@ -168,7 +167,7 @@ async function fetchCoordInfo(scraper: MangaScraper, viewer: HTMLElement): Promi Referer: scraper.URI.origin } }); - return await FetchJSON>(request); + return FetchJSON>(request); } /*********************************************** From 3b3a2622e32a6a3fabd64d187c87f6071b341931 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 30 Mar 2024 10:46:25 +0100 Subject: [PATCH 06/28] MagKan : now uses Comici --- web/src/engine/websites/MagKan.ts | 41 +++++---------------------- web/src/engine/websites/MagKan_e2e.ts | 12 ++++---- 2 files changed, 13 insertions(+), 40 deletions(-) diff --git a/web/src/engine/websites/MagKan.ts b/web/src/engine/websites/MagKan.ts index 492193e270..a57d286e2a 100644 --- a/web/src/engine/websites/MagKan.ts +++ b/web/src/engine/websites/MagKan.ts @@ -1,19 +1,14 @@ import { Tags } from '../Tags'; import icon from './MagKan.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, Page } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; -import { Fetch, FetchCSS } from '../platform/FetchProvider'; +import * as Comici from './decorators/ComiciViewer'; -function MangaExtractor(element: HTMLElement) { - return { - id: element.querySelector('a').pathname, - title: element.querySelector('h2.comic_name').textContent.trim() - }; -} - -@Common.MangaCSS(/^{origin}\/[^/]+/, 'h1.ttl') -@Common.MangasSinglePageCSS('/', 'div#main div.panel div.box div.inner', MangaExtractor) -@Common.ImageAjax() +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() export default class extends DecoratableMangaScraper { @@ -25,26 +20,4 @@ export default class extends DecoratableMangaScraper { return icon; } - public override async FetchChapters(manga: Manga): Promise { - const request = new Request(new URL(manga.Identifier, this.URI).href); - const [mainDiv] = await FetchCSS(request, 'div#main'); - const current = [...mainDiv.querySelectorAll('div#main div.update_summary div.exp ul.btn li a[href*="/assets/files/"]')].map(element => { - const id = element.pathname.replace(/\/HTML5\/?$/i, ''); - return new Chapter(this, manga, id, element.text.replace('を読む', '').trim()); - }); - const previous = [...mainDiv.querySelectorAll('div#main div.sam_exp div.exp')].map(element => { - const id = element.querySelector('ul.btn li a[href*="/assets/files/"]').pathname.replace(/\/HTML5\/?$/i, ''); - return new Chapter(this, manga, id, element.querySelector('div.back_number_summary div.ttl').textContent.trim()); - }); - return [...current, ...previous].distinct(); - } - - public override async FetchPages(chapter: Chapter): Promise { - const uri = new URL(chapter.Identifier + '/iPhone/ibook.xml', this.URI); - const response = await Fetch(new Request(uri.href)); - const data = await response.text(); - const pages = parseInt(data.match(/(\d+)<\/total>/)[1]); - return new Array(pages).fill(null).map((_, index) => new Page(this, chapter, new URL(`${chapter.Identifier}/books/images/2/${index + 1}.jpg`, uri))); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/MagKan_e2e.ts b/web/src/engine/websites/MagKan_e2e.ts index 0dd9323e36..855bcdc3b2 100644 --- a/web/src/engine/websites/MagKan_e2e.ts +++ b/web/src/engine/websites/MagKan_e2e.ts @@ -6,18 +6,18 @@ const config = { title: 'MagKan' }, container: { - url: 'https://kansai.mag-garden.co.jp/oshihen/', - id: '/oshihen/', + url: 'https://kansai.mag-garden.co.jp/series/76efde6cc8881/', + id: '/series/76efde6cc8881/', title: '推し変しやがれ!!' }, child: { - id: '/assets/files/oshihen1', - title: '第零話' + id: '/episodes/90451498292e5', + title: '第七話【前】' }, entry: { index: 1, - size: 317_098, - type: 'image/jpeg' + size: 1_235_068, + type: 'image/png' } }; From f6a38a5c43c81a69573b6210bf69ec9c0dfab4d2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 30 Mar 2024 10:50:48 +0100 Subject: [PATCH 07/28] Comici websites : better regexp This commit allow copypasting a manga with a trailing "/" too (website provide both depending on how the manga link was gathered) --- web/src/engine/websites/BigComics.ts | 2 +- web/src/engine/websites/COMICMeDu.ts | 2 +- web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/MangaBANG.ts | 2 +- web/src/engine/websites/YoungAnimal.ts | 2 +- web/src/engine/websites/YoungChampion.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/BigComics.ts b/web/src/engine/websites/BigComics.ts index 3eed3fa48e..87f5fa1935 100644 --- a/web/src/engine/websites/BigComics.ts +++ b/web/src/engine/websites/BigComics.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/COMICMeDu.ts b/web/src/engine/websites/COMICMeDu.ts index e1b709ec0d..9ef6b424c2 100644 --- a/web/src/engine/websites/COMICMeDu.ts +++ b/web/src/engine/websites/COMICMeDu.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index c917489a83..f1d8c8af1b 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/MangaBANG.ts b/web/src/engine/websites/MangaBANG.ts index 1dfcd0ded6..7d4dd9f123 100644 --- a/web/src/engine/websites/MangaBANG.ts +++ b/web/src/engine/websites/MangaBANG.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungAnimal.ts b/web/src/engine/websites/YoungAnimal.ts index 343de455d5..826fa1fd13 100644 --- a/web/src/engine/websites/YoungAnimal.ts +++ b/web/src/engine/websites/YoungAnimal.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() diff --git a/web/src/engine/websites/YoungChampion.ts b/web/src/engine/websites/YoungChampion.ts index 6ff617659d..09897ea486 100644 --- a/web/src/engine/websites/YoungChampion.ts +++ b/web/src/engine/websites/YoungChampion.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; -@Common.MangaCSS(/^{origin}\/series\/[^/]+$/, Comici.queryMangaTitleURI) +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) @Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() From 2813aaca705ff88d03f909671d6cd8a6f2d353a4 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Apr 2024 09:50:06 +0200 Subject: [PATCH 08/28] update index --- web/src/engine/websites/MagKan.ts | 1 - web/src/engine/websites/_index.ts | 7 ++++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/MagKan.ts b/web/src/engine/websites/MagKan.ts index a57d286e2a..0d0c56bc60 100644 --- a/web/src/engine/websites/MagKan.ts +++ b/web/src/engine/websites/MagKan.ts @@ -9,7 +9,6 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index fd139ab887..6304870cb5 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -40,6 +40,7 @@ export { default as BakaMan } from './BakaMan'; export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BestManhua } from './BestManhua'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; @@ -64,8 +65,10 @@ export { default as ComicFX } from './ComicFX'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; @@ -280,6 +283,7 @@ export { default as Manga1001top } from './Manga1001top'; export { default as MangaAction } from './MangaAction'; export { default as MangaArab } from './MangaArab'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabaz } from './Mangabaz'; export { default as MangaBob } from './MangaBob'; @@ -696,6 +700,8 @@ export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -723,7 +729,6 @@ export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From 1dd3a420f452a79169950379227c2a0dd4aedbc5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Apr 2024 10:20:28 +0200 Subject: [PATCH 09/28] adjust manga selector --- web/src/engine/websites/decorators/ComiciViewer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 1232f38167..12f093ed7b 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -10,7 +10,7 @@ import { WebsiteResourceKey as R } from '../../../i18n/ILocale'; export const mangaListPath = '/series/list?page={page}'; export const queryMangaTitleURI = 'h1.series-h-title span:not([class])'; -export const queryManga = 'div.series-box-vertical a'; +export const queryManga = 'div.series-box-vertical > a'; const queryMangaTitle = 'h2.title-text'; export const queryChapter = 'div.series-ep-list a[data-href]'; const queryChapterTitle = 'span.series-ep-list-item-h-text'; From b78091a205e670361db10b0dae01d82b1588cf64 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Apr 2024 10:21:09 +0200 Subject: [PATCH 10/28] clean code --- web/src/engine/websites/BigComics.ts | 1 - web/src/engine/websites/COMICMeDu.ts | 1 - web/src/engine/websites/ComicRide.ts | 1 - web/src/engine/websites/MangaBANG.ts | 1 - web/src/engine/websites/YoungAnimal.ts | 2 -- web/src/engine/websites/YoungChampion.ts | 2 -- 6 files changed, 8 deletions(-) diff --git a/web/src/engine/websites/BigComics.ts b/web/src/engine/websites/BigComics.ts index 87f5fa1935..b55d575b78 100644 --- a/web/src/engine/websites/BigComics.ts +++ b/web/src/engine/websites/BigComics.ts @@ -9,7 +9,6 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/COMICMeDu.ts b/web/src/engine/websites/COMICMeDu.ts index 9ef6b424c2..df88bfc329 100644 --- a/web/src/engine/websites/COMICMeDu.ts +++ b/web/src/engine/websites/COMICMeDu.ts @@ -9,7 +9,6 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index f1d8c8af1b..538ea864f5 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -9,7 +9,6 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/MangaBANG.ts b/web/src/engine/websites/MangaBANG.ts index 7d4dd9f123..4756419a6e 100644 --- a/web/src/engine/websites/MangaBANG.ts +++ b/web/src/engine/websites/MangaBANG.ts @@ -9,7 +9,6 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/YoungAnimal.ts b/web/src/engine/websites/YoungAnimal.ts index 826fa1fd13..b4d5ba1372 100644 --- a/web/src/engine/websites/YoungAnimal.ts +++ b/web/src/engine/websites/YoungAnimal.ts @@ -9,9 +9,7 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { - public constructor() { super('younganimal', `Young Animal`, 'https://younganimal.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); } diff --git a/web/src/engine/websites/YoungChampion.ts b/web/src/engine/websites/YoungChampion.ts index 09897ea486..c2475f074f 100644 --- a/web/src/engine/websites/YoungChampion.ts +++ b/web/src/engine/websites/YoungChampion.ts @@ -9,9 +9,7 @@ import * as Comici from './decorators/ComiciViewer'; @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() - export default class extends DecoratableMangaScraper { - public constructor() { super('youngchampion', `Young Champion`, 'https://youngchampion.jp', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); } From 76526d682e63c8df3b324c72c54bb89566cc571d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Apr 2024 10:22:05 +0200 Subject: [PATCH 11/28] MangaCross > ChampionCross --- .../engine/transformers/BookmarkConverter.ts | 1 + .../transformers/BookmarkConverter_test.ts | 3 +- web/src/engine/websites/ChampionCross.ts | 20 ++++ .../{MangaCross.webp => ChampionCross.webp} | Bin ...MangaCross_e2e.ts => ChampionCross_e2e.ts} | 18 ++-- web/src/engine/websites/MangaCross.ts | 86 ------------------ web/src/engine/websites/_index.ts | 2 +- 7 files changed, 33 insertions(+), 97 deletions(-) create mode 100644 web/src/engine/websites/ChampionCross.ts rename web/src/engine/websites/{MangaCross.webp => ChampionCross.webp} (100%) rename web/src/engine/websites/{MangaCross_e2e.ts => ChampionCross_e2e.ts} (53%) delete mode 100644 web/src/engine/websites/MangaCross.ts diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index 2c2e441e13..9354ec3870 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -26,6 +26,7 @@ const legacyWebsiteIdentifierMap = { 'kumascans': 'retsu', 'lovehug': 'welovemanga', 'lyrascans': 'quantumscans', //https://www.mangaupdates.com/groups.html?id=35005683580 'Formerly known as LyraScans' + 'mangacross': 'championcross', 'mangamx': 'mangaoni', 'manganel': 'manganato', 'manganelos': 'mangapure', diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index 4bb0dd4732..91ca7a8e71 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -64,7 +64,7 @@ describe('BookmarkConverter', () => { { sourceID: 'azoramanga', targetID: 'azoraworld' }, { sourceID: 'bacamangaorg', targetID: 'bacamanga' }, { sourceID: 'bananascan', targetID: 'harmonyscan' }, - { sourceID: 'blogtruyen', targetID: 'blogtruyenmoi'}, + { sourceID: 'blogtruyen', targetID: 'blogtruyenmoi' }, { sourceID: 'comicbushi', targetID: 'comicgrowl' }, { sourceID: 'comicwalker', targetID: 'kadocomi' }, { sourceID: 'crazyscans', targetID: 'mangacultivator' }, @@ -81,6 +81,7 @@ describe('BookmarkConverter', () => { { sourceID: 'imperioscans', targetID: 'neroxus' }, { sourceID: 'lovehug', targetID: 'welovemanga' }, { sourceID: 'lyrascans', targetID: 'quantumscans' }, + { sourceID: 'mangacross', targetID: 'championcross' }, { sourceID: 'mangamx', targetID: 'mangaoni' }, { sourceID: 'manganel', targetID: 'manganato' }, { sourceID: 'manganelos', targetID: 'mangapure' }, diff --git a/web/src/engine/websites/ChampionCross.ts b/web/src/engine/websites/ChampionCross.ts new file mode 100644 index 0000000000..5cf99e6e11 --- /dev/null +++ b/web/src/engine/websites/ChampionCross.ts @@ -0,0 +1,20 @@ +import { Tags } from '../Tags'; +import icon from './ChampionCross.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, 'div.article-text > a', 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() +export default class extends DecoratableMangaScraper { + public constructor() { + super('championcross', `Champion Cross`, 'https://championcross.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/MangaCross.webp b/web/src/engine/websites/ChampionCross.webp similarity index 100% rename from web/src/engine/websites/MangaCross.webp rename to web/src/engine/websites/ChampionCross.webp diff --git a/web/src/engine/websites/MangaCross_e2e.ts b/web/src/engine/websites/ChampionCross_e2e.ts similarity index 53% rename from web/src/engine/websites/MangaCross_e2e.ts rename to web/src/engine/websites/ChampionCross_e2e.ts index 6e9158046b..0eb839bedd 100644 --- a/web/src/engine/websites/MangaCross_e2e.ts +++ b/web/src/engine/websites/ChampionCross_e2e.ts @@ -2,22 +2,22 @@ const config: Config = { plugin: { - id: 'mangacross', - title: 'MangaCross' + id: 'championcross', + title: 'Champion Cross' }, container: { - url: 'https://mangacross.jp/comics/watamaho/', - id: 'watamaho', - title: 'あの頃、私たちは魔法使いでした。' + url: 'https://championcross.jp/series/50d8ea89cfc92/', + id: '/series/50d8ea89cfc92/', + title: 'あの頃、私たちは魔法使いでした。 1' }, child: { - id: '/comics/watamaho/1', - title: '第1話 「桜が舞った日のこと」' + id: '/episodes/13d4bf3743424', + title: '第1話 「桜が舞った日のこと」' }, entry: { index: 0, - size: 897_673, - type: 'image/jpeg' + size: 2_691_707, + type: 'image/png' } }; diff --git a/web/src/engine/websites/MangaCross.ts b/web/src/engine/websites/MangaCross.ts deleted file mode 100644 index 9470ace487..0000000000 --- a/web/src/engine/websites/MangaCross.ts +++ /dev/null @@ -1,86 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './MangaCross.webp'; -import { Chapter, DecoratableMangaScraper, Manga, Page, type MangaPlugin } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import { FetchJSON } from '../platform/FetchProvider'; - -type APIMangas = { - comics: APIManga[] -} - -type APIManga = { - dir_name: string, - title: string, -} - -type APIChapters = { - comic: { - title : string, - episodes: APIChapter[] - } -} - -type APIChapter = { - id: number, - volume: string, - title: string, - status: string - page_url: string, -} - -type APIPages = { - episode_pages: { - image: { - pc_url : string - } - }[] -} - -@Common.ImageAjax(true) -export default class extends DecoratableMangaScraper { - - public constructor() { - super('mangacross', `MangaCross`, 'https://mangacross.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); - } - - public override get Icon() { - return icon; - } - - public override ValidateMangaURL(url: string): boolean { - return new RegExp(`^${this.URI.origin}/comics/[^/]+/$`).test(url); - } - - public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const id = new URL(url).pathname.match(/comics\/([^/]+)\//)[1]; - const uri = new URL(`/api/comics/${id}.json`, this.URI); - const request = new Request(uri.href); - const data = await FetchJSON(request); - return new Manga(this, provider, id, data.comic.title); - } - - public override async FetchMangas(provider: MangaPlugin): Promise { - const uri = new URL('/api/comics.json', this.URI); - const request = new Request(uri.href); - const data = await FetchJSON(request); - return data.comics.map(comic => new Manga(this, provider, comic.dir_name, comic.title.trim())); - } - - public override async FetchChapters(manga: Manga): Promise { - const uri = new URL(`/api/comics/${manga.Identifier}.json`, this.URI); - const request = new Request(uri.href); - const data = await FetchJSON(request); - return data.comic.episodes.map(episode => { - let title = episode.volume + ' '; - title += episode.title ? episode.title : ''; - return new Chapter(this, manga, episode.page_url, title.trim()); - }); - } - - public override async FetchPages(chapter: Chapter): Promise { - const uri = new URL(`${chapter.Identifier}/viewer.json`, this.URI); - const request = new Request(uri.href); - const data = await FetchJSON(request); - return data.episode_pages.map(page => new Page(this, chapter, new URL(page.image.pc_url))); - } -} \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 6304870cb5..5da3606d9f 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -50,6 +50,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CloverManga } from './CloverManga'; export { default as Cocorip } from './Cocorip'; @@ -295,7 +296,6 @@ export { default as MangaChill } from './MangaChill'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaCultivator } from './MangaCultivator'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDenizi } from './MangaDenizi'; From 60c5d3f6303032546b8c5518e47132d5b1250deb Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 23 Apr 2024 10:33:21 +0200 Subject: [PATCH 12/28] update cross logo --- web/src/engine/websites/ChampionCross.webp | Bin 2246 -> 392 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/web/src/engine/websites/ChampionCross.webp b/web/src/engine/websites/ChampionCross.webp index 0a9498cb9069286df7e4d74c5ec60b5ab0080ecb..d0ba5e188096d0e40148e3f27d172314aaa48e4c 100644 GIT binary patch literal 392 zcmV;30eAjVNk&G10RRA3MM6+kP&goT0RRAS2>_h|DnI~006v96p-`nGqav^r2>_rF zfB`N8i~pi$N`v+T;XRs?wp9BsPI(Wx6m>WSXieJU?L+mXjH&5SGwVBxVs^ZH!?fVD zer2}MnybJ7{`p!{y2@+dSP7TV^okwdXI$L{#bJ2yyRpgL{}90cIY=Gdo13ZAjy9}A z2^|N8)1Uw6Ki#!|5N`~zh(G#~|FbAx{fz%>p?^R1)OtG%<9~uj-|z90+}}t%*tTzr zV%^W}84p2To^SOkej~n0qqlaYbU)f|@J@f0&!vz51HBo}{Q6oe{ww}1$6crXfA{c` zs?>Ukzixl%NYc;l1^;6`sVK-6oEQQYnMh7_A$@{5@15JZ#ZXes%o>#GyAVy=_v+Mx zzK_`+#x&2M<@5Y=D7xuWA?dHW-~&Smna)yb>CwM-d&X002H7t@Za!tX*Bk7$(5zyJV-pUdq4 literal 2246 zcmV;%2s!ssNk&G#2mkCiUbpMmdLY|Dbw~caaM;_9(s(^a`M+$KCD`RBB`~lG_wVszvP52OhJ))X7- zLh>_D0l0k*`u%%TVVnqRYB)e8M4yi$S9a7y0I4KObaG^{BaB<68R?P+Q4W!ZBe1nQ z;b5$e>lhvRZkQQQYFd_KiUOVkk^=u3hVaDWx;h!2V*yX8;F7lz-4o>4&S1Dm9Oe0n3X~Sp}R7k*|&unK$Y35vO@Z zbO5;0S&VCd(f$x4XO;>g&knALUUPFk37m)(<3XS=A0oef^scz5ozviS^Z@L=OcA5A zfenP+(Eeg6+kF%PIE^t+{BU_x(V~(U!wtd0i8n|0ou!e{Oww0DsSD zc_xE-8zKE%3~0Y-$5Tr883ivx;PpEqwE@0n1rz1d9gr*9x~me(o_{IU<}FOhAhF)f zK2$hlqXGO>#`ML&%<^@c2!7`sz4;)C-rx8zAxdCxBx$%gNj!3{-qf9gxeWw&>JzIG z_a}l`tmxG}D8cEz#&j_U*NhLrtR;U&JX0IYiTvS;re+Sn6IG_#b^CdOu=c{kK5;7; zac@{tHx-aCmY5n=?>0z-fO)4qd;(g4YmX|iw*Uk|=O1@b<>8I12^_pr&jIS$D#&HXt@?lbsvYXF4O@~c_4?!FqZ z^YXxu$-dcv^{DPmz=bx0oK+uS-(if)s=)GT88f-Ffpwax6G8s1Oz1@O97X#p%!1I3 zX^)PXs971Heht`tgw3PCI&eXW^iYGb{j>vLM;Y3q1m&!{Enl=b3)y%v}%SsM=ne&n(c;(&Qb2)JqVEM z*%&EWq$G^ntbG3GE=77NivGk%2=}E?rRnY+r}>J$O32a=P{+Nx@rc0sng~MuDxCW{>XVC_q(3YT)1`N4>a!(T=tObXogAx4>E5aAW%n! zw~A?RDgONj7Q^AFCLhQjy_kgMa~qsMe(wn~NvZg` zWU6}rme3op<>E$kT{rmYc5hSzKqPHD2J9zHOY!|ZsoUr)EQ*Djs2l0E3 z1EWWl#0cuO!)U)$^6CB|fc%lNx*Y&kP&gpU0ssJz5dfV5DnI~006x)NrA??MKcXlb z{HyR932bT3OI{&^m)3tGIny_@zkaOyIc0K_CHj9 zfFIO9#(KbixAqMEr1lQ}0saHiANFV9r}q=mOfNSZ)nRv)?dWG*tGBcmtr~D#*mm=% z>RwNcN`&q>?amgDMT(oP=Vu2-gqp5^0NnA+OVu{uFr)|!S?Q7w{;_O^UHi;iA(wvk zor79oCGzS;*zM&_R0Y>)^nwf*Cv`L9JKev2It>2%X)Dc^?+g z)g|5+@0`>qO0ZKb=t0Ur`kQiJ{PlkQoTXuaps7Fm-M(S3LNpQjlM?-6C?fRi|H_2* zFC%zij6er6BO$F?R+Z{+u%ka`x`I{P_FwD`Liw?~&N>l#68nkO(cFGJ%vfP1*^i9K z`Gx)}&o=+U5!B)*FfauTS7PVl;%hx_gGPestfQhY6>o%no)wY%*K#lbB&bR_M1&LI ze?Q}@<5BabJjpPIUM&>V?JOt>!g>L9s8RoA8gO~P<-mD>F6t5)QXq+Zy;aR~fbr5sxE+D4tRCNSBjM9`}INpb9$4deW z#KdW$29Ki3m-G==+2;wgB7E&XBMuKQnD6n`-_(cBu@+nN!G%~ye2+56{tek=6dwmAMz|Z~vK?Gb4?2dYCe!}rwva1pIU5E7CU!So#j!zTAy74M<#8jI6ngh34 UawC92^lD|w16(w#(fmjV0Ps^$I{*Lx From 60e4002d7c4cb70bde6f27040ad34d16ebcd6afb Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Apr 2024 13:27:50 +0200 Subject: [PATCH 13/28] fix case --- web/src/engine/websites/decorators/ComiciViewer.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 12f093ed7b..e71b29d075 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -112,7 +112,7 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap const [viewer] = await FetchCSS(request, '#comici-viewer'); if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); - const coord = await fetchCoordInfo(this, viewer); + const coord = await FetchCoordInfo(this, viewer); return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } @@ -131,7 +131,7 @@ export function PagesSinglePageAJAX() { }; } -async function fetchCoordInfo(scraper: MangaScraper, viewer: HTMLElement): Promise> { +async function FetchCoordInfo(scraper: MangaScraper, viewer: HTMLElement): Promise> { //first request get page count let uri = new URL('/book/contentsInfo', scraper.URI); let params = new URLSearchParams({ @@ -186,7 +186,7 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si const data = await Common.FetchImageAjax.call(this, page, priority, signal, detectMimeType); return !page.Parameters?.scramble ? data : DeScramble(data, async (image, ctx) => { - const decodedArray = decodeScrambleArray(page.Parameters.scramble as string); + const decodedArray = DecodeScrambleArray(page.Parameters.scramble as string); const tileWidth = Math.floor(image.width / 4); const tileHeight = Math.floor(image.height / 4); for (let k = 0, i = 0; i < 4; i++) { @@ -215,7 +215,7 @@ export function ImageAjax(detectMimeType = false) { }; } -function decodeScrambleArray(scramble: string): number[][] { +function DecodeScrambleArray(scramble: string): number[][] { const decoded : number[][]= []; const encoded = scramble.replace(/\s+/g, '').slice(1).slice(0, -1).split(','); for (let i = 0; i < defaultOrder.length; i++) { From a69a9155f12b5a1e3574311f4a6231f7a4d0e6e5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 7 May 2024 11:51:55 +0200 Subject: [PATCH 14/28] update tests to use vitest --- web/src/engine/websites/BigComics_e2e.ts | 5 +++-- web/src/engine/websites/COMICMeDu_e2e.ts | 5 +++-- web/src/engine/websites/ChampionCross_e2e.ts | 5 +++-- web/src/engine/websites/ComicRide_e2e.ts | 5 +++-- web/src/engine/websites/MangaBANG_e2e.ts | 5 +++-- web/src/engine/websites/YoungAnimal_e2e.ts | 5 +++-- web/src/engine/websites/YoungChampion_e2e.ts | 5 +++-- 7 files changed, 21 insertions(+), 14 deletions(-) diff --git a/web/src/engine/websites/BigComics_e2e.ts b/web/src/engine/websites/BigComics_e2e.ts index 140bd04fef..9edf9ac70d 100644 --- a/web/src/engine/websites/BigComics_e2e.ts +++ b/web/src/engine/websites/BigComics_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/COMICMeDu_e2e.ts b/web/src/engine/websites/COMICMeDu_e2e.ts index badd19efac..537bf6cdc6 100644 --- a/web/src/engine/websites/COMICMeDu_e2e.ts +++ b/web/src/engine/websites/COMICMeDu_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/ChampionCross_e2e.ts b/web/src/engine/websites/ChampionCross_e2e.ts index 0eb839bedd..eaa3aeca7b 100644 --- a/web/src/engine/websites/ChampionCross_e2e.ts +++ b/web/src/engine/websites/ChampionCross_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture, type Config } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { plugin: { @@ -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/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index e5573e63b1..7474db7004 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_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/MangaBANG_e2e.ts b/web/src/engine/websites/MangaBANG_e2e.ts index 57405b9204..6ae92e07c0 100644 --- a/web/src/engine/websites/MangaBANG_e2e.ts +++ b/web/src/engine/websites/MangaBANG_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/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts index 81916f2ef1..c51d9a5862 100644 --- a/web/src/engine/websites/YoungAnimal_e2e.ts +++ b/web/src/engine/websites/YoungAnimal_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/YoungChampion_e2e.ts b/web/src/engine/websites/YoungChampion_e2e.ts index a83ad6dd4c..4f3120cd3e 100644 --- a/web/src/engine/websites/YoungChampion_e2e.ts +++ b/web/src/engine/websites/YoungChampion_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 From cf0a0804afb942198c3728587798316204e77a60 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 18 May 2024 13:28:19 +0200 Subject: [PATCH 15/28] Update _index.ts --- web/src/engine/websites/_index.ts | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 0aeb6002e2..cc3b412738 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -42,6 +42,7 @@ export { default as BakaMan } from './BakaMan'; export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BestManhua } from './BestManhua'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; @@ -53,6 +54,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CloverManga } from './CloverManga'; export { default as Cocorip } from './Cocorip'; @@ -69,8 +71,10 @@ export { default as ComicFX } from './ComicFX'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -295,6 +299,7 @@ export { default as Manga1001top } from './Manga1001top'; export { default as MangaAction } from './MangaAction'; export { default as MangaArab } from './MangaArab'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabaz } from './Mangabaz'; export { default as MangaBob } from './MangaBob'; @@ -307,7 +312,6 @@ export { default as MangaChill } from './MangaChill'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDenizi } from './MangaDenizi'; export { default as MangaDex } from './MangaDex'; @@ -728,6 +732,8 @@ export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -756,7 +762,6 @@ export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From 8ae83deae0f2c6781c9d0f5919cbbdb7a735cfe3 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 22 Jun 2024 21:43:24 +0200 Subject: [PATCH 16/28] code refactoring --- .../websites/decorators/ComiciViewer.ts | 45 ++++++------------- 1 file changed, 13 insertions(+), 32 deletions(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index e71b29d075..129b6de323 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -112,7 +112,7 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap const [viewer] = await FetchCSS(request, '#comici-viewer'); if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); - const coord = await FetchCoordInfo(this, viewer); + const coord = await FetchCoordInfo.call(this, viewer); return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } @@ -131,43 +131,24 @@ export function PagesSinglePageAJAX() { }; } -async function FetchCoordInfo(scraper: MangaScraper, viewer: HTMLElement): Promise> { - //first request get page count - let uri = new URL('/book/contentsInfo', scraper.URI); - let params = new URLSearchParams({ - 'comici-viewer-id': viewer.getAttribute('comici-viewer-id'), - 'user-id': viewer.dataset['memberJwt'], - 'page-from': '0', - 'page-to': '1', - }); +async function FetchCoordInfo(this: MangaScraper, viewer: HTMLElement): Promise> { - uri.search = params.toString(); - let request = new Request(uri, { - headers: { - Origin: scraper.URI.origin, - Referer: scraper.URI.origin - } - }); - const data = await FetchJSON < APIResult>(request); + //first request get page count + const viewerId = viewer.getAttribute('comici-viewer-id'); + const userId = viewer.dataset['memberJwt']; + const { totalPages } = await FetchJSON>(CreateRequest.call(this, '1', viewerId, userId)); //second request fetch actual pages data - const numbers = data.totalPages; - - uri = new URL('/book/contentsInfo', scraper.URI); - params = new URLSearchParams({ - 'comici-viewer-id': viewer.getAttribute('comici-viewer-id'), - 'user-id': viewer.dataset['memberJwt'], - 'page-from': '0', - 'page-to': numbers.toString() - }); - uri.search = params.toString(); - request = new Request(uri, { + return FetchJSON>(CreateRequest.call(this, totalPages.toString(), viewerId, userId)); +} + +function CreateRequest(this: MangaScraper, pageTo: string, viewerId: string, userId: string): Request { + return new Request(new URL(`/book/contentsInfo?comici-viewer-id=${viewerId}&user-id=${userId}&page-from=0&page-to=${pageTo}`, this.URI), { headers: { - Origin: scraper.URI.origin, - Referer: scraper.URI.origin + Origin: this.URI.origin, + Referer: this.URI.origin } }); - return FetchJSON>(request); } /*********************************************** From 789111e08c02a5a8a4c58c492a819cfc284b8534 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 22 Jun 2024 21:44:11 +0200 Subject: [PATCH 17/28] fix tests --- web/src/engine/websites/BigComics_e2e.ts | 2 +- web/src/engine/websites/COMICMeDu_e2e.ts | 2 +- web/src/engine/websites/ChampionCross_e2e.ts | 4 ++-- web/src/engine/websites/ComicRide_e2e.ts | 2 +- web/src/engine/websites/MagKan_e2e.ts | 6 +++--- web/src/engine/websites/MangaBANG_e2e.ts | 2 +- web/src/engine/websites/YoungAnimal_e2e.ts | 2 +- web/src/engine/websites/YoungChampion_e2e.ts | 2 +- 8 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web/src/engine/websites/BigComics_e2e.ts b/web/src/engine/websites/BigComics_e2e.ts index 9edf9ac70d..32df919327 100644 --- a/web/src/engine/websites/BigComics_e2e.ts +++ b/web/src/engine/websites/BigComics_e2e.ts @@ -12,7 +12,7 @@ const config = { title: '岳' }, child: { - id: '/episodes/4b87f55986ccc', + id: '/episodes/4b87f55986ccc/', title: '1巻-第0歩 お家' }, entry: { diff --git a/web/src/engine/websites/COMICMeDu_e2e.ts b/web/src/engine/websites/COMICMeDu_e2e.ts index 537bf6cdc6..4783f5b61d 100644 --- a/web/src/engine/websites/COMICMeDu_e2e.ts +++ b/web/src/engine/websites/COMICMeDu_e2e.ts @@ -12,7 +12,7 @@ const config = { title: 'ぱらのいあけ〜じ' }, child: { - id: '/episodes/beaa305e9cf32', + id: '/episodes/beaa305e9cf32/', title: 'その(1)' }, entry: { diff --git a/web/src/engine/websites/ChampionCross_e2e.ts b/web/src/engine/websites/ChampionCross_e2e.ts index eaa3aeca7b..7949cf0aec 100644 --- a/web/src/engine/websites/ChampionCross_e2e.ts +++ b/web/src/engine/websites/ChampionCross_e2e.ts @@ -9,10 +9,10 @@ const config: Config = { container: { url: 'https://championcross.jp/series/50d8ea89cfc92/', id: '/series/50d8ea89cfc92/', - title: 'あの頃、私たちは魔法使いでした。 1' + title: 'あの頃、私たちは魔法使いでした。' }, child: { - id: '/episodes/13d4bf3743424', + id: '/episodes/13d4bf3743424/', title: '第1話 「桜が舞った日のこと」' }, entry: { diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index 7474db7004..60fd8f83ef 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -12,7 +12,7 @@ const config = { title: '呪われ侯爵様の訳ありメイド' }, child: { - id: '/episodes/48d531d8140b5', + id: '/episodes/48d531d8140b5/', title: '第1話' }, entry: { diff --git a/web/src/engine/websites/MagKan_e2e.ts b/web/src/engine/websites/MagKan_e2e.ts index 2b74bdd94c..005a7743e4 100644 --- a/web/src/engine/websites/MagKan_e2e.ts +++ b/web/src/engine/websites/MagKan_e2e.ts @@ -12,12 +12,12 @@ const config = { title: '推し変しやがれ!!' }, child: { - id: '/episodes/90451498292e5', - title: '第七話【前】' + id: '/episodes/93e16b054f108/', + title: '第零話' }, entry: { index: 1, - size: 1_235_068, + size: 3_166_820, type: 'image/png' } }; diff --git a/web/src/engine/websites/MangaBANG_e2e.ts b/web/src/engine/websites/MangaBANG_e2e.ts index 6ae92e07c0..770fab5104 100644 --- a/web/src/engine/websites/MangaBANG_e2e.ts +++ b/web/src/engine/websites/MangaBANG_e2e.ts @@ -12,7 +12,7 @@ const config = { title: '藤崎くんちのお母さんには秘密がある' }, child: { - id: '/episodes/fff51cc22815e', + id: '/episodes/fff51cc22815e/', title: '藤崎くんちのお母さん (1)' }, entry: { diff --git a/web/src/engine/websites/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts index c51d9a5862..b3e730d222 100644 --- a/web/src/engine/websites/YoungAnimal_e2e.ts +++ b/web/src/engine/websites/YoungAnimal_e2e.ts @@ -12,7 +12,7 @@ const config = { title: '拷問バイトくんの日常' }, child: { - id: '/episodes/c44e40bd07ed7', + id: '/episodes/c44e40bd07ed7/', title: '第1話' }, entry: { diff --git a/web/src/engine/websites/YoungChampion_e2e.ts b/web/src/engine/websites/YoungChampion_e2e.ts index 4f3120cd3e..17d514689c 100644 --- a/web/src/engine/websites/YoungChampion_e2e.ts +++ b/web/src/engine/websites/YoungChampion_e2e.ts @@ -12,7 +12,7 @@ const config = { title: '惨家' }, child: { - id: '/episodes/2aa2386bccbcd', + id: '/episodes/71edbfc76e327/', title: '第1話' }, entry: { From 3167068a07bee0fbbba4bbe4d148b21b321850db Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 25 Jun 2024 10:26:44 +0200 Subject: [PATCH 18/28] Comici : use chapter url to fetch pages --- web/src/engine/websites/decorators/ComiciViewer.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 129b6de323..65a327b7b6 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -112,7 +112,7 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap const [viewer] = await FetchCSS(request, '#comici-viewer'); if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); - const coord = await FetchCoordInfo.call(this, viewer); + const coord = await FetchCoordInfo.call(this, viewer, chapter); return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } @@ -131,22 +131,22 @@ export function PagesSinglePageAJAX() { }; } -async function FetchCoordInfo(this: MangaScraper, viewer: HTMLElement): Promise> { +async function FetchCoordInfo(this: MangaScraper, viewer: HTMLElement, chapter : Chapter): Promise> { //first request get page count const viewerId = viewer.getAttribute('comici-viewer-id'); const userId = viewer.dataset['memberJwt']; - const { totalPages } = await FetchJSON>(CreateRequest.call(this, '1', viewerId, userId)); + const { totalPages } = await FetchJSON>(CreateRequest.call(this, '1', viewerId, userId, chapter)); //second request fetch actual pages data - return FetchJSON>(CreateRequest.call(this, totalPages.toString(), viewerId, userId)); + return FetchJSON>(CreateRequest.call(this, totalPages.toString(), viewerId, userId, chapter)); } -function CreateRequest(this: MangaScraper, pageTo: string, viewerId: string, userId: string): Request { +function CreateRequest(this: MangaScraper, pageTo: string, viewerId: string, userId: string, chapter): Request { return new Request(new URL(`/book/contentsInfo?comici-viewer-id=${viewerId}&user-id=${userId}&page-from=0&page-to=${pageTo}`, this.URI), { headers: { Origin: this.URI.origin, - Referer: this.URI.origin + Referer: new URL(chapter.id, this.URI).href } }); } From 5a8bb561f5ffa89ba5afe341f8e22d1b58a5ac99 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 25 Jun 2024 10:43:57 +0200 Subject: [PATCH 19/28] Add RimacomiPlus https://github.com/manga-download/hakuneko/issues/7212 --- web/src/engine/websites/RimacomiPlus.ts | 21 ++++++++++++++++ web/src/engine/websites/RimacomiPlus.webp | Bin 0 -> 600 bytes web/src/engine/websites/RimacomiPlus_e2e.ts | 26 ++++++++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 48 insertions(+) create mode 100644 web/src/engine/websites/RimacomiPlus.ts create mode 100644 web/src/engine/websites/RimacomiPlus.webp create mode 100644 web/src/engine/websites/RimacomiPlus_e2e.ts diff --git a/web/src/engine/websites/RimacomiPlus.ts b/web/src/engine/websites/RimacomiPlus.ts new file mode 100644 index 0000000000..5bcaefd35a --- /dev/null +++ b/web/src/engine/websites/RimacomiPlus.ts @@ -0,0 +1,21 @@ +import { Tags } from '../Tags'; +import icon from './RimacomiPlus.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as Comici from './decorators/ComiciViewer'; + +@Common.MangaCSS(/^{origin}\/([^/]+\/)?series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) +@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Comici.ChaptersSinglePageCSS() +@Comici.PagesSinglePageAJAX() +@Comici.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('rimacomiplus', `RimacomiPlus (リマコミ+)`, 'https://rimacomiplus.jp', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/RimacomiPlus.webp b/web/src/engine/websites/RimacomiPlus.webp new file mode 100644 index 0000000000000000000000000000000000000000..e1f1fcc40c0c514f517bf5e40837131d8d7cd894 GIT binary patch literal 600 zcmV-e0;l~_Nk&Fc0ssJ4MM6+kP&gn&0ssKe4*;D3DnI~006v96p-`nHBO<%{OaPz| zfCDd3!jOKU;?FK_a2_ZfAUwcy7W4rBEz|+%0p+vomixTGI~7fRS)KX@PpvvJn<|~d@m?^lffIxC|;jW6` zcIRv00002~`AC1Rk=$18&;I%g|6>*RfBn|H+IF#g{2_M;`dilhxf5-$hg4Be+c*_9 z9R&ZZuU=rX?Mfh2odQ|EJKai#+TV_!My}t=i}%Tb)?cFK6fICCkZUPB1&Ffiuok_u z&lbXZw@}#E@3a3`7oCtJmLR~ytV>L?PT+iYboXi#S~Lii05b_oo_VGWxpeVc5Tw?z z^3EvvBHydU^r03H)*)izX%!e*xzl(UbhIo)0*iy$1zc`xMcXIrb7S+9@P$0J zg?deN7el2%k@|5@w5;lgg^BDMNIzO%aB2=$`h_0*wfXyElD6mY#Jd~i$}o>fp}JFl zKk}Z?KHL$|iyl{FeG9U7lI@%Dg=c5GU%Q^JP0E-4Ke_UNj@Pd8yt}2!7R-y9U0|+s m{R5MxR44EhDTK;K$!$XF2>puvQ}YmJkK#M_8h%sK!vFvU7cZ>< literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/RimacomiPlus_e2e.ts b/web/src/engine/websites/RimacomiPlus_e2e.ts new file mode 100644 index 0000000000..303fb13032 --- /dev/null +++ b/web/src/engine/websites/RimacomiPlus_e2e.ts @@ -0,0 +1,26 @@ +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'rimacomiplus', + title: 'RimacomiPlus (リマコミ+)' + }, + container: { + url: 'https://rimacomiplus.jp/cocohana/series/853b5f1c905d4/', + id: '/cocohana/series/853b5f1c905d4/', + title: '包帯ごっこ' + }, + child: { + id: '/cocohana/episodes/7cba174d95a20/', + title: '第1話' + }, + entry: { + index: 0, + size: 3_686_629, + 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 7251358e2a..0de5ca3f6c 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -583,6 +583,7 @@ export { default as Remangas } from './Remangas'; export { default as ResetScans } from './ResetScans'; export { default as Retsu } from './Retsu'; export { default as RidiBooks } from './RidiBooks'; +export { default as RimacomiPlus } from './RimacomiPlus'; export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; export { default as RobinManga } from './RobinManga'; From ef767c17bc9ebb85e6cd3c92d0bf1e429e0fcb20 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 25 Jun 2024 11:20:47 +0200 Subject: [PATCH 20/28] Youngchampion: fix mangalist --- web/src/engine/websites/YoungChampion.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/YoungChampion.ts b/web/src/engine/websites/YoungChampion.ts index c2475f074f..797dec2f26 100644 --- a/web/src/engine/websites/YoungChampion.ts +++ b/web/src/engine/websites/YoungChampion.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as Comici from './decorators/ComiciViewer'; @Common.MangaCSS(/^{origin}\/series\/[^/]+(\/)?$/, Comici.queryMangaTitleURI) -@Common.MangasMultiPageCSS(Comici.mangaListPath, Comici.queryManga, 0, 1, 0, Comici.MangaExtractor) +@Common.MangasMultiPageCSS(Comici.mangaListPath, 'div.series-box-vertical div.article-text > a', 0, 1, 0, Comici.MangaExtractor) @Comici.ChaptersSinglePageCSS() @Comici.PagesSinglePageAJAX() @Comici.ImageAjax() From 313bb0aa05b4f7d3251aa3b497b794495e9fb775 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 14 Aug 2024 15:10:02 +0200 Subject: [PATCH 21/28] update bookmarkconverter --- web/src/engine/transformers/BookmarkConverter.ts | 1 + web/src/engine/transformers/BookmarkConverter_test.ts | 1 + 2 files changed, 2 insertions(+) diff --git a/web/src/engine/transformers/BookmarkConverter.ts b/web/src/engine/transformers/BookmarkConverter.ts index 87343694a8..450a275a80 100644 --- a/web/src/engine/transformers/BookmarkConverter.ts +++ b/web/src/engine/transformers/BookmarkConverter.ts @@ -30,6 +30,7 @@ export const legacyWebsiteIdentifierMap = new Map([ [ 'komikav', 'apkomik' ], [ 'kumascans', 'retsu' ], [ 'lyrascans', 'quantumscans' ], + [ 'mangacross', 'championcross' ], [ 'mangamx', 'mangaoni' ], [ 'manganel', 'manganato' ], [ 'mangaproz', 'mangapro' ], diff --git a/web/src/engine/transformers/BookmarkConverter_test.ts b/web/src/engine/transformers/BookmarkConverter_test.ts index 989ca3fecd..4be61e15aa 100644 --- a/web/src/engine/transformers/BookmarkConverter_test.ts +++ b/web/src/engine/transformers/BookmarkConverter_test.ts @@ -32,6 +32,7 @@ const legacyWebsiteIdentifierMapTestCases = [ { sourceID: 'komikav', targetID: 'apkomik' }, { sourceID: 'kumascans', targetID: 'retsu' }, { sourceID: 'lyrascans', targetID: 'quantumscans' }, + { sourceID: 'mangacross', targetID: 'championcross'}, { sourceID: 'mangamx', targetID: 'mangaoni' }, { sourceID: 'manganel', targetID: 'manganato' }, { sourceID: 'mangaproz', targetID: 'mangapro' }, From 8e5cda9b0944dc32e9f639932b55218870f26fdc Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 14 Aug 2024 15:18:44 +0200 Subject: [PATCH 22/28] Update _index.ts --- web/src/engine/websites/_index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d2870126a8..7260fb2762 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -40,6 +40,7 @@ export { default as Baozimh } from './Baozimh'; export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BestManhua } from './BestManhua'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; @@ -50,6 +51,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as CloverManga } from './CloverManga'; @@ -68,8 +70,10 @@ export { default as ComicFuz } from './ComicFuz'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -291,6 +295,7 @@ export { default as Manga347 } from './Manga347'; export { default as MangaAction } from './MangaAction'; export { default as MangaArab } from './MangaArab'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as MangaBob } from './MangaBob'; export { default as Mangabox } from './Mangabox'; @@ -302,7 +307,6 @@ export { default as MangaChill } from './MangaChill'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDex } from './MangaDex'; export { default as MangaDig } from './MangaDig'; @@ -561,6 +565,7 @@ export { default as Remangas } from './Remangas'; export { default as ResetScans } from './ResetScans'; export { default as Retsu } from './Retsu'; export { default as RidiBooks } from './RidiBooks'; +export { default as RimacomiPlus } from './RimacomiPlus'; export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; export { default as RobinManga } from './RobinManga'; @@ -717,6 +722,8 @@ export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -740,7 +747,6 @@ export { default as BookLive } from './legacy/BookLive'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From 40a869b963d69a3ea110c6af987ea30c2039e36c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 9 Sep 2024 20:59:41 +0200 Subject: [PATCH 23/28] Update _index.ts --- web/src/engine/websites/_index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 080fb4ac3d..dd237c86d3 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -41,6 +41,7 @@ export { default as Baozimh } from './Baozimh'; export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BestManhua } from './BestManhua'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; @@ -50,6 +51,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as Cocorip } from './Cocorip'; @@ -67,8 +69,10 @@ export { default as ComicFuz } from './ComicFuz'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -288,6 +292,7 @@ export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; export { default as MangaAction } from './MangaAction'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabox } from './Mangabox'; export { default as MangaBTT } from './MangaBTT'; @@ -298,7 +303,6 @@ export { default as MangaChill } from './MangaChill'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDex } from './MangaDex'; export { default as MangaDig } from './MangaDig'; @@ -557,6 +561,7 @@ export { default as Remangas } from './Remangas'; export { default as ResetScans } from './ResetScans'; export { default as Retsu } from './Retsu'; export { default as RidiBooks } from './RidiBooks'; +export { default as RimacomiPlus } from './RimacomiPlus'; export { default as RimuScan } from './RimuScan'; export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; @@ -717,6 +722,8 @@ export { default as YaoiScan } from './YaoiScan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -737,7 +744,6 @@ export { default as BookLive } from './legacy/BookLive'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From 1364ee687ec7ec5f7e8b0033f6415bac2e950070 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 28 Sep 2024 13:36:44 +0200 Subject: [PATCH 24/28] use typed page --- web/src/engine/websites/decorators/ComiciViewer.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 65a327b7b6..9dd31dc53c 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -34,6 +34,10 @@ type APIPage = { scramble: string } +type ScrambleData = { + scramble: string +} + export function MangaExtractor(element: HTMLAnchorElement) { const titleElement = element.querySelector(queryMangaTitle); return { @@ -103,7 +107,7 @@ export function ChaptersSinglePageCSS(query: string = queryChapter, extract = Ch * @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 */ -export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chapter): Promise { +export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chapter): Promise[]> { const request = new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin @@ -113,7 +117,7 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); const coord = await FetchCoordInfo.call(this, viewer, chapter); - return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); + return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } /** @@ -163,11 +167,11 @@ function CreateRequest(this: MangaScraper, pageTo: string, viewerId: string, use * @param signal - An abort signal that can be used to cancel the request for the image data * @param detectMimeType - Force a fingerprint check of the image data to detect its mime-type (instead of relying on the Content-Type header) */ -async function FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { +async function FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { const data = await Common.FetchImageAjax.call(this, page, priority, signal, detectMimeType); return !page.Parameters?.scramble ? data : DeScramble(data, async (image, ctx) => { - const decodedArray = DecodeScrambleArray(page.Parameters.scramble as string); + const decodedArray = DecodeScrambleArray(page.Parameters.scramble); const tileWidth = Math.floor(image.width / 4); const tileHeight = Math.floor(image.height / 4); for (let k = 0, i = 0; i < 4; i++) { @@ -189,7 +193,7 @@ export function ImageAjax(detectMimeType = false) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { Common.ThrowOnUnsupportedDecoratorContext(context); return class extends ctor { - public async FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal): Promise { + public async FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal): Promise { return FetchImage.call(this, page, priority, signal, detectMimeType); } }; From 7cb8381c6c4f751fe159ed36df15a4831f4fc3ad Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 7 Oct 2024 11:41:04 +0200 Subject: [PATCH 25/28] Update _index.ts --- web/src/engine/websites/_index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 933f4b9279..3036a65957 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -39,6 +39,7 @@ export { default as BacaKomik } from './BacaKomik'; export { default as BacaManga } from './BacaManga'; export { default as Baozimh } from './Baozimh'; export { default as Batoto } from './Batoto'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; @@ -49,6 +50,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as Cocorip } from './Cocorip'; @@ -66,8 +68,10 @@ export { default as ComicFuz } from './ComicFuz'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -285,6 +289,7 @@ export { default as Manga18FX } from './Manga18FX'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabox } from './Mangabox'; export { default as MangaBTT } from './MangaBTT'; @@ -294,7 +299,6 @@ export { default as MangaChan } from './MangaChan'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDex } from './MangaDex'; export { default as MangaDistrict } from './MangaDistrict'; @@ -551,6 +555,7 @@ export { default as Remangas } from './Remangas'; export { default as ResetScans } from './ResetScans'; export { default as Retsu } from './Retsu'; export { default as RidiBooks } from './RidiBooks'; +export { default as RimacomiPlus } from './RimacomiPlus'; export { default as RimuScan } from './RimuScan'; export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; @@ -714,6 +719,8 @@ export { default as YaoiScan } from './YaoiScan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -734,7 +741,6 @@ export { default as BookLive } from './legacy/BookLive'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From c058ea7cccdff6f63d8fe697080443e03143065b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 17 Oct 2024 10:03:16 +0200 Subject: [PATCH 26/28] Update _index.ts --- web/src/engine/websites/_index.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d00f54b587..118da3126b 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -39,6 +39,7 @@ export { default as BacaManga } from './BacaManga'; export { default as Baozimh } from './Baozimh'; export { default as BarManga } from './BarManga'; export { default as Batoto } from './Batoto'; +export { default as BigComics } from './BigComics'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; @@ -48,6 +49,7 @@ export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; +export { default as ChampionCross } from './ChampionCross'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as Cocorip } from './Cocorip'; @@ -65,8 +67,10 @@ export { default as ComicFuz } from './ComicFuz'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicGrowl } from './ComicGrowl'; export { default as ComicK } from './ComicK'; +export { default as COMICMeDu } from './COMICMeDu'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; @@ -287,6 +291,7 @@ export { default as Manga18FX } from './Manga18FX'; export { default as Manga168 } from './Manga168'; export { default as Manga347 } from './Manga347'; export { default as MangaAy } from './MangaAy'; +export { default as MangaBANG } from './MangaBANG'; export { default as MangaBat } from './MangaBat'; export { default as Mangabox } from './Mangabox'; export { default as MangaBTT } from './MangaBTT'; @@ -296,7 +301,6 @@ export { default as MangaChan } from './MangaChan'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; -export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDex } from './MangaDex'; export { default as MangaDistrict } from './MangaDistrict'; @@ -549,6 +553,7 @@ export { default as Remangas } from './Remangas'; export { default as ResetScans } from './ResetScans'; export { default as Retsu } from './Retsu'; export { default as RidiBooks } from './RidiBooks'; +export { default as RimacomiPlus } from './RimacomiPlus'; export { default as RimuScan } from './RimuScan'; export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; @@ -714,6 +719,8 @@ export { default as YaoiScan } from './YaoiScan'; export { default as YaoiTR } from './YaoiTR'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungAnimal } from './YoungAnimal'; +export { default as YoungChampion } from './YoungChampion'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -734,7 +741,6 @@ export { default as BookLive } from './legacy/BookLive'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicFire } from './legacy/ComicFire'; -export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicValkyrie } from './legacy/ComicValkyrie'; From fa65b3906afe1f6ae8a16e02bbf7a343aee8d510 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 27 Oct 2024 11:08:14 +0100 Subject: [PATCH 27/28] update tests --- web/src/engine/websites/BigComics_e2e.ts | 4 +--- web/src/engine/websites/COMICMeDu_e2e.ts | 4 +--- web/src/engine/websites/ChampionCross_e2e.ts | 4 +--- web/src/engine/websites/ComicRide_e2e.ts | 4 +--- web/src/engine/websites/MangaBANG_e2e.ts | 4 +--- web/src/engine/websites/RimacomiPlus_e2e.ts | 4 +--- web/src/engine/websites/YoungAnimal_e2e.ts | 4 +--- web/src/engine/websites/YoungChampion_e2e.ts | 4 +--- 8 files changed, 8 insertions(+), 24 deletions(-) diff --git a/web/src/engine/websites/BigComics_e2e.ts b/web/src/engine/websites/BigComics_e2e.ts index 32df919327..94c12a828e 100644 --- a/web/src/engine/websites/BigComics_e2e.ts +++ b/web/src/engine/websites/BigComics_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/COMICMeDu_e2e.ts b/web/src/engine/websites/COMICMeDu_e2e.ts index 4783f5b61d..6ae4bbba41 100644 --- a/web/src/engine/websites/COMICMeDu_e2e.ts +++ b/web/src/engine/websites/COMICMeDu_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/ChampionCross_e2e.ts b/web/src/engine/websites/ChampionCross_e2e.ts index 7949cf0aec..6b2e6b4726 100644 --- a/web/src/engine/websites/ChampionCross_e2e.ts +++ b/web/src/engine/websites/ChampionCross_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/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index 60fd8f83ef..cc93ff3c0b 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_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/MangaBANG_e2e.ts b/web/src/engine/websites/MangaBANG_e2e.ts index 770fab5104..3ecf36c4f4 100644 --- a/web/src/engine/websites/MangaBANG_e2e.ts +++ b/web/src/engine/websites/MangaBANG_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/RimacomiPlus_e2e.ts b/web/src/engine/websites/RimacomiPlus_e2e.ts index 303fb13032..6d4f9752ee 100644 --- a/web/src/engine/websites/RimacomiPlus_e2e.ts +++ b/web/src/engine/websites/RimacomiPlus_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/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts index b3e730d222..43ebd49ff8 100644 --- a/web/src/engine/websites/YoungAnimal_e2e.ts +++ b/web/src/engine/websites/YoungAnimal_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/YoungChampion_e2e.ts b/web/src/engine/websites/YoungChampion_e2e.ts index 17d514689c..3e58a4ebad 100644 --- a/web/src/engine/websites/YoungChampion_e2e.ts +++ b/web/src/engine/websites/YoungChampion_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 From 524c9b328cc68a27bef0c94b3bae5d6a217bc01e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 4 Nov 2024 13:47:08 +0100 Subject: [PATCH 28/28] use values instead of html element --- web/src/engine/websites/MagKan_e2e.ts | 2 +- web/src/engine/websites/YoungAnimal_e2e.ts | 2 +- web/src/engine/websites/decorators/ComiciViewer.ts | 10 +++++----- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/web/src/engine/websites/MagKan_e2e.ts b/web/src/engine/websites/MagKan_e2e.ts index 0bec25a3a2..efc1d1f086 100644 --- a/web/src/engine/websites/MagKan_e2e.ts +++ b/web/src/engine/websites/MagKan_e2e.ts @@ -11,7 +11,7 @@ const config = { title: '推し変しやがれ!!' }, child: { - id: '/episodes/93e16b054f108/', + id: '/episodes/a742481ce1e89/', title: '第零話' }, entry: { diff --git a/web/src/engine/websites/YoungAnimal_e2e.ts b/web/src/engine/websites/YoungAnimal_e2e.ts index 43ebd49ff8..052fc1a753 100644 --- a/web/src/engine/websites/YoungAnimal_e2e.ts +++ b/web/src/engine/websites/YoungAnimal_e2e.ts @@ -16,7 +16,7 @@ const config = { }, entry: { index: 0, - size: 933_886, + size: 955_211, type: 'image/png' } }; diff --git a/web/src/engine/websites/decorators/ComiciViewer.ts b/web/src/engine/websites/decorators/ComiciViewer.ts index 9dd31dc53c..9b6aae109a 100644 --- a/web/src/engine/websites/decorators/ComiciViewer.ts +++ b/web/src/engine/websites/decorators/ComiciViewer.ts @@ -116,7 +116,10 @@ export async function FetchPagesSinglePageAJAX(this: MangaScraper, chapter: Chap const [viewer] = await FetchCSS(request, '#comici-viewer'); if (!viewer) throw new Exception(R.Plugin_Common_Chapter_UnavailableError); - const coord = await FetchCoordInfo.call(this, viewer, chapter); + const viewerId = viewer.getAttribute('comici-viewer-id'); + const userId = viewer.dataset['memberJwt']; + + const coord = await FetchCoordInfo.call(this, viewerId, userId, chapter); return coord.result.map(image => new Page(this, chapter, new URL(image.imageUrl), { scramble: image.scramble, Referer: this.URI.origin })); } @@ -135,11 +138,8 @@ export function PagesSinglePageAJAX() { }; } -async function FetchCoordInfo(this: MangaScraper, viewer: HTMLElement, chapter : Chapter): Promise> { - +async function FetchCoordInfo(this: MangaScraper, viewerId: string, userId : string, chapter : Chapter): Promise> { //first request get page count - const viewerId = viewer.getAttribute('comici-viewer-id'); - const userId = viewer.dataset['memberJwt']; const { totalPages } = await FetchJSON>(CreateRequest.call(this, '1', viewerId, userId, chapter)); //second request fetch actual pages data