From 39508c60ea643a621189e118fe47ea96746647bc Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 15 Jul 2023 19:35:54 +0200 Subject: [PATCH 01/88] Add Speedbind Decorator and websites Carefully tested websites and unscrambling, everything seems good \o/ --- web/src/engine/websites/_index.ts | 3 + .../engine/websites/decorators/SpeedBind.ts | 827 ++++++++++++++++++ web/src/engine/websites/legacy/BookLive.ts | 20 +- web/src/engine/websites/legacy/Cmoa.ts | 48 + web/src/engine/websites/legacy/Cmoa.webp | Bin 0 -> 2830 bytes web/src/engine/websites/legacy/ComicBrise.ts | 70 +- web/src/engine/websites/legacy/ComicMeteor.ts | 123 +-- .../engine/websites/legacy/ComicValkyrie.ts | 86 +- .../engine/websites/legacy/ComicZerosum.ts | 85 +- .../engine/websites/legacy/DigitalMargaret.ts | 32 + .../websites/legacy/DigitalMargaret.webp | Bin 0 -> 436 bytes web/src/engine/websites/legacy/Futabanet.ts | 82 +- web/src/engine/websites/legacy/MangaPlanet.ts | 58 ++ .../engine/websites/legacy/MangaPlanet.webp | Bin 0 -> 3674 bytes web/src/engine/websites/legacy/Ohtabooks.ts | 133 +-- 15 files changed, 1167 insertions(+), 400 deletions(-) create mode 100644 web/src/engine/websites/decorators/SpeedBind.ts create mode 100644 web/src/engine/websites/legacy/Cmoa.ts create mode 100644 web/src/engine/websites/legacy/Cmoa.webp create mode 100644 web/src/engine/websites/legacy/DigitalMargaret.ts create mode 100644 web/src/engine/websites/legacy/DigitalMargaret.webp create mode 100644 web/src/engine/websites/legacy/MangaPlanet.ts create mode 100644 web/src/engine/websites/legacy/MangaPlanet.webp diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 278c3ae8f7..d9653dde8d 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -626,6 +626,7 @@ export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; export { default as CatManga } from './legacy/CatManga'; +export { default as Cmoa } from './legacy/Cmoa'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicAction } from './legacy/ComicAction'; export { default as ComicBoost } from './legacy/ComicBoost'; @@ -661,6 +662,7 @@ export { default as DaumWebtoon } from './legacy/DaumWebtoon'; export { default as Daysneo } from './legacy/Daysneo'; export { default as Delitoon } from './legacy/Delitoon'; export { default as DelitoonDE } from './legacy/DelitoonDE'; +export { default as DigitalMargaret } from './legacy/DigitalMargaret'; export { default as Dmzj } from './legacy/Dmzj'; export { default as DokiFansubs } from './legacy/DokiFansubs'; export { default as DongManManhua } from './legacy/DongManManhua'; @@ -828,6 +830,7 @@ export { default as MangaPanda } from './legacy/MangaPanda'; export { default as MangaPark } from './legacy/MangaPark'; export { default as MangaParkEN } from './legacy/MangaParkEN'; export { default as MangaParkToday } from './legacy/MangaParkToday'; +export { default as MangaPlanet } from './legacy/MangaPlanet'; export { default as MangaRaw } from './legacy/MangaRaw'; export { default as MangarawOnline } from './legacy/MangarawOnline'; export { default as MangaReader } from './legacy/MangaReader'; diff --git a/web/src/engine/websites/decorators/SpeedBind.ts b/web/src/engine/websites/decorators/SpeedBind.ts new file mode 100644 index 0000000000..d4f16aa77c --- /dev/null +++ b/web/src/engine/websites/decorators/SpeedBind.ts @@ -0,0 +1,827 @@ +import { Fetch, FetchCSS, FetchJSON, FetchRequest, FetchWindowCSS } from '../../FetchProvider'; +import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; +import type { Priority } from '../../taskpool/TaskPool'; +import * as Common from './Common'; + +type JSONPageData_v016452 = { + items: Configuration_v016452[] +} + +type Configuration_v016452 = { + ContentID : string, + ctbl: string[], + ptbl: string[], + ServerType: number, + ContentsServer: string, + p: string, + ViewMode: number, + ContentDate : string +} + +type Params_v016452 = { + cid: string, + u0: string, + u1: string, + sharingKey: string +} + +type JSONImageData_v016061 = { + resources: { + i: { + src: string + } + } + views: PageView_v016061[] +} +type PageView_v016061 = { + coords: string[], + width: number, + height : number +} + +type PageView_v016130 = { + transfers: { + coords: { + height : number, + width: number, + xdest: number, + xsrc: number, + ydest: number, + ysrc: number + }[] + }[], + width: number, + height: number +} + +type SBCDATA = { + ttx: string; +} + +type DescrambleKP = { + s: string, + u: string +} + +/********************************************** + ******** Page List Extraction Methods ******** + **********************************************/ + +/** + * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. + * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages + * @param baseUrl - sdcqds + */ +export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { + const url = baseUrl ? new URL(baseUrl) : new URL(this.URI); + const uri = new URL(chapter.Identifier, this.URI); + const request = new FetchRequest(uri.href, { + headers: { + Referer: this.URI.href + } });//referer needed for ManpaPlanet + const data = await FetchCSS(request, 'div#content.pages'); + const el = data[0]; + + if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { + const uri = new URL(chapter.Identifier, url); + uri.searchParams.set('cid', el.dataset['ptbinbCid']); + return await getPageList_v016113(this, uri.pathname + uri.search, el.dataset.ptbinb, url.href, chapter); + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && uri.searchParams.get('u0') && uri.searchParams.get('u1')) { + return await getPageList_v016452(this, chapter, el.dataset.ptbinb, url.href); + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && uri.searchParams.get('u1')) { + return await getPageList_v016201(chapter, el.dataset.ptbinb, url.href); + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { + return await getPageList_v016130(this, chapter.Identifier, el.dataset.ptbinb, url.href, chapter); + } + const imageConfigurations = el.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + if (imageConfigurations.length > 0) { + // TODO: Use the response URL instead of the request URL (in case of redirection ...) + return await _getPageList_v016061(this, [...imageConfigurations], request.url, chapter); + } + + throw new Error('Unsupported version of SpeedBinb reader!'); +} + +/** + * A class decorator that adds the ability to extract all pages for a given chapter using the given CSS {@link query}. + * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. + * @param baseUrl - sdcqds + */ +export function PagesSinglePage(baseUrl = '') { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + if (context && context.kind !== 'class') { + throw new Error(context.name); + } + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePage.call(this, chapter, baseUrl); + } + }; + }; +} + +/** +************************* +*** SpeedBinb v01.6061 *** +* ** Comic Meteor, Comic Valkyrie, ZeroSum, DigitalMargaRet, ComicBrise +************************* +*/ +async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: HTMLDivElement[], url: string, parent: Chapter): Promise { + return imageConfigurations.map(element => { + //Zerosum & digital margaret fix ("index.html" or missing "/") + const baseURI = new URL(url); + return new Page(scraper, parent, new URL(element.dataset.ptimg, baseURI.href)); + }); +} + +/** + ************************* + *** SpeedBinb v01.6113 *** + * ** Ohtabooks, Futabanet*** + ************************* + */ +async function getPageList_v016113(scraper: MangaScraper, chapterID: string, apiURL: string, baseURL: string, chapter: Chapter): Promise { + return await getPageList_v016130(scraper, chapterID, apiURL, baseURL, chapter); +} + +/** + ************************* + *** SpeedBinb v01.6452 *** + * ** Cmoa *** + ************************* + */ +async function getPageList_v016452(scraper : MangaScraper, chapter: Chapter, apiURL: string, baseURL: string): Promise { + const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); + const u0 = new URL(chapter.Identifier, baseURL).searchParams.get('u0'); + const u1 = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); + const sharingKey = _tt(cid); + const uri = new URL(apiURL, baseURL + '/'); + uri.searchParams.set('cid', cid); + uri.searchParams.set('dmytime', String(Date.now())); + uri.searchParams.set('k', sharingKey); + uri.searchParams.set('u0', u0); + uri.searchParams.set('u1', u1); + const request = new FetchRequest(uri.href); + const data: JSONPageData_v016452 = await FetchJSON(request); + const params: Params_v016452 = { cid, sharingKey, u0, u1 }; + return await getPageLinks_v016452(scraper, data.items[0], params, baseURL, chapter); +} +async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter): Promise { + configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl); + configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl); + //configuration.ServerType = parseInt(configuration.ServerType); + if (configuration['ServerType'] === 0) { + return await getPageLinksSBC_v016452(scraper, configuration, params, baseURL, chapter); + } + return Promise.reject(new Error('Content server type not supported!')); +} + +async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter) { + const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + uri.searchParams.set('cid', params.cid); + uri.searchParams.set('p', configuration.p); + uri.searchParams.set('q', '1'); + uri.searchParams.set('vm', String(configuration.ViewMode)); + uri.searchParams.set('dmytime', configuration.ContentDate); + uri.searchParams.set('u0', params.u0); + uri.searchParams.set('u1', params.u1); + return await fetchSBC(scraper, uri, configuration, chapter); +} + +/** +************************* +*** SpeedBinb v01.6201 *** +* ** YoungJump *** +************************* +*/ + +async function getPageList_v016201(chapter: Chapter, apiURL: string, baseURL: string): Promise { + const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); + const u = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); + const sharingKey = _tt(cid); + const uri = new URL(apiURL, baseURL + '/'); + uri.searchParams.set('cid', cid); + uri.searchParams.set('dmytime', String(Date.now())); + uri.searchParams.set('k', sharingKey); + uri.searchParams.set('u1', u); + const request = new FetchRequest(uri.href); + const data: JSONPageData_v016452 = await FetchJSON(request); + return await getPageLinks_v016201(data.items[0], sharingKey, u, chapter); +} + +async function getPageLinks_v016201(configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { + const cid = configuration.ContentID; + configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); + configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); + //configuration.ServerType = parseInt(configuration.ServerType); + + if (configuration['ServerType'] === 2) { + return await _getPageLinksContent_v016201(configuration, u, chapter); + } + return Promise.reject(new Error('Content server type not supported!')); +} +async function _getPageLinksContent_v016201(configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { + const uri = new URL(configuration['ContentsServer']); + uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; + uri.pathname += 'content'; + uri.searchParams.set('dmytime', configuration['ContentDate']); + uri.searchParams.set('u1', u); + const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); + const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + const src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + }); + return pageLinks; +} + +/** + ***************************** + *** SpeedBinb v01.6130 ****** + * ** BookLive, MangaPlanet*** + ***************************** + */ + +async function getPageList_v016130(scraper: MangaScraper, chapterID: string, apiURL: string, baseURL: string, chapter: Chapter): Promise { + const cid = new URL(chapterID, baseURL).searchParams.get('cid'); + const sharingKey = _tt(cid); + const uri = new URL(apiURL, baseURL + '/'); + uri.href = uri.href.replace(/\/\//g, '/'); + uri.searchParams.set('cid', cid); + uri.searchParams.set('dmytime', String(Date.now())); + uri.searchParams.set('k', sharingKey); + + const request = new FetchRequest(uri.href); + await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet + + const response = await fetch(new FetchRequest(uri.href)); + const data: JSONPageData_v016452 = await response.json(); + + return await getPageLinks_v016130(scraper, data.items[0], sharingKey, baseURL, chapter); +} + +async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey, baseURL: string, chapter: Chapter): Promise{ + const cid = configuration.ContentID; + /* + *let stbl = this._pt( cid, sharingKey, configuration.stbl ); + *let ttbl = this._pt( cid, sharingKey, configuration.ttbl ); + */ + configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); + configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); + //configuration.ServerType = parseInt(configuration.ServerType); + + if (configuration['ServerType'] === 0) { //Booklive + return await getPageLinksSBC_v016130(scraper, configuration, baseURL, chapter); + } + if (configuration['ServerType'] === 1) {//Futabanet + return await getPageLinksContentJS_v016130(scraper, configuration, chapter); + } + if (configuration['ServerType'] === 2) {//MangaPlanet + return await getPageLinksContent_v016130(scraper, configuration, chapter); + } + return Promise.reject(new Error('Content server type not supported!')); +} + +async function getPageLinksSBC_v016130(scraper: MangaScraper, configuration: Configuration_v016452, baseURL: string, chapter: Chapter) { + const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + uri.searchParams.set('cid', configuration.ContentID); + uri.searchParams.set('dmytime', configuration.ContentDate); + uri.searchParams.set('p', configuration.p); + uri.searchParams.set('vm', String(configuration.ViewMode)); + return await fetchSBC(scraper, uri, configuration, chapter); +} + +async function getPageLinksContent_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter : Chapter) { + const uri = new URL(configuration.ContentsServer); + uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; + uri.pathname += 'content'; + uri.searchParams.set('dmytime', configuration.ContentDate); + const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href, { headers: { Referer: scraper.URI.href } })); + + const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + const src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + }); + return pageLinks; +} + +async function getPageLinksContentJS_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter: Chapter) { + const uri = new URL(configuration.ContentsServer); + uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; + uri.pathname += 'content.js'; + if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); + const response = await Fetch(new FetchRequest(uri.href)); + const data = await response.text(); + const jsonObj = JSON.parse(data.slice(16, -1)); + const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + let src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + if (!src.startsWith('/')) src = '/' + src; + return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); + }); + return pageLinks; +} + +//**************** +// COMMON +//**************** + +async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configuration_v016452, chapter: Chapter) { + const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); + const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + const src = img.getAttribute('src'); + uri.searchParams.set('src', src); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + return new Page(scraper, chapter, new URL(uri.href.replace('/sbcGetCntnt.php', '/sbcGetImg.php'))); + }); + return pageLinks; +} + +/*********************************************** + ******** 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 { + let promise; + switch (true) { + case page.Link.href.endsWith('ptimg.json'): + promise = await process_v016061(this, page, priority, signal, detectMimeType); + break; + case page.Link.href.includes('sbcGetImg'): + promise = await process_v016130(this, page, priority, signal, detectMimeType); + break; + case page.Link.href.includes('M_L.jpg'): + promise = await process_v016130(this, page, priority, signal, detectMimeType); + break; + case page.Link.href.includes('M_H.jpg'): + promise = await process_v016130(this, page, priority, signal, detectMimeType); + break; + case page.Link.href.includes('/img/'): + promise = await process_v016130(this, page, priority, signal, detectMimeType); + break; + default: + promise = Promise.reject('Unsupported version of SpeedBinb reader!'); + break; + } + return promise; +} + +async function process_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { + const data: JSONImageData_v016061 = await FetchJSON(new FetchRequest(page.Link.href)); + const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); + const views = data.views; + const imagedata: Blob = await Common.FetchImage.call(scraper, fakepage, priority, signal, detectMimeType); + const bmpdata = await createImageBitmap(imagedata); + return await descramble_v016061(bmpdata, views); +} + +async function descramble_v016061(bitmap: ImageBitmap, views: PageView_v016061[]): Promise { + return new Promise(resolve => { + const view = views[0]; + const canvas = document.createElement('canvas'); + canvas.width = view.width; + canvas.height = view.height; + const ctx = canvas.getContext('2d'); + + for (const part of view.coords) { + // sample => 'i:119,4+107,150>428,900' + const num = part.split(/[:,+>]/); + const sourceX = parseInt(num[1]); + const sourceY = parseInt(num[2]); + const targetX = parseInt(num[5]); + const targetY = parseInt(num[6]); + const partWidth = parseInt(num[3]); + const partHeight = parseInt(num[4]); + ctx.drawImage(bitmap, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); + } + canvas.toBlob(data => { + resolve(data); + }, 'image/png', parseFloat('90') / 100); + }); +} + +async function process_v016130(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType: boolean): Promise { + const imagedata: Blob = await Common.FetchImage.call(scraper, page, priority, signal, detectMimeType); + const descrambleKeyPair: DescrambleKP = JSON.parse(window.atob(page.Link.hash.slice(1))); + const bmpdata = await createImageBitmap(imagedata); + return await descramble_v016130(bmpdata, descrambleKeyPair); +} + +async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Promise { + return new Promise(resolve => { + const view: PageView_v016130 = _getImageDescrambleCoords(keys.s, keys.u, bitmap.width, bitmap.height); + const canvas = document.createElement('canvas'); + canvas.width = view.width; + canvas.height = view.height; + const ctx = canvas.getContext('2d'); + + for (const part of view.transfers[0].coords) { + const sourceX = part.xsrc; + const sourceY = part.ysrc; + const targetX = part.xdest; + const targetY = part.ydest; + const partWidth = part.width; + const partHeight = part.height; + ctx.drawImage(bitmap, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); + } + canvas.toBlob(data => { + resolve(data); + }, 'image/png', parseFloat('90') / 100); + }); +} + +/** + * 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 ImageDescrambler(detectMimeType = false) { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + if (context && context.kind !== 'class') { + throw new Error(context.name); + } + 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 _tt(t) : string { + const n = Date.now().toString(16).padStart(16, 'x'); // w.getRandomString(16) + const i = Array(Math.ceil(16 / t.length) + 1).join(t); + const r = i.substring(0, 16); + const e = i.substring(i.length - 16); + /* + const r = i.substr(0, 16); + const e = i.substr(-16, 16); + */ + let s = 0; + let u = 0; + let h = 0; + return n.split("").map(function (t, i) { + return s ^= n.charCodeAt(i), + u ^= r.charCodeAt(i), + h ^= e.charCodeAt(i), + t + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"[s + u + h & 63]; + }).join(""); +} + +function _pt(t, i, n) { + const r = t + ':' + i; + let e = 0; + + for (let s = 0; s < r.length; s++) { + e += r.charCodeAt(s) << s % 16; + } + + 0 == (e &= 2147483647) && (e = 305419896); + + let u = ''; + let h = e; + + for (let s = 0; s < n.length; s++) { + h = h >>> 1 ^ 1210056708 & -(1 & h); + const o = (n.charCodeAt(s) - 32 + h) % 94 + 32; + u += String.fromCharCode(o); + } + try { + return JSON.parse(u); + } catch (t) { + return null; + } +} + +/** + * Determine which descramble key pair from ctbl / ptbl shall be used + * depending on the given image name 'pages/cu77gvXE.jpg' + */ +function lt_001(t, ctbl, ptbl) { + const i = [0, 0]; + const n = t.lastIndexOf("/") + 1; + const r = t.length - n; + if (t) { + for (let e = 0; e < r; e++) + i[e % 2] += t.charCodeAt(e + n); + i[0] %= 8, + i[1] %= 8; + } + return { s: ptbl[i[0]], u: ctbl[i[1]] }; +} + +/** + * Copied from official SpeedBinb library + * t imagecontext containing src property ('pages/cu77gvXE.jpg') + * s, u descramble key pair, used to determine descrambler object + * i width of descrambled image + * n height of descrambled image + */ +function _getImageDescrambleCoords(/*t*/s, u, i, n) { + const r = _lt_002(s, u); // var r = this.lt(t.src); + if (!r || !r.vt()) + return null; + const e = r.dt({ + width: i, + height: n + }); + return { + width: e.width, + height: e.height, + transfers: [{ + index: 0, + coords: r.gt({ + width: i, + height: n + }) + }] + }; +} + +/** + * Get a descrambler based on the descramble key pair from ctbl / ptbl + */ +function _lt_002(s, u) { + return "=" === u.charAt(0) && "=" === s.charAt(0) ? new _speedbinb_f(u, s) : u.match(/^[0-9]/) && s.match(/^[0-9]/) ? new _speedbinb_a(u, s) : "" === u && "" === s ? new _speedbinb_h : null; +} + +/** + * Copied from official SpeedBinb library + * define prototype for f + */ +const _speedbinb_f = function () { + function s(t, i) { + this.Mt = null; + const n = t.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/) + , r = i.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/); + + if (null !== n && null !== r && n[1] === r[1] && n[2] === r[2] && n[4] === r[4] && "+" === n[3] && "-" === r[3] && (this.C = parseInt(n[1], 10), + this.I = parseInt(n[2], 10), + this.jt = parseInt(n[4], 10), + !(8 < this.C || 8 < this.I || 64 < this.C * this.I))) { + const e = this.C + this.I + this.C * this.I; + if (n[5].length === e && r[5].length === e) { + const s = this.yt(n[5]) + , u = this.yt(r[5]); + this.xt = s.n, + this.Et = s.t, + this.It = u.n, + this.St = u.t, + this.Mt = []; + for (let h = 0; h < this.C * this.I; h++) + this.Mt.push(s.p[u.p[h]]); + } + } + } + return s.prototype.vt = function () { + return null !== this.Mt; + } + , + s.prototype.bt = function (t) { + const i = 2 * this.C * this.jt + , n = 2 * this.I * this.jt; + return t.width >= 64 + i && t.height >= 64 + n && t.width * t.height >= (320 + i) * (320 + n); + } + , + s.prototype.dt = function (t) { + return this.bt(t) ? { + width: t.width - 2 * this.C * this.jt, + height: t.height - 2 * this.I * this.jt + } : t; + } + , + s.prototype.gt = function (t) { + if (!this.vt()) + return null; + if (!this.bt(t)) + return [{ + xsrc: 0, + ysrc: 0, + width: t.width, + height: t.height, + xdest: 0, + ydest: 0 + }]; + + const h = []; + const i = t.width - 2 * this.C * this.jt, + n = t.height - 2 * this.I * this.jt, + r = Math.floor((i + this.C - 1) / this.C), + e = i - (this.C - 1) * r, + s = Math.floor((n + this.I - 1) / this.I), + u = n - (this.I - 1) * s; + + for (let o = 0; o < this.C * this.I; ++o) { + const a = o % this.C + , f = Math.floor(o / this.C) + , c = this.jt + a * (r + 2 * this.jt) + (this.It[f] < a ? e - r : 0) + , l = this.jt + f * (s + 2 * this.jt) + (this.St[a] < f ? u - s : 0) + , v = this.Mt[o] % this.C + , d = Math.floor(this.Mt[o] / this.C) + , g = v * r + (this.xt[d] < v ? e - r : 0) + , p = d * s + (this.Et[v] < d ? u - s : 0) + , b = this.It[f] === a ? e : r + , m = this.St[a] === f ? u : s; + 0 < i && 0 < n && h.push({ + xsrc: c, + ysrc: l, + width: b, + height: m, + xdest: g, + ydest: p + }); + } + return h; + } + , + s.prototype.yt = function (t) { + let i; + const n = [], r = [], e = []; + for (i = 0; i < this.C; i++) + n.push(s.Tt[t.charCodeAt(i)]); + for (i = 0; i < this.I; i++) + r.push(s.Tt[t.charCodeAt(this.C + i)]); + for (i = 0; i < this.C * this.I; i++) + e.push(s.Tt[t.charCodeAt(this.C + this.I + i)]); + return { + t: n, + n: r, + p: e + }; + } + , + s.Tt = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1], + s; +}(); + +/** + * Copied from official SpeedBinb library + * define prototype for a + */ +const _speedbinb_a = function () { + function t(t, i) { + this.mt = null, + this.wt = null; + const n = this.yt(t); + const r = this.yt(i); + n && r && n.ndx === r.ndx && n.ndy === r.ndy && (this.mt = n, + this.wt = r); + } + return t.prototype.vt = function () { + return null !== this.mt && null !== this.wt; + } + , + t.prototype.bt = function (t) { + return 64 <= t.width && 64 <= t.height && 102400 <= t.width * t.height; + } + , + t.prototype.dt = function (t) { + return t; + } + , + t.prototype.gt = function (t) { + if (!this.vt()) + return null; + const i = []; + const n = t.width - t.width % 8, + r = Math.floor((n - 1) / 7) - Math.floor((n - 1) / 7) % 8, + e = n - 7 * r, + s = t.height - t.height % 8, + u = Math.floor((s - 1) / 7) - Math.floor((s - 1) / 7) % 8, + h = s - 7 * u, + o = this.mt.piece.length; + if (!this.bt(t)) + return [{ + xsrc: 0, + ysrc: 0, + width: t.width, + height: t.height, + xdest: 0, + ydest: 0 + }]; + for (let a = 0; a < o; a++) { + const f = this.mt.piece[a] + , c = this.wt.piece[a]; + i.push({ + xsrc: Math.floor(f.x / 2) * r + f.x % 2 * e, + ysrc: Math.floor(f.y / 2) * u + f.y % 2 * h, + width: Math.floor(f.w / 2) * r + f.w % 2 * e, + height: Math.floor(f.h / 2) * u + f.h % 2 * h, + xdest: Math.floor(c.x / 2) * r + c.x % 2 * e, + ydest: Math.floor(c.y / 2) * u + c.y % 2 * h + }); + } + const l = r * (this.mt.ndx - 1) + e + , v = u * (this.mt.ndy - 1) + h; + return l < t.width && i.push({ + xsrc: l, + ysrc: 0, + width: t.width - l, + height: v, + xdest: l, + ydest: 0 + }), + v < t.height && i.push({ + xsrc: 0, + ysrc: v, + width: t.width, + height: t.height - v, + xdest: 0, + ydest: v + }), + i; + } + , + t.prototype.yt = function (t) { + if (!t) + return null; + const i = t.split("-"); + if (3 != i.length) + return null; + const n = parseInt(i[0], 10) + , r = parseInt(i[1], 10) + , e = i[2]; + if (e.length != n * r * 2) + return null; + const v = []; + const a = (n - 1) * (r - 1) - 1; + const f = a + (n - 1); + const c = f + (r - 1); + const l = c + 1; + + for (let s, u, h, o, d = 0;d < n * r;d++) + s = this.Ot(e.charAt(2 * d)), + u = this.Ot(e.charAt(2 * d + 1)), + d <= a ? o = h = 2 : d <= f ? (h = 2,o = 1) : d <= c ? (h = 1,o = 2) : d <= l && (o = h = 1), + v.push({ + x: s, + y: u, + w: h, + h: o + }); + return { + ndx: n, + ndy: r, + piece: v + }; + } + , + t.prototype.Ot = function (t) { + let i = 0; + let n = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(t); + return n < 0 ? n = "abcdefghijklmnopqrstuvwxyz".indexOf(t) : i = 1, + i + 2 * n; + } + , + t; +}(); + +/** + * Copied from official SpeedBinb library + * define prototype for h + */ +const _speedbinb_h = function () { + // eslint-disable-next-line @typescript-eslint/no-empty-function + function t() { } + return t.prototype.vt = function () { + return !0; + } + , + t.prototype.bt = function () { + return !1; + } + , + t.prototype.dt = function (t) { + return t; + } + , + t.prototype.gt = function (t) { + return [{ + xsrc: 0, + ysrc: 0, + width: t.width, + height: t.height, + xdest: 0, + ydest: 0 + }]; + } + , + t; +}(); \ No newline at end of file diff --git a/web/src/engine/websites/legacy/BookLive.ts b/web/src/engine/websites/legacy/BookLive.ts index 104c854d46..1048ea8de6 100755 --- a/web/src/engine/websites/legacy/BookLive.ts +++ b/web/src/engine/websites/legacy/BookLive.ts @@ -1,14 +1,24 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './BookLive.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +function ChapterExtractor(element: HTMLElement) { + const id = '/bviewer/s/?cid=' + element.dataset.title + '_' + element.dataset.vol; + const title = element.dataset.vol.trim(); + return { id, title }; +} + +@Common.MangaCSS(/^https?:\/\/booklive\.jp\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') +@Common.MangasNotSupported() +@Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { - super('booklive', `BookLive`, 'https://booklive.jp' /*, Tags.Language.English, Tags ... */); + super('booklive', `BookLive`, 'https://booklive.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } public override get Icon() { diff --git a/web/src/engine/websites/legacy/Cmoa.ts b/web/src/engine/websites/legacy/Cmoa.ts new file mode 100644 index 0000000000..a7727195d5 --- /dev/null +++ b/web/src/engine/websites/legacy/Cmoa.ts @@ -0,0 +1,48 @@ +import { Tags } from '../../Tags'; +import icon from './Cmoa.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; +function MangaLabelExtractor(body: HTMLBodyElement) { + const title = body.querySelector('#GA_this_page_title_name').textContent.trim(); + return title; +} + +@Common.MangaCSS(/^https?:\/\/www\.cmoa\.jp\/title\/\d+\/$/, 'body', MangaLabelExtractor) +@Common.MangasNotSupported() +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() +export default class extends DecoratableMangaScraper { + public constructor() { + super('cmoa', `コミックシーモア (Cmoa)`, 'https://www.cmoa.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + public override get Icon() { + return icon; + } + + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li'); + const chapters = []; + const totalPage = pages.length == 0 ? 1 : pages.length - 1; + for (let i = 0; i < totalPage; i++) { + const uri = new URL(manga.Identifier, this.URI); + uri.searchParams.set('page', String(i + 1)); + const pageRequest = new FetchRequest(uri.href); + const data = await FetchCSS(pageRequest, '.title_vol_vox_vols .title_vol_vox_vols_i'); + for (const element of data) { + const chapterLink = element.querySelector('a[href^="/reader/"]'); + if (!chapterLink) { + continue; + } + const chapterUrl = new URL(chapterLink.href, this.URI); + const id = chapterUrl.searchParams.get('content_id'); + const u0 = chapterUrl.pathname.startsWith('/reader/sample') ? 1 : 0; + const title = element.querySelector('.title_details_title_name_h2').textContent.trim(); + chapters.push(new Chapter(this, manga, `/bib/speedreader/?cid=${id.slice(1, 11)}_jp_${id.slice(11, 15)}&u0=${u0}&u1=0`, title.replace('NEW\n', '').trim())); + } + } + return chapters; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/Cmoa.webp b/web/src/engine/websites/legacy/Cmoa.webp new file mode 100644 index 0000000000000000000000000000000000000000..26b8475537c4a2219883e69bc538cd2a32830f9b GIT binary patch literal 2830 zcmV+p3-R<)Nk&En3jhFDMM6+kP&il$0000G0001A003VA06|PpNO=GN00D3mfRUqw z4h9f%&yxW@aM2v_M8MsNpb4oGIx~rZ{4XLVpwsEkE}{%mkHrKX^mj^`ruI`{tDvpF zYLstLwwapO3K>tGDet7*lkQsow*jU*%6`%tvr#w;HRX%xEBPw1QKYL3ZGhqODSD!w z%OTK3QMsxLbO8WXP&goF3IG6bEdZSXDqsL$06t|Xjzy#*p&87+*gytEwg7_w{Q&*} zqw0eF8&RLC{!9Bi*dM*<$@7Ki4;cQSKPvPI)d!#l^q=)zVZMMK zS|7Tf2fw_2l)0!KcmIC;kn`uo$C|yP^+wB|NZOWsqwL4%zcKw-?+4S*s2Aej%Rjw- zSAJpf;(!mx|Dk`k{^!Ui*k51|)-Kv z1$r+2)h!iUJ3Cd4j`2pvF&oyoA;$6D#D>vtQgB*ewmDJF8U;c0Eu%U3jFyk8y1Yal zJ%2xAWq6wuH@qVa1)OmDk*&^^;#2kf#rk4-l8}>ZEv5J4nrQjMzwwCrge zjhV7YnF*tJ!s96i9uXzdH?m$NQT0DevH$=8{(m7d^K7SoDaK$vJwj*M*9ZVK-|Lb3 zy8`e zv^@Q*_-%>3sScW9Wi5RiK#1HduRc5!5y8tYFOdd=W@oKIqRs6_@H!;P{fYQ^Z*{m| z1*OqlhLF;s@;1>?tO(4-7zT{ehzgoH=I`2Z3Z5iB=5`=knO6ZM$h z;_z8U!vC1#Ssp9UFVfqu#30qBMeF(e3~NWBONc%EU%In@WS-H6$>N)AUcMp0rVK3V z0wuw6vKU*BZ;ZZJ$eHiuh#-NiL_8(rxhfyOp!0h#3MGRZ&B9y&Ub@DEk!uqWQ3Ua zQx22_Whl?zliMcnoRgjYzyCk~*#2h^|L@_!WBg9}JNN(O{N^rrTf`#9Qso+T#X)v! z#WC|PhPibw3t-ik8~x^fH2mYst<$r4-ubv?eBcD)87XzdL$yP->~X=wvd1j=GJDT7 zzBFzMt&sA&HQXtb@S||6FU;)gzmT0H;TEBt*CQ}A48x5#yBR}p&#n(@ev}g*$%LO* z(=}=RJ_r6aTSKSy3}2(IF-0ZvK;}TpnUT)7e?A2;;-dNzp9!hAeCgtt!no^1N3kh5 zTlUNX7}MUp<~$8R2{X)Yhx3E6 z^n8|P&R03wTbO>PQx3bY!{9va^UZpguUeMN|2r7%0nj@@`Gi6)tSlU9JC`b|GPE;5 zg8v!jCs;?LfXC(A-IM3B%U_BU9(X!4$L7n+bu>DyT3EO&b#U|10Qe3sL7UNx0Z*Mt zk~idO0Y23fnJ#;84(UP$+1W?e(BpKdaz8@M2DAwnN7bsq^6M)0l0Rz+RA_ESgw20Q zf$)Q^Dg5+Lgit5$3f}8~!AU{zLG3%kkGQ5Z?-1_5c&H9IV`|jRGt1}%Qr}Ng#CnJL z^E*1c78DrScVKm+9&CWyLzD%urv2d7CeAhEJEwg|B%jSlqF>ra{J&x`*y||mjOvyLvKeHXMSRgu5Fu4?o zN-3zqFZVCOVfGmD7(T1rHpIZIz82-IiuahVAfJcV}b`0FDB45Tc~T=R`J?3 zJ)&7KR5=P2uSh`-4PQZGdo5)D4%ds@&~d+zPIXfoda(_Fq1*_Nxy~)T!p78(4sJj3 z>v6^6Z+t9vfxe9>h&M7nH!I%dFK8EKfXIm3+t6;((|j1)FAM}BAZ=K|+Y^Ye>Vw}p zdiuNLcuYl|M`iw_&J-hV!Zdt-z?FX&CgSCUw5z97R|J2wQ1VjHAw!6KEoL=ZBQ-LC zDuPF8L2|*u@T)HW_WTk*|F}z#0#41;LE+N+<+Y^&kJh%~QWIDsQh*8WWbN|E!obhg zp`|EH_j8$Q*%^}an&qS$fert5CPA5;y&s>rq07NF3=jWRM|)i~?W4n0tkJFjqDpCp z`jR$}GdcvrB5y(#@*xEJxyjP$@D6(w39!v%4-CZO@Aa@i$n0Ml8aLB1Ukm|_DXx|| z`asx~?<&$%X1zTza;>MwWVW6;o4cXLbLSgzkn#g$#+^7%GA*&`aD5*MTa!#xWNt+h zRM_}seZ=+QY_k;DSX}to=-+`qVThS3*cZOgSzLCicWlbjC*l)d@JEb7g`SG!^?Ga- zvEdS9ofRcU;M{^PIiND#=Y@3x?F2_r+8k?CYjq3XlG2G!&QiXL`!YSfcqGl*n0N22 zN=JDxe@qMR%Y#BxDGL~3l=ETVhST=6Z7{jw7)!v0nKo+l8pS)e4FKc($i*HfdROhn z^kZ8C87^PmPwB{wSo}#urQ$%`8FBcs9QRJ;dJZsdu8m%JW^rM@1E_T1J7m;mZbHI} z7usf9yfk44R)K+pymk$t-k@?K4okXlXujF3s_0sZ{6Aj>&UN4Kd_mR2%;+wLO~WFm2V- zjI!|z{UoTL{ReJO%6bkTW)fz)^MAQx6f{BqiOIAzFSE^i`UrKj=iNo&C^@_As!K=j zIra;$#URB0{d;}o@dY;lq7v0@AF#TbdPU9*G|(9qieM)n z3UC!RdNklpGxj$pP=R_Vuok5S&Tfm%37J2=nkw+QKvZ84j!WLQbc+1*>D2gR9M`JTL`}&{=(k!@ zd3`q6hI+w186#o|F}9ngQMR^hG}km12q5U6$1T~nQ%Vl4~Lnb zH*<6PPN5+!eJ&B|_uGI;L!Znly2Om?zcw@~-T(ZieQVym { - return { - id: this.getRootRelativeOrAbsoluteLink(element.pathname, this.url), - title: element.innerText.trim() - }; - }); - } - async _getChapters(manga) { - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, '.modal.modal-chapter .modal-body'); + public override async FetchChapters(manga: Manga): Promise { + const uri = new URL(manga.Identifier, this.URI); + const request = new FetchRequest(uri.href); + const data = await FetchCSS(request, '.modal.modal-chapter .modal-body'); return data.reverse() - .filter(e => e.querySelector(".banner-trial source").getAttribute("alt") == "FREE") - .map(element => { - return { - id: element.querySelector('.banner-trial a').pathname, - title: element.querySelector('.primary-title').textContent.trim() - }; - }); + .filter(e => e.querySelector(".banner-trial img").getAttribute("alt") == "FREE") + .map(element => new Chapter(this, manga, element.querySelector('.banner-trial a').pathname, element.querySelector('.primary-title').textContent.trim())); } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ComicMeteor.ts b/web/src/engine/websites/legacy/ComicMeteor.ts index a6811b8c19..235d5657e2 100755 --- a/web/src/engine/websites/legacy/ComicMeteor.ts +++ b/web/src/engine/websites/legacy/ComicMeteor.ts @@ -1,105 +1,38 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './ComicMeteor.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + const title = anchor.querySelector('img').getAttribute('alt').trim(); + return { id, title }; +} +@Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/\S+\/$/, 'div.h2ttl_other') +@Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { - public constructor() { - super('comicmeteor', `COMICメテオ (COMIC Meteor)`, 'https://comic-meteor.jp' /*, Tags.Language.English, Tags ... */); + super('comicmeteor', `COMICメテオ (COMIC Meteor)`, 'https://comic-meteor.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } - public override get Icon() { return icon; } -} - -// Original Source -/* -class ComicMeteor extends SpeedBinb { - /** - * - * - constructor() { - super(); - super.id = 'comicmeteor'; - super.label = 'COMICメテオ (COMIC Meteor)'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://comic-meteor.jp'; + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const contents = await FetchCSS(request, 'div#contents'); + const data = contents[0]; + let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a')] + .map(element => new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim())); + if (chapterList.length == 0) { + chapterList = [...data.querySelectorAll('div.latest_info_box div.latest_info_link_btn01 a')] + .map(element => new Chapter(this, manga, element.pathname, element.text.replace('読む', '').trim())); + } + return chapterList; } - - /** - * - * - _getMangaListFromPages( page ) { - page = page || 1; - let request = new Request( this.url + '/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page=' + page, this.requestOptions ); - return this.fetchDOM( request, 'div.update_work_size div.update_work_info_img a', 5 ) - .then( data => { - let mangaList = data.map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.querySelector( 'source' ).getAttribute('alt').trim() - }; - } ); - if( mangaList.length > 0 ) { - return this._getMangaListFromPages( page + 1 ) - .then( mangas => mangaList.concat( mangas ) ); - } else { - return Promise.resolve( mangaList ); - } - } ); - } - - /** - * - * - _getMangaList( callback ) { - this._getMangaListFromPages() - .then( data => { - callback( null, data ); - } ) - .catch( error => { - console.error( error, this ); - callback( error, undefined ); - } ); - } - - /** - * - * - _getChapterList( manga, callback ) { - let request = new Request( this.url + manga.id, this.requestOptions ); - this.fetchDOM( request, 'div#contents' ) - .then( data => { - data = data[0]; - let chapterList = [...data.querySelectorAll( 'div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a' )] - .map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.closest( 'div.work_episode_table' ).querySelector( 'div.work_episode_txt' ).innerText.replace( manga.title, '' ).trim(), - language: '' - }; - } ); - if( chapterList.length === 0 ) { - chapterList = [...data.querySelectorAll( 'div.latest_info_box div.latest_info_link_btn01 a' )] - .map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.text.replace( '読む', '' ).trim(), - language: '' - }; - } ); - } - callback( null, chapterList ); - } ) - .catch( error => { - console.error( error, manga ); - callback( error, undefined ); - } ); - } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ComicValkyrie.ts b/web/src/engine/websites/legacy/ComicValkyrie.ts index 6ac0617b4e..d7b4b26c5b 100755 --- a/web/src/engine/websites/legacy/ComicValkyrie.ts +++ b/web/src/engine/websites/legacy/ComicValkyrie.ts @@ -1,66 +1,44 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './ComicValkyrie.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; + +function MangaExtractor(element: HTMLElement) { + const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '').slice(1); + const title = element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim(); + return { id, title }; +} +function ChapterExtractor(element: HTMLElement) { + const a: HTMLAnchorElement = element.parentElement.querySelector('a.read_bt'); + const id = a.href; + const title = element.textContent.trim(); + return { id, title }; +} +@Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) +@Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { - public constructor() { - super('comicvalkyrie', `Comic Valkyrie`, 'https://www.comic-valkyrie.com' /*, Tags.Language.English, Tags ... */); + super('comicvalkyrie', `Comic Valkyrie`, 'https://www.comic-valkyrie.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } - public override get Icon() { return icon; } -} - -// Original Source -/* -class ComicValkyrie extends SpeedBinb { - - constructor() { - super(); - super.id = 'comicvalkyrie'; - super.label = 'Comic Valkyrie'; - this.tags = ['manga', 'japanese']; - this.url = 'https://www.comic-valkyrie.com'; - } - - async _getChapters(manga) { - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, '#new_story .title, #back_number .title'); - return data.map(element => { - const a = element.parentElement.querySelector('a.read_bt'); - return { - id: a.href, - title: element.textContent, - language: '' - }; - }); - } - async _getMangaFromURI(uri) { - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'meta[property="og:title"]', 3); - let id = uri.pathname.slice(1); - let title = this.cleanMangaTitle(data[0].content); - return new Manga(this, id, title); + public override ValidateMangaURL(url: string): boolean { + return /^https?:\/\/www\.comic-valkyrie\.com\/\S+\/new.html$/.test(url); } - async _getMangas() { - let request = new Request(this.url + '/list', this.requestOptions); - let data = await this.fetchDOM(request, '.box_wrap .box'); - return data.map(element => ({ - id: new URL(element.querySelector('a').href).pathname.replace('/new.html', '').slice(1), - title: this.cleanMangaTitle(element.querySelector('.title').textContent), - })); + public override async FetchManga(provider: MangaPlugin, url: string): Promise { + const uri = new URL(url); + const request = new FetchRequest(uri.href); + const data = await FetchCSS(request, 'meta[property = "og:title"]'); + const id = uri.pathname.replace('/new.html', '').slice(1); + const title = data[0].content.replace(/\s*THE COMIC\s*/i, '').trim(); + return new Manga(this, provider, id, title); } - - cleanMangaTitle(str) { - return str.replace(/\s*THE COMIC\s*i, '').trim(); - } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ComicZerosum.ts b/web/src/engine/websites/legacy/ComicZerosum.ts index 0f94617a02..6979bd4260 100755 --- a/web/src/engine/websites/legacy/ComicZerosum.ts +++ b/web/src/engine/websites/legacy/ComicZerosum.ts @@ -1,56 +1,61 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './ComicZerosum.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, Manga, type MangaPlugin } from '../../providers/MangaPlugin'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchJSON, FetchRequest } from '../../FetchProvider'; + +type MangaJson = { + Work: { + Name: string, + Tag: string; + Stories?: { + Url: string, + Name: string + }[] + } +} -export default class extends DecoratableMangaScraper { +type MangaList = { + Stories: { + Work: { + Name: string, + Tag : string + } + }[] +} +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() +export default class extends DecoratableMangaScraper { + private readonly data_url = 'https://zerosumonline.com/json/zerosum/'; public constructor() { - super('comiczerosum', `Comic ゼロサム (Comic ZEROSUM)`, 'https://online.ichijinsha.co.jp/zerosum' /*, Tags.Language.English, Tags ... */); + super('comiczerosum', `Comic ゼロサム (Comic ZEROSUM)`, 'https://zerosumonline.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } - public override get Icon() { return icon; } -} -// Original Source -/* -class ComicZerosum extends SpeedBinb { - - constructor() { - super(); - super.id = 'comiczerosum'; - super.label = 'Comic ゼロサム (Comic ZEROSUM)'; - this.tags = ['manga', 'japanese']; - this.url = 'https://online.ichijinsha.co.jp/zerosum'; - this.data_url = 'https://online.ichijinsha.co.jp/json/zerosum'; + public override ValidateMangaURL(url: string) : boolean { + return /^https?:\/\/zerosumonline\.com\/zerosum\/comic\/[^/]+$/.test(url); } - async _getMangas() { - const request = new Request(`${this.data_url}/list/name.json`, this.requestOptions); - const data = await this.fetchJSON(request); + public override async FetchManga(provider: MangaPlugin, url: string) : Promise { + const id = url.match(/\/zerosum\/comic\/([^/]+)$/)[1]; + const request = new FetchRequest(`${this.data_url}/works/${id}.json`); + const data: MangaJson = await FetchJSON(request); + return new Manga(this, provider, id, data.Work.Name); - return data.Stories.map(story => { - return { - id: story.Work.Tag, - title: story.Work.Name - }; - }); } - async _getChapters(manga) { - const request = new Request(`${this.data_url}/works/${manga.id}.json`, this.requestOptions); - const data = await this.fetchJSON(request); + public override async FetchMangas(provider : MangaPlugin): Promise { + const request = new FetchRequest(`${this.data_url}/list/name.json`); + const data: MangaList = await FetchJSON(request); + return data.Stories.map(story => new Manga(this, provider, story.Work.Tag, story.Work.Name)); + } - return data.Work.Stories.map(story => { - return { - id: story.Url, - title: story.Name - }; - }); + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(`${this.data_url}/works/${manga.Identifier}.json`); + const data: MangaJson = await FetchJSON(request); + return data.Work.Stories.map(story => new Chapter(this, manga, story.Url, story.Name)); } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/DigitalMargaret.ts b/web/src/engine/websites/legacy/DigitalMargaret.ts new file mode 100644 index 0000000000..1e1098f2a4 --- /dev/null +++ b/web/src/engine/websites/legacy/DigitalMargaret.ts @@ -0,0 +1,32 @@ +import { Tags } from '../../Tags'; +import icon from './DigitalMargaret.webp'; +import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + const title = anchor.querySelector('img').getAttribute('alt').trim(); + return {id, title}; +} +function ChapterExtractor(element: HTMLElement) { + const id = element.querySelector('a').pathname; + const title = element.querySelector('p').textContent.trim(); + return { id, title }; +} + +@Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/\S+\/$/, 'section#product div.content h3') +@Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) +@Common.ChaptersSinglePageCSS('section#product div.list div.box div.number',ChapterExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() + +export default class extends DecoratableMangaScraper { + public constructor() { + super('digitalmargaret', `デジタルマーガレット (Digital Margaret)`, 'https://digitalmargaret.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/legacy/DigitalMargaret.webp b/web/src/engine/websites/legacy/DigitalMargaret.webp new file mode 100644 index 0000000000000000000000000000000000000000..dd80d39ab9bc1b26a225840c3877edc8c953013a GIT binary patch literal 436 zcmV;l0ZaZ;Nk&Gj0RRA3MM6+kP&go<0RR9n2LPP`Dlh;r06uLplt&~ZA|WcM0DujN zW&n9B##CT7z+HfE9+Iv6d}!eF#!+EmgN$$^n5UNZIF^mv&PZk)fB^pez^mUlHy3Z$ zh+h}w%ROPCXzI?)%=Rbc*8V5~D}W@dD|f>FWQ;>q^Y)%MQ~R9b=e*S3oP=~YKMIxz z$dl^Vs9~aaZ1dHpD?>L0211*)L={CLF)F|RWsLZb%9!w*lj^&k_Wl3r34a@S4BqwY z={DKsDrKvmj+6X+!ke`^k615+iI4f zLa1J0eEQQ`lkr5?O} zmRFsPv2LcD(Ww&ApSl%6K^YQ*XPTL_AW5Ep|bXXK4$HS(GNuKMA{ e=v#Z2c<9$u`~%6Dn('span:not(.new)').innerText.replace(/\(\d+\.\d+(.*)\)$/, '').trim(); + const id = anchor.href; + return { id, title }; +} +@Common.MangaCSS(/^https?:\/\/gaugau\.futabanet\.jp\/list\/work\/\S+$/, 'h1.detail-ex__title') +@Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) +@Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) +@SpeedBind.PagesSinglePage('https://reader.futabanet.jp') +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { - super('futabanet', `がうがうモンスター (Futabanet Monster)`, 'https://gaugau.futabanet.jp' /*, Tags.Language.English, Tags ... */); + super('futabanet', `がうがうモンスター (Futabanet Monster)`, 'https://gaugau.futabanet.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } - public override get Icon() { return icon; } -} - -// Original Source -/* -class Futabanet extends SpeedBinb { - - constructor() { - super(); - super.id = 'futabanet'; - super.label = 'がうがうモンスター (Futabanet Monster)'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://gaugau.futabanet.jp'; - } - - async _getMangaFromURI(uri) { - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'h1.detail-ex__title'); - let id = uri.pathname; - let title = data[0].textContent.trim(); - return new Manga(this, id, title); - } - - async _getMangas() { - let request = new Request(new URL('/list/works', this.url), this.requestOptions); - let pages = await this.fetchDOM(request, 'li.m-pager__last a'); - pages = Number( new URL(pages[0].href).searchParams.get('page') ); - - let data; - let mangas = []; - for (let page = 1; page <= pages; page++) { - request = new Request(this.url + '/list/works?page=' + page); - data = await this.fetchDOM(request, 'div.m-result-list__item a'); - mangas.push( ...data.map(element => { - return { - id: this.getRootRelativeOrAbsoluteLink(element, this.url), - title: element.querySelector('.m-result-list__title').textContent.trim() - }; - })); - } - return mangas; - } - - async _getChapters(manga) { - let request = new Request(new URL(manga.id, this.url), this.requestOptions); - let data = await this.fetchDOM(request, 'section.detail-sec.detail-ex div.detail-ex__btn-item a'); - return data.map(element => { - let title = element.querySelector('span:not(.new)'); - return { - id: this.getRootRelativeOrAbsoluteLink(element, request.url), - title: title.innerText.replace(/\(\d+\.\d+(.*)\)$/, '').trim(), - }; - }); - } - -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/MangaPlanet.ts b/web/src/engine/websites/legacy/MangaPlanet.ts new file mode 100644 index 0000000000..c93f52ab45 --- /dev/null +++ b/web/src/engine/websites/legacy/MangaPlanet.ts @@ -0,0 +1,58 @@ +import { Tags } from '../../Tags'; +import icon from './MangaPlanet.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest, FetchWindowScript } from '../../FetchProvider'; + +function MangaExtractor(element: HTMLElement) { + const id = element.querySelector('a').pathname; + const title = element.querySelector('h3').innerText.trim(); + return {id, title}; +} + +@Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/\S+$/, '.card-body.book-detail h3') +@Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list',1,1,0, MangaExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() + +export default class extends DecoratableMangaScraper { + public constructor() { + super('mangaplanet', `MangaPlanet`, 'https://mangaplanet.com', Tags.Language.English, Tags.Media.Manga, Tags.Source.Official); + } + public override get Icon() { + return icon; + } + + public override async Initialize(): Promise { + const request = new FetchRequest(this.URI.href); + return FetchWindowScript(request, `window.cookieStore.set('mpaconf', '18')`); + } + + public override async FetchChapters(manga: Manga): Promise { + const uri = new URL(manga.Identifier, this.URI); + const request = new FetchRequest(uri.href); + const data = await FetchCSS(request, '#accordion div[id*="vol_"]'); + const chapters : Chapter[] = []; + for (const volume of data) { + const title = volume.querySelector('h3').textContent.trim() + " - "; + + for (const chapter of [...volume.querySelectorAll(".list-group")].filter(e => e.querySelector('a') != null)) { + const origurl = /'([a-z0-9:/.?=]*)'/g.exec(chapter.querySelector('a').getAttribute("@click"))[1]; + //the chapter site gives different urls. sometimes you first get redirected to a login or 18+ restricted page other times not. + let chapid = origurl.split("/").slice(-1)[0]; + if (chapid.includes("?")) { + chapid = chapid.split("=").slice(-1)[0];//gets the id of the cid parameter + } + let url = ""; + if (origurl.includes("/reader")) { + url = "/reader?cid=" + chapid + "&sk=1"; + } else if (origurl.includes("/viewer")) { + url = "https://image.mangaplanet.com/viewer/" + chapid; + } + chapters.push(new Chapter(this, manga, url, title + chapter.querySelector('span').innerText.trim())); + } + } + return chapters; + } +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/MangaPlanet.webp b/web/src/engine/websites/legacy/MangaPlanet.webp new file mode 100644 index 0000000000000000000000000000000000000000..a5a04787ab80d7501076f587cd8c99b16f0acb50 GIT binary patch literal 3674 zcmV-g4yEx@Nk&Fe4gdgGMM6+kP&il$0000G0001A003VA06|PpNE-$K00FRtZQCJ9 z()0b_AK7MgscrYzc3ZQk?zQdRv5m&qsP3_C+qP{R6%qe;kW~?p8SCAHh?oHWkE#26 zCV-Q_XL#qB6#f0`(SS1lQY4pjSw2obVdUiG9HK1ZymxfzymwM2Wn=sNZ959zg{V?3 zy#_Tm59%dUt4e9`EU~Zc^&N+IB3>Yx_M^kDeB{*+KKbN>S0B0Zupdo}K)e(uPOGIT z;Z*CeU@y)^oC@8xKK7Z^a;DE5yLC52r3g_kbg5E^aEv91tz4@yLWP!Hp0!{W$4Q!o z5JH+Jacmas*9X*Y%^4p#)ChykjAOyPUAG# zM+Y~et}9Umbm9+}o_X$yWxM@t$7Pot+Or6V#4+v5HRy)>^}810)Cx}HVDJ9gp`EBA z^qafn{4@8MH!7l9*yYq>P#^K<2{7&!OXFZQ3~_3=jKkx+z<{>nFFyQRtyDW-ja*Yu zb)~|hPb^NY#%XMyEJB6uvyZ)W=~g`e=T+!jo8v$nE3G3~orVrO7N<&X z$0}DvnH(D|pL5CjRmzdpVRhVL$DkB(<#e(;_PFE9zl>5m+gWUN9ou&JT%M%|;WG)n zkGb)pbGK`RZ7dD-6;j&<&Efg^1vqkiZ@cX-Z^F^^qNP^nslC{QWb(|ru{V+p*NvWg z^~2L{vDJNS?PwOyR(G`G$gMP2gz1)A2~(SncIDaft`R6j3do&hxl@qNBIevV0;L#b zu_ac@#1^Af;`#n9EhvTGVQD#1yMt=+YsyK2hJ$rT1 zZgE*+YezkOFWMIs@(O*{nb(R41K+YxmSAr+z|`A*h!=|d-e0Eo!86xVD{X4?S$yZ( zL=-4AuC|~NJcn6ap2QB@>9Rq1Tmc|7M2K*=rR510?~XX>MkEE`1cc^~ER^ZPCKOg* zZwgXCwX%){D{-*(P`b_EX)B8Mv{_Q7#M{YWlCho@Lt;k3(Dyep9yJ-~}g0QOZ0^%9PkVXq`omEh|MiRtXkLWVQ;* zvAZ1pCtN|ErVq;$?9F}%d)<1|Mn!pso%K$c61xr>54h&SD=*#>DL_11+`rLI7MCZs zy>R`8kG}A?>Z2nf@5ljg>nSzn2IaPv)(-$5dk>Pv!on}orj}f&o*~Y z#8a(oWT70vHX;JV<@3zDV;G*!9cNimhQ!Vy5)~D4d*MgMwoOmv?r|jk4NEV^t z_O(&6JI1_iX?>;k_86RUq_Jt+&k%aJ5Jk`n^n}{Rx)h$Q{Q4hGa_r2t}89kWwp~azgA+`@^ z;px;dYz5A_Oc$Y4i&HOvUuX9VPWwqCNW{2%EJCPG)~Oy))}BeZ5=dDnmV>o zsrD-5REKQ1@_h?tNgOAg#&Kd6?ERG+3QnoHIyzOaLZRxQ;oB>ojxBTi^onmcfK%#H z#EDQ#RUjI_VEd!bzwXvsuRH(f?H7!X09F2OidS;07yiDAQ}5L|=hS<3!v75h09H^q zAP@)u0MH`fDMUk0Lz?Ai;vUt!f|(rIX;VbYuOL= zBl+9d1D&7kFQ^aM&)QFW-$#GoJwQLMbrpWj`wsbPe%$;Qe(3(?drW`y_5j6){U0qf z1UrOAZ1(;8yHzZ|pci;}kKnTKKJ%`Bull^7et-T~{}1`^fKS%1NdH`4upY<1v<;|+ z3Vy0ia(E%ozEHp0g2=S^PO`*4UI2TWZ!2TStk(HBXY@VbbAEnrgvc{!IDv4=GbwJK zCUhl#~^u0RH|*f{f>Q*2V+5 zBOI>(P?srQez`K>2s1OF5Mu$D>W3`xQBFzx&}eG8Mq&Ue{$kvAKY80?mL5N)+#m{^ znu_1I<-;w#^N;e*E&2bOyz8_7F~W*5``hQFg{0{h&V`W~`SL2&Go$5uDor@nxddOt z@a<|;`|S}jI9pM<98P;9U11dH=L-9*H#?wHxDlk-=%{6Kx{5-+ItdJCuAPj?(^5+4 zovDRoAyf2m-WV@_Kz@IpG;%i)z5}v+eV)z)|HoD$Lh4Vzd{3qkqZcAhymxenZH3C@ zio`@x|Jh2}1AtC#e^IDE`bBVPuMEu?U=Y!#D#~mB4ss&b^ucXZQirhYOy$29d^b<7 zrEfjSgDaZV_DwqNo0y^ML!IDVWWctx3ElG*?WS_pylV%-sD*N{k!QX-VsB*rE2S<; zrES2A{{Wl|7OVJq9G#qpLtph;NvFecVo%@8UiYm89Q(WO(Req=-Z5wY+oNRnUL-(z zkfKS$czL?lx5n9`BswtOWsb-Y&(K~eeLYbq`t9aqq9v4$P!cCg#|;|ESC5%AW2yKZ zTH#R5K!t(KrPoc*$fjwe1vYY zt5k-OpIdE7T_S|Er=9Z19o5Y$OZ!R-gagqK6x25llXf4PWw=OrlGo?RCKbOZjU9Ue zdlFoK;KywRI+0*ZtLSqaP}#&}pCM3D^L4KV=g08N59(y`LiMQBc3azg(qmT;iP~lz zJlsoLcxt7MLCjMz5dD3jWk^!j?{27!L?4YK(_R~(q-G)a+}vW1ChpxSXT0YBFPQ{IEiu*;3bP5-;{V>kiV$5IJq+j$S(NTS-ON@eD- zr&u6SJi)N+I1Y0RcWT692tVOUqWeene0N98C)gEHn|76bC~9*2i*h}yM&~ba&o6YE z)kwMM;xM*B6}S@WXYTTgqd$+KMXU&j3hTm61SxI7ksm8g+!k^(i7hA%fc0*h_L40;)lp_Sn^)?#kmoDrlJ{D zhcTnC)1kSfYX)3?33b-~!i99XDqz&jFJb2HBrcfYg|Rw?G4!KC)d<~6>9p%VTK`rI zzc)rV`;&|4COhW8NtM8>4&pItA<4{L{trgn@43h$7>^BItb{ixd%%2i@s! zwoRFlEaGmBal`m5!NM?*7iysELTTI4B7Q9cwhzws?NZEI!72aS)`so&Fnr(nN!VVo sxCg9~AZmaJM`Qx6b;qjf@Uz_q+^7!9wcI$k7VCQRK}w|o9?$>)05^t1=Kufz literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/legacy/Ohtabooks.ts b/web/src/engine/websites/legacy/Ohtabooks.ts index e4b0c003a6..dfbdf4164c 100755 --- a/web/src/engine/websites/legacy/Ohtabooks.ts +++ b/web/src/engine/websites/legacy/Ohtabooks.ts @@ -1,106 +1,55 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './Ohtabooks.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + const title = anchor.querySelector('.title').textContent.trim(); + return { id, title }; +} +@Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/\S+\/$/, 'h2.contentTitle') +@Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { - super('ohtabooks', `Ohtabooks`, 'http://webcomic.ohtabooks.com' /*, Tags.Language.English, Tags ... */); + super('ohtabooks', `Ohtabooks`, 'http://webcomic.ohtabooks.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } public override get Icon() { return icon; } -} - -// Original Source -/* -class Ohtabooks extends SpeedBinb { - /** - * - * - constructor() { - super(); - super.id = 'ohtabooks'; - super.label = 'Ohtabooks'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'http://webcomic.ohtabooks.com'; + public override async FetchPages(chapter: Chapter): Promise { + //find real reader url to send to Speedbind, since redirection is done by Javascript + const data = await FetchCSS(new FetchRequest(chapter.Identifier), 'body'); + const reallink = data[0].innerHTML.match(/location.href='(.*)'/)[1]; + return await SpeedBind.FetchPagesSinglePage.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } - /** - * - * - _getMangaList( callback ) { - let uri = this.url + '/list/'; - this.fetchDOM( uri, 'div.bnrList ul li a' ) - .then( data => { - let mangaList = data.map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, uri ), - title: element.querySelector( '.title' ).textContent.trim() - }; - } ); - callback( null, mangaList ); - } ) - .catch( error => { - console.error( error, this ); - callback( error, undefined ); - } ); + public override async FetchChapters(manga: Manga): Promise { + const uri = new URL(manga.Identifier, this.URI); + const data = await FetchCSS(new FetchRequest(uri.href), 'a[onClick^="return !openBook("]'); + let chapterList = data.map(element => { + let partId = element.getAttribute('onclick'); + partId = partId.match(/\d+/)[0]; + + let title = element.querySelector('.title') ? element.querySelector('.title').textContent : element.querySelector('btnMini') ? element.querySelector('btnMini').textContent : 'マンガをよむ'; + title = title.trim(); + return { + id: 'https://yondemill.jp/contents/' + partId + '?view=1&u0=1', + title: title + }; + }); + // Remove duplicates + chapterList = chapterList.reverse().filter((chapter, index) => { + return index === chapterList.findIndex(c => c.id === chapter.id); + }); + + return chapterList.map(chapter => new Chapter(this, manga, chapter.id, chapter.title)); } - - /** - * - * - _getChapterList( manga, callback ) { - let uri = this.url + manga.id; - this.fetchDOM( uri, 'a[onClick^="return !openBook("]' ) - .then( data => { - let chapterList = data.map( element => { - let partId = element.getAttribute( 'onclick' ); - partId = partId.match(/\d+/); - - let title = element.querySelector( '.title' ); - if( title ) { - title = title.textContent; - } else if( element.classList.contains( 'btnMini' ) ) { - title = element.textContent; - } - - return { - id: this.getRootRelativeOrAbsoluteLink( 'https://yondemill.jp/contents/' + partId + '?view=1&u0=1', uri ), - title: title ? title.trim() : 'マンガをよむ', - language: 'ja' - }; - } ); - - // Remove duplicates - chapterList = chapterList.reverse().filter( ( chapter, index ) => { - return index === chapterList.findIndex( c => c.id === chapter.id ); - } ); - - callback( null, chapterList ); - } ) - .catch( error => { - console.error( error, manga ); - callback( error, undefined ); - } ); - } - - _getPageList( manga, chapter, callback ) { - this.fetchDOM( chapter.id, 'script[type="text/javascript"]' ) - .then( data => { - data = data[0].innerHTML; - let ch = { - id: data.substring( data.indexOf('\'') + 1, data.lastIndexOf('\'') ), - title: chapter.title, - language: chapter.language - }; - super._getPageList( manga, ch, callback ); - } ); - } -} -*/ \ No newline at end of file +} \ No newline at end of file From a2bd26f774bf0c372f383ae6088b9e45d3e2e492 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 15 Jul 2023 20:01:32 +0200 Subject: [PATCH 02/88] Update SpeedBind.ts --- web/src/engine/websites/decorators/SpeedBind.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBind.ts b/web/src/engine/websites/decorators/SpeedBind.ts index d4f16aa77c..5c97549ef9 100644 --- a/web/src/engine/websites/decorators/SpeedBind.ts +++ b/web/src/engine/websites/decorators/SpeedBind.ts @@ -93,7 +93,7 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, return await getPageList_v016452(this, chapter, el.dataset.ptbinb, url.href); } if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && uri.searchParams.get('u1')) { - return await getPageList_v016201(chapter, el.dataset.ptbinb, url.href); + return await getPageList_v016201(this, chapter, el.dataset.ptbinb, url.href); } if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { return await getPageList_v016130(this, chapter.Identifier, el.dataset.ptbinb, url.href, chapter); @@ -200,7 +200,7 @@ async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Co ************************* */ -async function getPageList_v016201(chapter: Chapter, apiURL: string, baseURL: string): Promise { +async function getPageList_v016201(scraper: MangaScraper,chapter: Chapter, apiURL: string, baseURL: string): Promise { const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); const u = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); const sharingKey = _tt(cid); @@ -211,21 +211,21 @@ async function getPageList_v016201(chapter: Chapter, apiURL: string, baseURL: st uri.searchParams.set('u1', u); const request = new FetchRequest(uri.href); const data: JSONPageData_v016452 = await FetchJSON(request); - return await getPageLinks_v016201(data.items[0], sharingKey, u, chapter); + return await getPageLinks_v016201(scraper, data.items[0], sharingKey, u, chapter); } -async function getPageLinks_v016201(configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { +async function getPageLinks_v016201(scraper : MangaScraper, configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); //configuration.ServerType = parseInt(configuration.ServerType); if (configuration['ServerType'] === 2) { - return await _getPageLinksContent_v016201(configuration, u, chapter); + return await _getPageLinksContent_v016201(scraper, configuration, u, chapter); } return Promise.reject(new Error('Content server type not supported!')); } -async function _getPageLinksContent_v016201(configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { +async function _getPageLinksContent_v016201(scraper: MangaScraper, configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { const uri = new URL(configuration['ContentsServer']); uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; uri.pathname += 'content'; @@ -236,7 +236,7 @@ async function _getPageLinksContent_v016201(configuration: Configuration_v016452 const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); - return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); }); return pageLinks; } From ba1439c8a2f27b1300aa5fc8ef1aa9b06568ae32 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 20 Sep 2023 13:46:22 +0200 Subject: [PATCH 03/88] add ComicPolaris && 123Hon ZeroSum is now a custom API --- .../engine/websites/decorators/SpeedBind.ts | 7 +- web/src/engine/websites/legacy/BookLive.ts | 43 +----- .../engine/websites/legacy/ComicPolaris.ts | 125 +++++------------- .../engine/websites/legacy/ComicZerosum.ts | 85 ++++++------ .../engine/websites/legacy/OneTwoThreeHon.ts | 71 ++++------ 5 files changed, 107 insertions(+), 224 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBind.ts b/web/src/engine/websites/decorators/SpeedBind.ts index 5c97549ef9..d0d372808c 100644 --- a/web/src/engine/websites/decorators/SpeedBind.ts +++ b/web/src/engine/websites/decorators/SpeedBind.ts @@ -133,8 +133,13 @@ export function PagesSinglePage(baseUrl = '') { */ async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: HTMLDivElement[], url: string, parent: Chapter): Promise { return imageConfigurations.map(element => { - //Zerosum & digital margaret fix ("index.html" or missing "/") + //Zerosum & digital margaret, 123hon fix (missing "/").. Other ending must have been filtered from the plugin itself (like "/index.html") const baseURI = new URL(url); + + if (!baseURI.href.endsWith('/') && !element.dataset.ptimg.startsWith('/')) { + baseURI.href += '/'; + } + return new Page(scraper, parent, new URL(element.dataset.ptimg, baseURI.href)); }); } diff --git a/web/src/engine/websites/legacy/BookLive.ts b/web/src/engine/websites/legacy/BookLive.ts index 1048ea8de6..68df1f664d 100755 --- a/web/src/engine/websites/legacy/BookLive.ts +++ b/web/src/engine/websites/legacy/BookLive.ts @@ -24,45 +24,4 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } -} - -// Original Source -/* -class BookLive extends SpeedBinb { - - constructor() { - super(); - super.id = 'booklive'; - super.label = 'BookLive'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://booklive.jp'; - } - - async _getMangaFromURI(uri) { - let request = new Request(uri, this.requestOptions); - let data = await this.fetchDOM(request, 'div#product_detail_area div.product_info > h1#product_display_1', 3); - let id = uri.pathname; - let title = data[0].innerText.trim(); - return new Manga(this, id, title); - } - - async _getMangas() { - // https://booklive.jp/select/title/page_no/5012 - const msg = 'This website does not support mangas/chapters, please copy and paste the links containing the chapters directly from your browser into HakuNeko.'; - throw new Error(msg); - } - - async _getChapters(manga) { - const uri = new URL(manga.id, this.url); - const request = new Request(uri, this.requestOptions); - const data = await this.fetchDOM(request, 'div#product_detail_area div.product_actions ul a.bl-bviewer'); - return data.map(element => { - return { - id: '/bviewer/s/?cid=' + element.dataset.title + '_' + element.dataset.vol, - title: element.dataset.vol.trim(), - language: '' - }; - }); - } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ComicPolaris.ts b/web/src/engine/websites/legacy/ComicPolaris.ts index 931ee7bef8..7e76a5344e 100755 --- a/web/src/engine/websites/legacy/ComicPolaris.ts +++ b/web/src/engine/websites/legacy/ComicPolaris.ts @@ -1,105 +1,42 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './ComicPolaris.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + const title = anchor.querySelector('img').getAttribute('alt').trim(); + return { id, title }; +} +@Common.MangaCSS(/^https?:\/\/comic-polaris\.jp\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') +@Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { - super('comicpolaris', `COMICポラリス (COMIC Polaris)`, 'https://comic-polaris.jp' /*, Tags.Language.English, Tags ... */); + super('comicpolaris', `COMICポラリス (COMIC Polaris)`, 'https://comic-polaris.jp', Tags.Media.Manga, Tags.Language.Japanese); } - public override get Icon() { return icon; } -} - -// Original Source -/* -class ComicPolaris extends SpeedBinb { - - /** - * - * - constructor() { - super(); - super.id = 'comicpolaris'; - super.label = 'COMICポラリス (COMIC Polaris)'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://comic-polaris.jp'; - } - - /** - * - * - _getMangaListFromPages( page ) { - page = page || 1; - let request = new Request( this.url + '/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page=' + page, this.requestOptions ); - return this.fetchDOM( request, 'div.update_work_size div.update_work_info_img a', 5 ) - .then( data => { - let mangaList = data.map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.querySelector( 'source' ).getAttribute('alt').trim() - }; - } ); - if( mangaList.length > 0 ) { - return this._getMangaListFromPages( page + 1 ) - .then( mangas => mangaList.concat( mangas ) ); - } else { - return Promise.resolve( mangaList ); - } - } ); - } - - /** - * - * - _getMangaList( callback ) { - this._getMangaListFromPages() - .then( data => { - callback( null, data ); - } ) - .catch( error => { - console.error( error, this ); - callback( error, undefined ); - } ); + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const data = (await FetchCSS(request, 'div#contents'))[0]; + let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a')] + .map(element => { + return new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim()); + }); + if (chapterList.length === 0) { + chapterList = [...data.querySelectorAll('div.latest_info_box div.latest_info_link_btn01 a')] + .map(element => { + return new Chapter(this, manga, element.pathname, element.text.replace('読む', '').trim()); + }); + } + return chapterList; } - /** - * - * - _getChapterList( manga, callback ) { - let request = new Request( this.url + manga.id, this.requestOptions ); - this.fetchDOM( request, 'div#contents' ) - .then( data => { - data = data[0]; - let chapterList = [...data.querySelectorAll( 'div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a' )] - .map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.closest( 'div.work_episode_table' ).querySelector( 'div.work_episode_txt' ).innerText.replace( manga.title, '' ).trim(), - language: '' - }; - } ); - if( chapterList.length === 0 ) { - chapterList = [...data.querySelectorAll( 'div.latest_info_box div.latest_info_link_btn01 a' )] - .map( element => { - return { - id: this.getRootRelativeOrAbsoluteLink( element, request.url ), - title: element.text.replace( '読む', '' ).trim(), - language: '' - }; - } ); - } - callback( null, chapterList ); - } ) - .catch( error => { - console.error( error, manga ); - callback( error, undefined ); - } ); - } -} -*/ \ No newline at end of file +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/ComicZerosum.ts b/web/src/engine/websites/legacy/ComicZerosum.ts index 6979bd4260..0f94617a02 100755 --- a/web/src/engine/websites/legacy/ComicZerosum.ts +++ b/web/src/engine/websites/legacy/ComicZerosum.ts @@ -1,61 +1,56 @@ -import { Tags } from '../../Tags'; -import icon from './ComicZerosum.webp'; -import { Chapter, DecoratableMangaScraper, Manga, type MangaPlugin } from '../../providers/MangaPlugin'; -import * as SpeedBind from '../decorators/SpeedBind'; -import { FetchJSON, FetchRequest } from '../../FetchProvider'; - -type MangaJson = { - Work: { - Name: string, - Tag: string; - Stories?: { - Url: string, - Name: string - }[] - } -} +// Auto-Generated export from HakuNeko Legacy +// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 -type MangaList = { - Stories: { - Work: { - Name: string, - Tag : string - } - }[] -} +//import { Tags } from '../../Tags'; +import icon from './ComicZerosum.webp'; +import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { - private readonly data_url = 'https://zerosumonline.com/json/zerosum/'; + public constructor() { - super('comiczerosum', `Comic ゼロサム (Comic ZEROSUM)`, 'https://zerosumonline.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + super('comiczerosum', `Comic ゼロサム (Comic ZEROSUM)`, 'https://online.ichijinsha.co.jp/zerosum' /*, Tags.Language.English, Tags ... */); } + public override get Icon() { return icon; } +} - public override ValidateMangaURL(url: string) : boolean { - return /^https?:\/\/zerosumonline\.com\/zerosum\/comic\/[^/]+$/.test(url); +// Original Source +/* +class ComicZerosum extends SpeedBinb { + + constructor() { + super(); + super.id = 'comiczerosum'; + super.label = 'Comic ゼロサム (Comic ZEROSUM)'; + this.tags = ['manga', 'japanese']; + this.url = 'https://online.ichijinsha.co.jp/zerosum'; + this.data_url = 'https://online.ichijinsha.co.jp/json/zerosum'; } - public override async FetchManga(provider: MangaPlugin, url: string) : Promise { - const id = url.match(/\/zerosum\/comic\/([^/]+)$/)[1]; - const request = new FetchRequest(`${this.data_url}/works/${id}.json`); - const data: MangaJson = await FetchJSON(request); - return new Manga(this, provider, id, data.Work.Name); + async _getMangas() { + const request = new Request(`${this.data_url}/list/name.json`, this.requestOptions); + const data = await this.fetchJSON(request); + return data.Stories.map(story => { + return { + id: story.Work.Tag, + title: story.Work.Name + }; + }); } - public override async FetchMangas(provider : MangaPlugin): Promise { - const request = new FetchRequest(`${this.data_url}/list/name.json`); - const data: MangaList = await FetchJSON(request); - return data.Stories.map(story => new Manga(this, provider, story.Work.Tag, story.Work.Name)); - } + async _getChapters(manga) { + const request = new Request(`${this.data_url}/works/${manga.id}.json`, this.requestOptions); + const data = await this.fetchJSON(request); - public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(`${this.data_url}/works/${manga.Identifier}.json`); - const data: MangaJson = await FetchJSON(request); - return data.Work.Stories.map(story => new Chapter(this, manga, story.Url, story.Name)); + return data.Work.Stories.map(story => { + return { + id: story.Url, + title: story.Name + }; + }); } -} \ No newline at end of file +} +*/ \ No newline at end of file diff --git a/web/src/engine/websites/legacy/OneTwoThreeHon.ts b/web/src/engine/websites/legacy/OneTwoThreeHon.ts index 76ed40c243..496d1198b0 100755 --- a/web/src/engine/websites/legacy/OneTwoThreeHon.ts +++ b/web/src/engine/websites/legacy/OneTwoThreeHon.ts @@ -1,60 +1,47 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; +import { Tags } from '../../Tags'; import icon from './OneTwoThreeHon.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../../providers/MangaPlugin'; +import * as Common from '../decorators/Common'; +import * as SpeedBind from '../decorators/SpeedBind'; +import { FetchCSS, FetchRequest } from '../../FetchProvider'; + +function MangaInfoExtractor(anchor: HTMLAnchorElement) { + console.log(anchor.pathname); + const id = anchor.pathname; + const title = anchor.pathname.match(/[\w]+\/web-comic\/([\S]+)\//)[1]; + return { id, title }; +} +@Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[\S]+\/web-comic\/[\S]+\/$/, 'div.title-area h2') +@SpeedBind.PagesSinglePage() +@SpeedBind.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { - super('onetwothreehon', `123hon`, 'https://www.123hon.com' /*, Tags.Language.English, Tags ... */); + super('onetwothreehon', `123hon`, 'https://www.123hon.com', Tags.Media.Manga, Tags.Language.Japanese ); } public override get Icon() { return icon; } -} - -// Original Source -/* -class OneTwoThreeHon extends SpeedBinb { - constructor() { - super(); - super.id = 'onetwothreehon'; - super.label = '123hon'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://www.123hon.com'; - this.mangaList = '/polca/web-comic/'; + public override async FetchMangas(provider: MangaPlugin): Promise { + const mangalist = []; + for (const path of ['/polca/web-comic/', '/nova/web-comic']) { + const mangas = await Common.FetchMangasSinglePageCSS.call(this, provider, path, 'ul.comic__list > li > a', MangaInfoExtractor); + mangalist.push(...mangas); + } + return mangalist; - this.queryMangas = 'ul.comic__list > li > a'; - this.queryChapters = 'div.read-episode li'; } - async _getMangas() { - const request = new Request(new URL(this.mangaList, this.url), this.requestOptions); - const data = await this.fetchDOM(request, this.queryMangas); - return data.map(link => { - return { - id: this.getRootRelativeOrAbsoluteLink(link, this.url), - title: link.href.match(/(\w+)\/?$/)[1] // Rather crude, but there are no text titles on the listing - }; - }); - } - - async _getChapters(manga) { - const request = new Request(new URL(manga.id, this.url), this.requestOptions); - const data = await this.fetchDOM(request, this.queryChapters); - + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const data = await FetchCSS(request, 'div.read-episode li'); return data.map(element => { if (element.querySelector('a')) { // otherwise chapter not available - return { - id: element.querySelector('a').href, - title: element.innerText.match(/\s*(.*?)\s+/)[1] - }; + return new Chapter(this, manga, new URL(element.querySelector('a').href.replace(/index.html$/, ''), this.URI).href, element.innerText.match(/\s*(.*?)\s+/)[1]); } - }).filter(element => element !== undefined); + }).filter(element => element !== undefined).filter(element => !/#comics-store/.test(element.Identifier)); } -} -*/ \ No newline at end of file +} \ No newline at end of file From e54cd12f030e244f3190ed6c60e8013caca1afc2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 1 Oct 2023 12:17:32 +0200 Subject: [PATCH 04/88] typo its SpeedBinb and not SpeedBind, silly me --- .../websites/decorators/{SpeedBind.ts => SpeedBinb.ts} | 0 web/src/engine/websites/legacy/BookLive.ts | 6 +++--- web/src/engine/websites/legacy/Cmoa.ts | 6 +++--- web/src/engine/websites/legacy/ComicBrise.ts | 6 +++--- web/src/engine/websites/legacy/ComicMeteor.ts | 6 +++--- web/src/engine/websites/legacy/ComicPolaris.ts | 6 +++--- web/src/engine/websites/legacy/ComicValkyrie.ts | 6 +++--- web/src/engine/websites/legacy/DigitalMargaret.ts | 6 +++--- web/src/engine/websites/legacy/Futabanet.ts | 6 +++--- web/src/engine/websites/legacy/MangaPlanet.ts | 6 +++--- web/src/engine/websites/legacy/Ohtabooks.ts | 8 ++++---- web/src/engine/websites/legacy/OneTwoThreeHon.ts | 6 +++--- 12 files changed, 34 insertions(+), 34 deletions(-) rename web/src/engine/websites/decorators/{SpeedBind.ts => SpeedBinb.ts} (100%) diff --git a/web/src/engine/websites/decorators/SpeedBind.ts b/web/src/engine/websites/decorators/SpeedBinb.ts similarity index 100% rename from web/src/engine/websites/decorators/SpeedBind.ts rename to web/src/engine/websites/decorators/SpeedBinb.ts diff --git a/web/src/engine/websites/legacy/BookLive.ts b/web/src/engine/websites/legacy/BookLive.ts index 68df1f664d..ba16d133b3 100755 --- a/web/src/engine/websites/legacy/BookLive.ts +++ b/web/src/engine/websites/legacy/BookLive.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './BookLive.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; function ChapterExtractor(element: HTMLElement) { const id = '/bviewer/s/?cid=' + element.dataset.title + '_' + element.dataset.vol; const title = element.dataset.vol.trim(); @@ -12,8 +12,8 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^https?:\/\/booklive\.jp\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/legacy/Cmoa.ts b/web/src/engine/websites/legacy/Cmoa.ts index a7727195d5..126253fd07 100644 --- a/web/src/engine/websites/legacy/Cmoa.ts +++ b/web/src/engine/websites/legacy/Cmoa.ts @@ -2,7 +2,7 @@ import icon from './Cmoa.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaLabelExtractor(body: HTMLBodyElement) { const title = body.querySelector('#GA_this_page_title_name').textContent.trim(); @@ -11,8 +11,8 @@ function MangaLabelExtractor(body: HTMLBodyElement) { @Common.MangaCSS(/^https?:\/\/www\.cmoa\.jp\/title\/\d+\/$/, 'body', MangaLabelExtractor) @Common.MangasNotSupported() -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { super('cmoa', `コミックシーモア (Cmoa)`, 'https://www.cmoa.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/legacy/ComicBrise.ts b/web/src/engine/websites/legacy/ComicBrise.ts index 48c73068ba..832e1ff51e 100755 --- a/web/src/engine/websites/legacy/ComicBrise.ts +++ b/web/src/engine/websites/legacy/ComicBrise.ts @@ -2,13 +2,13 @@ import { Tags } from '../../Tags'; import icon from './ComicBrise.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; @Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/\S+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { super('comicbrise', `Comic-Brise`, 'https://www.comic-brise.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/legacy/ComicMeteor.ts b/web/src/engine/websites/legacy/ComicMeteor.ts index 235d5657e2..afbbd2af21 100755 --- a/web/src/engine/websites/legacy/ComicMeteor.ts +++ b/web/src/engine/websites/legacy/ComicMeteor.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './ComicMeteor.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { @@ -13,8 +13,8 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/\S+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { super('comicmeteor', `COMICメテオ (COMIC Meteor)`, 'https://comic-meteor.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/legacy/ComicPolaris.ts b/web/src/engine/websites/legacy/ComicPolaris.ts index 7e76a5344e..21bd5ab56c 100755 --- a/web/src/engine/websites/legacy/ComicPolaris.ts +++ b/web/src/engine/websites/legacy/ComicPolaris.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './ComicPolaris.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { @@ -13,8 +13,8 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/comic-polaris\.jp\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/legacy/ComicValkyrie.ts b/web/src/engine/websites/legacy/ComicValkyrie.ts index d7b4b26c5b..d70dc1532a 100755 --- a/web/src/engine/websites/legacy/ComicValkyrie.ts +++ b/web/src/engine/websites/legacy/ComicValkyrie.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './ComicValkyrie.webp'; import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaExtractor(element: HTMLElement) { @@ -19,8 +19,8 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { super('comicvalkyrie', `Comic Valkyrie`, 'https://www.comic-valkyrie.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/legacy/DigitalMargaret.ts b/web/src/engine/websites/legacy/DigitalMargaret.ts index 1e1098f2a4..0e09926e5a 100644 --- a/web/src/engine/websites/legacy/DigitalMargaret.ts +++ b/web/src/engine/websites/legacy/DigitalMargaret.ts @@ -2,7 +2,7 @@ import icon from './DigitalMargaret.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; @@ -18,8 +18,8 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/\S+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number',ChapterExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/legacy/Futabanet.ts b/web/src/engine/websites/legacy/Futabanet.ts index 6f1b0c32a9..32789d12b6 100755 --- a/web/src/engine/websites/legacy/Futabanet.ts +++ b/web/src/engine/websites/legacy/Futabanet.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './Futabanet.webp'; import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; const title = anchor.querySelector('.m-result-list__title').textContent.trim(); @@ -17,8 +17,8 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/gaugau\.futabanet\.jp\/list\/work\/\S+$/, 'h1.detail-ex__title') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) -@SpeedBind.PagesSinglePage('https://reader.futabanet.jp') -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage('https://reader.futabanet.jp') +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/legacy/MangaPlanet.ts b/web/src/engine/websites/legacy/MangaPlanet.ts index c93f52ab45..94efafb20f 100644 --- a/web/src/engine/websites/legacy/MangaPlanet.ts +++ b/web/src/engine/websites/legacy/MangaPlanet.ts @@ -2,7 +2,7 @@ import icon from './MangaPlanet.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest, FetchWindowScript } from '../../FetchProvider'; function MangaExtractor(element: HTMLElement) { @@ -13,8 +13,8 @@ function MangaExtractor(element: HTMLElement) { @Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/\S+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list',1,1,0, MangaExtractor) -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/legacy/Ohtabooks.ts b/web/src/engine/websites/legacy/Ohtabooks.ts index dfbdf4164c..b3f625b885 100755 --- a/web/src/engine/websites/legacy/Ohtabooks.ts +++ b/web/src/engine/websites/legacy/Ohtabooks.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './Ohtabooks.webp'; import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { @@ -13,7 +13,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/\S+\/$/, 'h2.contentTitle') @Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) -@SpeedBind.ImageDescrambler() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { @@ -25,10 +25,10 @@ export default class extends DecoratableMangaScraper { } public override async FetchPages(chapter: Chapter): Promise { - //find real reader url to send to Speedbind, since redirection is done by Javascript + //find real reader url to send to SpeedBinb, since redirection is done by Javascript const data = await FetchCSS(new FetchRequest(chapter.Identifier), 'body'); const reallink = data[0].innerHTML.match(/location.href='(.*)'/)[1]; - return await SpeedBind.FetchPagesSinglePage.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); + return await SpeedBinb.FetchPagesSinglePage.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/legacy/OneTwoThreeHon.ts b/web/src/engine/websites/legacy/OneTwoThreeHon.ts index 496d1198b0..da800dbab9 100755 --- a/web/src/engine/websites/legacy/OneTwoThreeHon.ts +++ b/web/src/engine/websites/legacy/OneTwoThreeHon.ts @@ -2,7 +2,7 @@ import { Tags } from '../../Tags'; import icon from './OneTwoThreeHon.webp'; import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../../providers/MangaPlugin'; import * as Common from '../decorators/Common'; -import * as SpeedBind from '../decorators/SpeedBind'; +import * as SpeedBinb from '../decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../../FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { @@ -13,8 +13,8 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[\S]+\/web-comic\/[\S]+\/$/, 'div.title-area h2') -@SpeedBind.PagesSinglePage() -@SpeedBind.ImageDescrambler() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() export default class extends DecoratableMangaScraper { public constructor() { From 618806afd4c298357c7c5cbfea3783be241bbe13 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 1 Oct 2023 13:53:53 +0200 Subject: [PATCH 05/88] move files to websites --- .../engine/websites/{legacy => }/BookLive.ts | 8 ++-- .../websites/{legacy => }/BookLive.webp | Bin web/src/engine/websites/{legacy => }/Cmoa.ts | 10 ++-- .../engine/websites/{legacy => }/Cmoa.webp | Bin .../websites/{legacy => }/ComicBrise.ts | 10 ++-- .../websites/{legacy => }/ComicBrise.webp | Bin .../websites/{legacy => }/ComicMeteor.ts | 10 ++-- .../websites/{legacy => }/ComicMeteor.webp | Bin .../websites/{legacy => }/ComicPolaris.ts | 10 ++-- .../websites/{legacy => }/ComicPolaris.webp | Bin web/src/engine/websites/ComicRide.ts | 43 ++++++++++++++++++ web/src/engine/websites/ComicRide.webp | Bin 0 -> 446 bytes .../websites/{legacy => }/ComicValkyrie.ts | 10 ++-- .../websites/{legacy => }/ComicValkyrie.webp | Bin .../websites/{legacy => }/DigitalMargaret.ts | 8 ++-- .../{legacy => }/DigitalMargaret.webp | Bin .../engine/websites/{legacy => }/Futabanet.ts | 8 ++-- .../websites/{legacy => }/Futabanet.webp | Bin .../websites/{legacy => }/MangaPlanet.ts | 10 ++-- .../websites/{legacy => }/MangaPlanet.webp | Bin .../engine/websites/{legacy => }/Ohtabooks.ts | 10 ++-- .../websites/{legacy => }/Ohtabooks.webp | Bin .../websites/{legacy => }/OneTwoThreeHon.ts | 10 ++-- .../websites/{legacy => }/OneTwoThreeHon.webp | Bin web/src/engine/websites/_index.ts | 23 +++++----- 25 files changed, 107 insertions(+), 63 deletions(-) rename web/src/engine/websites/{legacy => }/BookLive.ts (80%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/BookLive.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/Cmoa.ts (90%) rename web/src/engine/websites/{legacy => }/Cmoa.webp (100%) rename web/src/engine/websites/{legacy => }/ComicBrise.ts (83%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicBrise.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicMeteor.ts (89%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicMeteor.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicPolaris.ts (89%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicPolaris.webp (100%) mode change 100755 => 100644 create mode 100644 web/src/engine/websites/ComicRide.ts create mode 100644 web/src/engine/websites/ComicRide.webp rename web/src/engine/websites/{legacy => }/ComicValkyrie.ts (88%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/ComicValkyrie.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/DigitalMargaret.ts (83%) rename web/src/engine/websites/{legacy => }/DigitalMargaret.webp (100%) rename web/src/engine/websites/{legacy => }/Futabanet.ts (85%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/Futabanet.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/MangaPlanet.ts (91%) rename web/src/engine/websites/{legacy => }/MangaPlanet.webp (100%) rename web/src/engine/websites/{legacy => }/Ohtabooks.ts (90%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/Ohtabooks.webp (100%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/OneTwoThreeHon.ts (88%) mode change 100755 => 100644 rename web/src/engine/websites/{legacy => }/OneTwoThreeHon.webp (100%) mode change 100755 => 100644 diff --git a/web/src/engine/websites/legacy/BookLive.ts b/web/src/engine/websites/BookLive.ts old mode 100755 new mode 100644 similarity index 80% rename from web/src/engine/websites/legacy/BookLive.ts rename to web/src/engine/websites/BookLive.ts index ba16d133b3..0265d80f1c --- a/web/src/engine/websites/legacy/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './BookLive.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; function ChapterExtractor(element: HTMLElement) { const id = '/bviewer/s/?cid=' + element.dataset.title + '_' + element.dataset.vol; const title = element.dataset.vol.trim(); diff --git a/web/src/engine/websites/legacy/BookLive.webp b/web/src/engine/websites/BookLive.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/BookLive.webp rename to web/src/engine/websites/BookLive.webp diff --git a/web/src/engine/websites/legacy/Cmoa.ts b/web/src/engine/websites/Cmoa.ts similarity index 90% rename from web/src/engine/websites/legacy/Cmoa.ts rename to web/src/engine/websites/Cmoa.ts index 126253fd07..3a5e8456b4 100644 --- a/web/src/engine/websites/legacy/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './Cmoa.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaLabelExtractor(body: HTMLBodyElement) { const title = body.querySelector('#GA_this_page_title_name').textContent.trim(); return title; diff --git a/web/src/engine/websites/legacy/Cmoa.webp b/web/src/engine/websites/Cmoa.webp similarity index 100% rename from web/src/engine/websites/legacy/Cmoa.webp rename to web/src/engine/websites/Cmoa.webp diff --git a/web/src/engine/websites/legacy/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts old mode 100755 new mode 100644 similarity index 83% rename from web/src/engine/websites/legacy/ComicBrise.ts rename to web/src/engine/websites/ComicBrise.ts index 832e1ff51e..0288612403 --- a/web/src/engine/websites/legacy/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './ComicBrise.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; @Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/\S+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') diff --git a/web/src/engine/websites/legacy/ComicBrise.webp b/web/src/engine/websites/ComicBrise.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/ComicBrise.webp rename to web/src/engine/websites/ComicBrise.webp diff --git a/web/src/engine/websites/legacy/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts old mode 100755 new mode 100644 similarity index 89% rename from web/src/engine/websites/legacy/ComicMeteor.ts rename to web/src/engine/websites/ComicMeteor.ts index afbbd2af21..2694e49d03 --- a/web/src/engine/websites/legacy/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './ComicMeteor.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; diff --git a/web/src/engine/websites/legacy/ComicMeteor.webp b/web/src/engine/websites/ComicMeteor.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/ComicMeteor.webp rename to web/src/engine/websites/ComicMeteor.webp diff --git a/web/src/engine/websites/legacy/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts old mode 100755 new mode 100644 similarity index 89% rename from web/src/engine/websites/legacy/ComicPolaris.ts rename to web/src/engine/websites/ComicPolaris.ts index 21bd5ab56c..5969fdd269 --- a/web/src/engine/websites/legacy/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './ComicPolaris.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; diff --git a/web/src/engine/websites/legacy/ComicPolaris.webp b/web/src/engine/websites/ComicPolaris.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/ComicPolaris.webp rename to web/src/engine/websites/ComicPolaris.webp diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts new file mode 100644 index 0000000000..fa49d3abc9 --- /dev/null +++ b/web/src/engine/websites/ComicRide.ts @@ -0,0 +1,43 @@ +import { Tags } from '../Tags'; +import icon from './ComicRide.webp'; +import { DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; + +function MangaExtractor(element: HTMLElement) { + return { + id: element.querySelector('a.p-update-list__main').pathname.replace(/\/\//g, "/"), + title: element.querySelector('.p-update-list__title').textContent.trim() + }; +} + +function ChapterExtractor(element: HTMLElement) { + return { + id: element.querySelector('span.p-backnumber-d__view a.u-over-opacity-img').pathname.replace(/\/\//g, "/"), + title: element.querySelector('.p-backnumber-d .p-backnumber-d__title').textContent.trim() + }; +} + +@Common.MangasSinglePageCSS('/', 'ul li.p-update-list__item', MangaExtractor) +@Common.ChaptersSinglePageCSS('article.p-modal-org', ChapterExtractor) +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() +export default class extends DecoratableMangaScraper { + public constructor() { + super('comicride', `ComicRide`, 'https://www.comicride.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override ValidateMangaURL(url: string): boolean { + return /^https?:\/\/www\.comicride\.jp\/(\/)?book\/\S+\/(index\.html)?$/.test(url); + } + + public override async FetchManga(provider: MangaPlugin, url: string): Promise { + return await Common.FetchMangaCSS.call(this, provider, url.replace(/\/\//g, "/"), '.p-detail-head__title'); + + } + +} \ 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..cf51ae3d888fb38445c9440c9fab9d8fda0c032c GIT binary patch literal 446 zcmV;v0YUy!Nk&Gt0RRA3MM6+kP&go}0RRAS3ILq}Dj)zL06uLhl0~E!SZvgY)^a1}z(=(_8pI_M5$pRz|YXO3pr;6VF`#=2_n-;lx zXpK+UZUZRJuoPeVjPig0{{P$_^sV|b>(D4?Hl=kEqL9wn|IfeuuNeR6JpzBX{fZfJ z8ES+D)qVft#r4_A3|>%LmVUq||N5I+1}8fxFldjJcsjnl?zr-Wx5~9^t>y9mIwlTh zx=8Qz2hUtPNm?2oEnPjW4pfEx{8M@)v9qvym#8F2TereVvc9SoEn{vhdwgrI5`mFmpFd$c1mE6zh22Eq zok;iFzHr;kyhu8-*ze3KOQ^={HBC|2)B{_DM@@G+^Yi59WG5>1^hE>6XPb<37VK+N zF=uhF#N`W8eHD9Pwn$!u4Oz6yW{fr1Ya7onu3s=p)@-(jk@|I)v44*N$MnZWEF)3q oqZ@{ixNnak-mi;qgtW7w(0V8O)!?~u(T;2O9;;9;#t;Ai0M(S*Pyhe` literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/legacy/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts old mode 100755 new mode 100644 similarity index 88% rename from web/src/engine/websites/legacy/ComicValkyrie.ts rename to web/src/engine/websites/ComicValkyrie.ts index d70dc1532a..6cad8340ea --- a/web/src/engine/websites/legacy/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './ComicValkyrie.webp'; -import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(element: HTMLElement) { const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '').slice(1); diff --git a/web/src/engine/websites/legacy/ComicValkyrie.webp b/web/src/engine/websites/ComicValkyrie.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/ComicValkyrie.webp rename to web/src/engine/websites/ComicValkyrie.webp diff --git a/web/src/engine/websites/legacy/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts similarity index 83% rename from web/src/engine/websites/legacy/DigitalMargaret.ts rename to web/src/engine/websites/DigitalMargaret.ts index 0e09926e5a..b59b3392d1 100644 --- a/web/src/engine/websites/legacy/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './DigitalMargaret.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; diff --git a/web/src/engine/websites/legacy/DigitalMargaret.webp b/web/src/engine/websites/DigitalMargaret.webp similarity index 100% rename from web/src/engine/websites/legacy/DigitalMargaret.webp rename to web/src/engine/websites/DigitalMargaret.webp diff --git a/web/src/engine/websites/legacy/Futabanet.ts b/web/src/engine/websites/Futabanet.ts old mode 100755 new mode 100644 similarity index 85% rename from web/src/engine/websites/legacy/Futabanet.ts rename to web/src/engine/websites/Futabanet.ts index 32789d12b6..586a512f31 --- a/web/src/engine/websites/legacy/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -1,8 +1,8 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './Futabanet.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; const title = anchor.querySelector('.m-result-list__title').textContent.trim(); diff --git a/web/src/engine/websites/legacy/Futabanet.webp b/web/src/engine/websites/Futabanet.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/Futabanet.webp rename to web/src/engine/websites/Futabanet.webp diff --git a/web/src/engine/websites/legacy/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts similarity index 91% rename from web/src/engine/websites/legacy/MangaPlanet.ts rename to web/src/engine/websites/MangaPlanet.ts index 94efafb20f..a06998c553 100644 --- a/web/src/engine/websites/legacy/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './MangaPlanet.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest, FetchWindowScript } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest, FetchWindowScript } from '../FetchProvider'; function MangaExtractor(element: HTMLElement) { const id = element.querySelector('a').pathname; diff --git a/web/src/engine/websites/legacy/MangaPlanet.webp b/web/src/engine/websites/MangaPlanet.webp similarity index 100% rename from web/src/engine/websites/legacy/MangaPlanet.webp rename to web/src/engine/websites/MangaPlanet.webp diff --git a/web/src/engine/websites/legacy/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts old mode 100755 new mode 100644 similarity index 90% rename from web/src/engine/websites/legacy/Ohtabooks.ts rename to web/src/engine/websites/Ohtabooks.ts index b3f625b885..bf86431663 --- a/web/src/engine/websites/legacy/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './Ohtabooks.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; diff --git a/web/src/engine/websites/legacy/Ohtabooks.webp b/web/src/engine/websites/Ohtabooks.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/Ohtabooks.webp rename to web/src/engine/websites/Ohtabooks.webp diff --git a/web/src/engine/websites/legacy/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts old mode 100755 new mode 100644 similarity index 88% rename from web/src/engine/websites/legacy/OneTwoThreeHon.ts rename to web/src/engine/websites/OneTwoThreeHon.ts index da800dbab9..ef1a0026a3 --- a/web/src/engine/websites/legacy/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -1,9 +1,9 @@ -import { Tags } from '../../Tags'; +import { Tags } from '../Tags'; import icon from './OneTwoThreeHon.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../../providers/MangaPlugin'; -import * as Common from '../decorators/Common'; -import * as SpeedBinb from '../decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../../FetchProvider'; +import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { console.log(anchor.pathname); diff --git a/web/src/engine/websites/legacy/OneTwoThreeHon.webp b/web/src/engine/websites/OneTwoThreeHon.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/OneTwoThreeHon.webp rename to web/src/engine/websites/OneTwoThreeHon.webp diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 16ed692841..563d88c42a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -32,6 +32,7 @@ export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlackArmy } from './BlackArmy'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -40,8 +41,14 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; +export { default as ComicBrise } from './ComicBrise'; +export { default as ComicMeteor } from './ComicMeteor'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicsValley } from './ComicsValley'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComikeyArchive } from './ComikeyArchive'; export { default as CopyPasteScan } from './CopyPasteScan'; export { default as CrazyScans } from './CrazyScans'; @@ -52,6 +59,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -82,6 +90,7 @@ export { default as FreeManga } from './FreeManga'; export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GloryManga } from './GloryManga'; @@ -232,6 +241,7 @@ export { default as MangaMonarca } from './MangaMonarca'; export { default as MangaNel } from './MangaNel'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaProZ } from './MangaProZ'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; @@ -318,7 +328,9 @@ export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NovelMic } from './NovelMic'; export { default as NoxSubs } from './NoxSubs'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OniScans } from './OniScans'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; @@ -473,17 +485,14 @@ export { default as BatoScan } from './legacy/BatoScan'; export { default as Biamam } from './legacy/Biamam'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; export { default as CatManga } from './legacy/CatManga'; -export { default as Cmoa } from './legacy/Cmoa'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicAction } from './legacy/ComicAction'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBorder } from './legacy/ComicBorder'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicBushi } from './legacy/ComicBushi'; export { default as ComicClear } from './legacy/ComicClear'; @@ -495,13 +504,10 @@ export { default as ComicFX } from './legacy/ComicFX'; export { default as ComicGardo } from './legacy/ComicGardo'; export { default as ComicK } from './legacy/ComicK'; export { default as COMICMeDu } from './legacy/COMICMeDu'; -export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as Comico } from './legacy/Comico'; export { default as ComicoNovel } from './legacy/ComicoNovel'; -export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicRyu } from './legacy/ComicRyu'; export { default as ComicTrail } from './legacy/ComicTrail'; -export { default as ComicValkyrie } from './legacy/ComicValkyrie'; export { default as ComicVN } from './legacy/ComicVN'; export { default as ComicWalker } from './legacy/ComicWalker'; export { default as ComicZenon } from './legacy/ComicZenon'; @@ -514,7 +520,6 @@ export { default as DaumWebtoon } from './legacy/DaumWebtoon'; export { default as Daysneo } from './legacy/Daysneo'; export { default as Delitoon } from './legacy/Delitoon'; export { default as DelitoonDE } from './legacy/DelitoonDE'; -export { default as DigitalMargaret } from './legacy/DigitalMargaret'; export { default as Dmzj } from './legacy/Dmzj'; export { default as DokiFansubs } from './legacy/DokiFansubs'; export { default as DongManManhua } from './legacy/DongManManhua'; @@ -527,7 +532,6 @@ export { default as ForgottenScans } from './legacy/ForgottenScans'; export { default as FRScan } from './legacy/FRScan'; export { default as FudidoScanlator } from './legacy/FudidoScanlator'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GanGanOnline } from './legacy/GanGanOnline'; export { default as Ganma } from './legacy/Ganma'; @@ -679,7 +683,6 @@ export { default as MangaPanda } from './legacy/MangaPanda'; export { default as MangaPark } from './legacy/MangaPark'; export { default as MangaParkEN } from './legacy/MangaParkEN'; export { default as MangaParkToday } from './legacy/MangaParkToday'; -export { default as MangaPlanet } from './legacy/MangaPlanet'; export { default as MangaRaw } from './legacy/MangaRaw'; export { default as MangarawOnline } from './legacy/MangarawOnline'; export { default as MangaReader } from './legacy/MangaReader'; @@ -774,12 +777,10 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as OnePunchMan } from './legacy/OnePunchMan'; export { default as OneShotScans } from './legacy/OneShotScans'; export { default as OneTimeScans } from './legacy/OneTimeScans'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PelaTeam } from './legacy/PelaTeam'; export { default as Penlab } from './legacy/Penlab'; export { default as PervEden } from './legacy/PervEden'; From 9e302421bcaa6d90eae707016be4c84ddccd862f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 1 Oct 2023 14:56:27 +0200 Subject: [PATCH 06/88] add getsuaku --- web/src/engine/websites/Getsuaku.ts | 45 ++++++++++++++++++ web/src/engine/websites/Getsuaku.webp | Bin 0 -> 2418 bytes web/src/engine/websites/_index.ts | 1 + .../engine/websites/decorators/SpeedBinb.ts | 19 ++++---- 4 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 web/src/engine/websites/Getsuaku.ts create mode 100644 web/src/engine/websites/Getsuaku.webp diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts new file mode 100644 index 0000000000..2c62b315c1 --- /dev/null +++ b/web/src/engine/websites/Getsuaku.ts @@ -0,0 +1,45 @@ +import { Tags } from '../Tags'; +import icon from './Getsuaku.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchJSON, FetchRequest, FetchWindowScript } from '../FetchProvider'; + +type APIChapters = { + objects: { + id: number, + book_id: number, + title: string, + episode_number: string, + cid : string + }[] +} + +function MangaExtractor(element: HTMLElement) { + return { + id: element.querySelector('div.button a.button__link-dark').pathname, + title: element.querySelector('div.comics__name').textContent.trim() + }; +} + +@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/\S+\/$/, 'div.detail__main h2.detail__title') +@Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageDescrambler() +export default class extends DecoratableMangaScraper { + public constructor() { + super('getsuaku', `Getsuaku`, 'https://getsuaku.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override async FetchChapters(manga: Manga): Promise { + const bookid = await FetchWindowScript(new FetchRequest(new URL(manga.Identifier, this.URI).href), 'book_id', 1500); + const url = new URL(`/api/sort_episodes?book_id=${bookid}&order=asc&mode=all`, this.URI); + const chapters = await FetchJSON(new FetchRequest(url.href)); + return chapters.objects.map(chapter => new Chapter(this, manga, `/episode/${chapter.cid}`, chapter.episode_number.trim())); + } + +} \ No newline at end of file diff --git a/web/src/engine/websites/Getsuaku.webp b/web/src/engine/websites/Getsuaku.webp new file mode 100644 index 0000000000000000000000000000000000000000..977f97921ce684e9a27bc59ec5110e0f03ba650b GIT binary patch literal 2418 zcmaJ>dpy(YAD_yh94W~qx0!2VwlSA6D{Q&6+%G3Fvwdxo?Yp*Vi#p5E&8aBzqodJ5 z7nS_zB1Nc3Dff;=%Mm|XMTLkBzj2Pv?~nRDujhHap6Bzt-=EL>^L^g0Z;%gx5Wf-v z3CDW`gatT9tb#xwD-?^gI292n;s*%iqX9&uWE}&Efw(grG6`m;CcoS8@-`n(PoqOR z=zRYhqEXzi(~YO-Tf+9F^j@VQ%Zc7eS4m!b#+MADQQ`b%4Y)tG_EYVr8pJgjZta(6 z?P;4XJI|YsNk+{7d{y83Tu&(fpx;A`OCAK@l4kno#$?>p8v3kZTMKu?3zg|-!$C$F zsp2v+;_#@t$(pA34{$eGNzbeON)7r$9=j2&rQVf8Hg``}j>C79^~X#E&+yWRQ-Uwe zxt-T<<8HgBmp<*^OgWF0J0*KA%b&`!_bQcROb!!5cH@q<5B|8|4A58Vga0Pgm2+o@LNHs!0<0 zsEKR)&nbi5H$<`H<$u}WIdWwj5&GnC%Ld&0YQZtRBZ$CN6`O_D>b(i;lhi~;`2{s{3sG8RF73j~&vPar zTdspejXmdQTBp?O>t^hQTes`BK2?#eUn{*{yrShjWjX0`LBemiOqq*Z9Uw)6ad)HiKcrSP{WT~nMmE^)L|F{S3qSW>D`OHgT(ui2qAPk$x(`6Q z`^5OlQL<&VQ&C5&BL=x_#a^!kM(H z>BOwvx;p4G0au`U2}6&>*obo+ero9(*?!m^R@r#sO}EsbdO06wXmdRzOF6iP?8lrN z>tR2!)EzOB&bbYcE39`b{lcVG@HBAJ__;-%wQyEjR$uEM!=4EQ2e1;Q5_4mFN3s9tmKxXA2IRTHvnAXSjY+>!j2XEhTv_QW4$)4V70gGgqNiAIdMPv_kGF-$zJ z)-R5ldemTO+TVn!^KNZ2_Upcg#Sgi_uN4<2F*M~yswqd?!t@Q&g|`QHTZ$(LQ9OO< zaj4a=D$5=hm&{weR9ml+S6Z;~m>RK)xi@3~$Eq2Ncp-je$-N)U-}yLhYyYjgxjT%e zldf7*n4Vd5u90=qEUPi=r!HSjXJxQpnn&yMqY+kqe1I#vM>2iD+%ZNqj)p#57dn+u zxAFLp#pzj(Lq$Z(H@Ay^uJVY9NTIo=o~nz?h{}*Y#E9mbinnzhP%gKrhhI7DV67@y zr{vL{NHNcQkd?bp1{m&A7iJ}-XkL;^GIIMgC-cwHCS@3{6V;EG#c|B~yZ(%4*HRu2 zf@t3h;EiOJ;M{RZg0|8zprNj=sugh3>$%ZmNN^4|d|-Vj%ininTpSv=^AD0_WW$6^ z6gu5?Ym=$YnZ$={YTw-r48ZSV21Mt$-)YMZH3}x|?nda)#*ev6Db_`!Wv4$)+NTQr ztX;?0Duef(T8m4kNj>&JOgKGi!|rq?vyLmpNg`-Qr9R$FKY3pz&hI>}PVw(lj0j=? zRBJf|;)WBj$&_6H4;l;57%VL8!`)gKltIP9!qG$ok?jf48Qw`8AUJ7z2qkG3#f1vP zxkKFq7y*;b1bAeqfSJJJVgy(inF_`N7{z`eYzKobLU_Bduq_K0(1n7YAP0cDz!A0- z1Of?la)DD2D1<{SiVDQpKv4*ky&VFjn6^k12I+u7IY9p&FhxZUH4YQxMfkg(;)I3K zc|118&W_LL!}<1bkVCUWy12M3wZUY6P0QlK7h8f;K&G95%(g?q5escC0g1%_4`njHqPe^v;2*u;Ow0}0 z%LeR%04|uwp#TcF=|U+s#*+h(c_1eQ1QV9NWB?uHfm}MshN2wcXs8vDOkuDVA{!Se zL?XtA#pRJ%6u`#|3sWS4GZ<71($mug<$?Aj;J4tBNW7Pamy;s_>1@9Rjl?@RIwP03 zULYlr39xueTKOa9W8%x sso&DF$aO}1musgGW4G|O|MS*MA%%e!wqM<=IDGX#z*3l=qi{Fmzo{P|VgLXD literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 563d88c42a..a41ed54c73 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -93,6 +93,7 @@ export { default as FuryoSquad } from './FuryoSquad'; export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GogoManga } from './GogoManga'; export { default as GoldenMangas } from './GoldenMangas'; diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index d0d372808c..08280dcb16 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -82,6 +82,7 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, Referer: this.URI.href } });//referer needed for ManpaPlanet const data = await FetchCSS(request, 'div#content.pages'); + if (data.length == 0) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully const el = data[0]; if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { @@ -128,7 +129,7 @@ export function PagesSinglePage(baseUrl = '') { /** ************************* *** SpeedBinb v01.6061 *** -* ** Comic Meteor, Comic Valkyrie, ZeroSum, DigitalMargaRet, ComicBrise +* ** Comic Meteor, Comic Valkyrie, ZeroSum, DigitalMargaRet, ComicBrise, ComicRide ************************* */ async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: HTMLDivElement[], url: string, parent: Chapter): Promise { @@ -148,6 +149,7 @@ async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: ************************* *** SpeedBinb v01.6113 *** * ** Ohtabooks, Futabanet*** + * Getsuaku, which is v01.6700 ************************* */ async function getPageList_v016113(scraper: MangaScraper, chapterID: string, apiURL: string, baseURL: string, chapter: Chapter): Promise { @@ -180,7 +182,7 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl); configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl); //configuration.ServerType = parseInt(configuration.ServerType); - if (configuration['ServerType'] === 0) { + if (configuration.ServerType === 0) { return await getPageLinksSBC_v016452(scraper, configuration, params, baseURL, chapter); } return Promise.reject(new Error('Content server type not supported!')); @@ -231,10 +233,10 @@ async function getPageLinks_v016201(scraper : MangaScraper, configuration: Confi return Promise.reject(new Error('Content server type not supported!')); } async function _getPageLinksContent_v016201(scraper: MangaScraper, configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { - const uri = new URL(configuration['ContentsServer']); + const uri = new URL(configuration.ContentsServer); uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; uri.pathname += 'content'; - uri.searchParams.set('dmytime', configuration['ContentDate']); + uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('u1', u); const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); @@ -281,13 +283,13 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); //configuration.ServerType = parseInt(configuration.ServerType); - if (configuration['ServerType'] === 0) { //Booklive + if (configuration.ServerType === 0) { //Booklive return await getPageLinksSBC_v016130(scraper, configuration, baseURL, chapter); } - if (configuration['ServerType'] === 1) {//Futabanet + if (configuration.ServerType === 1) {//Futabanet return await getPageLinksContentJS_v016130(scraper, configuration, chapter); } - if (configuration['ServerType'] === 2) {//MangaPlanet + if (configuration.ServerType === 2) {//MangaPlanet return await getPageLinksContent_v016130(scraper, configuration, chapter); } return Promise.reject(new Error('Content server type not supported!')); @@ -392,10 +394,9 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si async function process_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { const data: JSONImageData_v016061 = await FetchJSON(new FetchRequest(page.Link.href)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); - const views = data.views; const imagedata: Blob = await Common.FetchImage.call(scraper, fakepage, priority, signal, detectMimeType); const bmpdata = await createImageBitmap(imagedata); - return await descramble_v016061(bmpdata, views); + return await descramble_v016061(bmpdata, data.views); } async function descramble_v016061(bitmap: ImageBitmap, views: PageView_v016061[]): Promise { From bc2ed43c0835606faa04a061a0070eaf5ae37277 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 1 Oct 2023 15:07:45 +0200 Subject: [PATCH 07/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 63187656c2..b4b3b9d40d 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -27,6 +27,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -35,8 +36,14 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; +export { default as ComicBrise } from './ComicBrise'; +export { default as ComicMeteor } from './ComicMeteor'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicsValley } from './ComicsValley'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComikeyArchive } from './ComikeyArchive'; export { default as CopyPasteScan } from './CopyPasteScan'; export { default as CrazyScans } from './CrazyScans'; @@ -47,6 +54,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -75,8 +83,10 @@ export { default as FreeManga } from './FreeManga'; export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GoldenMangas } from './GoldenMangas'; export { default as GolDragon } from './GolDragon'; @@ -207,6 +217,7 @@ export { default as MangaMonarca } from './MangaMonarca'; export { default as MangaNel } from './MangaNel'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaRockTeam } from './MangaRockTeam'; @@ -283,7 +294,9 @@ export { default as NijiTranslations } from './NijiTranslations'; export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -434,7 +447,6 @@ export { default as BatoScan } from './legacy/BatoScan'; export { default as Biamam } from './legacy/Biamam'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; @@ -443,7 +455,6 @@ export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicAction } from './legacy/ComicAction'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBorder } from './legacy/ComicBorder'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicBushi } from './legacy/ComicBushi'; export { default as ComicClear } from './legacy/ComicClear'; @@ -455,13 +466,10 @@ export { default as ComicFX } from './legacy/ComicFX'; export { default as ComicGardo } from './legacy/ComicGardo'; export { default as ComicK } from './legacy/ComicK'; export { default as COMICMeDu } from './legacy/COMICMeDu'; -export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as Comico } from './legacy/Comico'; export { default as ComicoNovel } from './legacy/ComicoNovel'; -export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicRyu } from './legacy/ComicRyu'; export { default as ComicTrail } from './legacy/ComicTrail'; -export { default as ComicValkyrie } from './legacy/ComicValkyrie'; export { default as ComicVN } from './legacy/ComicVN'; export { default as ComicWalker } from './legacy/ComicWalker'; export { default as ComicZenon } from './legacy/ComicZenon'; @@ -486,7 +494,6 @@ export { default as ForgottenScans } from './legacy/ForgottenScans'; export { default as FRScan } from './legacy/FRScan'; export { default as FudidoScanlator } from './legacy/FudidoScanlator'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GanGanOnline } from './legacy/GanGanOnline'; export { default as Ganma } from './legacy/Ganma'; @@ -729,12 +736,10 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as OnePunchMan } from './legacy/OnePunchMan'; export { default as OneShotScans } from './legacy/OneShotScans'; export { default as OneTimeScans } from './legacy/OneTimeScans'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PelaTeam } from './legacy/PelaTeam'; export { default as Penlab } from './legacy/Penlab'; export { default as PervEden } from './legacy/PervEden'; From c64a616ed35b5480c5a569933547ee17d6faa705 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 4 Oct 2023 10:30:47 +0200 Subject: [PATCH 08/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index b6f723fc1c..380176014b 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -27,6 +27,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -35,8 +36,14 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; +export { default as ComicBrise } from './ComicBrise'; +export { default as ComicMeteor } from './ComicMeteor'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicsValley } from './ComicsValley'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZerosum } from './ComicZerosum'; export { default as ComikeyArchive } from './ComikeyArchive'; export { default as CopyPasteScan } from './CopyPasteScan'; @@ -48,6 +55,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -76,8 +84,10 @@ export { default as FreeManga } from './FreeManga'; export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GoldenMangas } from './GoldenMangas'; export { default as GolDragon } from './GolDragon'; @@ -208,6 +218,7 @@ export { default as MangaMonarca } from './MangaMonarca'; export { default as MangaNel } from './MangaNel'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaRockTeam } from './MangaRockTeam'; @@ -284,7 +295,9 @@ export { default as NijiTranslations } from './NijiTranslations'; export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -436,7 +449,6 @@ export { default as BatoScan } from './legacy/BatoScan'; export { default as Biamam } from './legacy/Biamam'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; @@ -445,7 +457,6 @@ export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicAction } from './legacy/ComicAction'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBorder } from './legacy/ComicBorder'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicBushi } from './legacy/ComicBushi'; export { default as ComicClear } from './legacy/ComicClear'; @@ -457,13 +468,10 @@ export { default as ComicFX } from './legacy/ComicFX'; export { default as ComicGardo } from './legacy/ComicGardo'; export { default as ComicK } from './legacy/ComicK'; export { default as COMICMeDu } from './legacy/COMICMeDu'; -export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as Comico } from './legacy/Comico'; export { default as ComicoNovel } from './legacy/ComicoNovel'; -export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicRyu } from './legacy/ComicRyu'; export { default as ComicTrail } from './legacy/ComicTrail'; -export { default as ComicValkyrie } from './legacy/ComicValkyrie'; export { default as ComicVN } from './legacy/ComicVN'; export { default as ComicWalker } from './legacy/ComicWalker'; export { default as ComicZenon } from './legacy/ComicZenon'; @@ -487,7 +495,6 @@ export { default as ForgottenScans } from './legacy/ForgottenScans'; export { default as FRScan } from './legacy/FRScan'; export { default as FudidoScanlator } from './legacy/FudidoScanlator'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GanGanOnline } from './legacy/GanGanOnline'; export { default as Ganma } from './legacy/Ganma'; @@ -730,12 +737,10 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as OnePunchMan } from './legacy/OnePunchMan'; export { default as OneShotScans } from './legacy/OneShotScans'; export { default as OneTimeScans } from './legacy/OneTimeScans'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PelaTeam } from './legacy/PelaTeam'; export { default as Penlab } from './legacy/Penlab'; export { default as PervEden } from './legacy/PervEden'; From d7e3da02b5beefed0cf709583dcdbdc7c2feacf2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 4 Oct 2023 11:31:26 +0200 Subject: [PATCH 09/88] fix calls --- web/src/engine/websites/decorators/SpeedBinb.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 08280dcb16..3ec6778635 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -394,7 +394,7 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si async function process_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { const data: JSONImageData_v016061 = await FetchJSON(new FetchRequest(page.Link.href)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); - const imagedata: Blob = await Common.FetchImage.call(scraper, fakepage, priority, signal, detectMimeType); + const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); const bmpdata = await createImageBitmap(imagedata); return await descramble_v016061(bmpdata, data.views); } @@ -425,7 +425,7 @@ async function descramble_v016061(bitmap: ImageBitmap, views: PageView_v016061[] } async function process_v016130(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType: boolean): Promise { - const imagedata: Blob = await Common.FetchImage.call(scraper, page, priority, signal, detectMimeType); + const imagedata: Blob = await Common.FetchImageAjax.call(scraper, page, priority, signal, detectMimeType); const descrambleKeyPair: DescrambleKP = JSON.parse(window.atob(page.Link.hash.slice(1))); const bmpdata = await createImageBitmap(imagedata); return await descramble_v016130(bmpdata, descrambleKeyPair); From edcf4c2767e28dc6862e2cbe43a09109d794902d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 5 Oct 2023 14:12:38 +0200 Subject: [PATCH 10/88] speedbinb : small fixes and create tests --- web/src/engine/websites/BookLive.ts | 2 +- web/src/engine/websites/BookLive_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/Cmoa.ts | 8 ++---- web/src/engine/websites/Cmoa_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/ComicBrise.ts | 4 +-- web/src/engine/websites/ComicBrise_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/ComicMeteor.ts | 4 +-- web/src/engine/websites/ComicMeteor_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/ComicPolaris.ts | 2 +- web/src/engine/websites/ComicPolaris_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/ComicRide_e2e.ts | 26 ++++++++++++++++++ web/src/engine/websites/ComicValkyrie.ts | 12 ++++----- web/src/engine/websites/ComicValkyrie_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/DigitalMargaret.ts | 2 +- .../engine/websites/DigitalMargaret_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/Futabanet.ts | 2 +- web/src/engine/websites/Futabanet_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/Getsuaku.ts | 4 +-- web/src/engine/websites/Getsuaku_e2e.ts | 26 ++++++++++++++++++ web/src/engine/websites/MangaPlanet.ts | 2 +- web/src/engine/websites/MangaPlanet_e2e.ts | 25 +++++++++++++++++ web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/Ohtabooks_e2e.ts | 27 +++++++++++++++++++ web/src/engine/websites/OneTwoThreeHon.ts | 6 ++--- web/src/engine/websites/OneTwoThreeHon_e2e.ts | 25 +++++++++++++++++ .../engine/websites/decorators/SpeedBinb.ts | 2 +- 27 files changed, 354 insertions(+), 29 deletions(-) create mode 100644 web/src/engine/websites/BookLive_e2e.ts create mode 100644 web/src/engine/websites/Cmoa_e2e.ts create mode 100644 web/src/engine/websites/ComicBrise_e2e.ts create mode 100644 web/src/engine/websites/ComicMeteor_e2e.ts create mode 100644 web/src/engine/websites/ComicPolaris_e2e.ts create mode 100644 web/src/engine/websites/ComicRide_e2e.ts create mode 100644 web/src/engine/websites/ComicValkyrie_e2e.ts create mode 100644 web/src/engine/websites/DigitalMargaret_e2e.ts create mode 100644 web/src/engine/websites/Futabanet_e2e.ts create mode 100644 web/src/engine/websites/Getsuaku_e2e.ts create mode 100644 web/src/engine/websites/MangaPlanet_e2e.ts create mode 100644 web/src/engine/websites/Ohtabooks_e2e.ts create mode 100644 web/src/engine/websites/OneTwoThreeHon_e2e.ts diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index 0265d80f1c..7b44441a64 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -13,7 +13,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts new file mode 100644 index 0000000000..a34f364c1b --- /dev/null +++ b/web/src/engine/websites/BookLive_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'booklive', + title: 'BookLive' + }, + container: { + url: 'https://booklive.jp/product/index/title_id/20063601/vol_no/001', + id: '/product/index/title_id/20063601/vol_no/001', + title: '火の神さまの掃除人ですが、いつの間にか花嫁として溺愛されています【単話】 1' + }, + child: { + id: '/bviewer/s/?cid=60095158_001', + title: '001' + }, + entry: { + index: 0, + size: 2_200_103, + 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/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 3a5e8456b4..9a8784ba73 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -4,15 +4,11 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -function MangaLabelExtractor(body: HTMLBodyElement) { - const title = body.querySelector('#GA_this_page_title_name').textContent.trim(); - return title; -} -@Common.MangaCSS(/^https?:\/\/www\.cmoa\.jp\/title\/\d+\/$/, 'body', MangaLabelExtractor) +@Common.MangaCSS(/^https?:\/\/www\.cmoa\.jp\/title\/\d+\/(vol\/\d+\/)?$/, '#GA_this_page_title_name') @Common.MangasNotSupported() @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('cmoa', `コミックシーモア (Cmoa)`, 'https://www.cmoa.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts new file mode 100644 index 0000000000..2d42023204 --- /dev/null +++ b/web/src/engine/websites/Cmoa_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'cmoa', + title: 'コミックシーモア (Cmoa)' + }, + container: { + url: 'https://www.cmoa.jp/title/151961/vol/24/', + id: '/title/151961/vol/24/', + title: '呪術廻戦' + }, + child: { + id: '/bib/speedreader/?cid=0000151961_jp_0021&u0=1&u1=0', + title: '呪術廻戦 21' + }, + entry: { + index: 0, + size: 2_861_208, + 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/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index 0288612403..b83677d932 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -8,7 +8,7 @@ import { FetchCSS, FetchRequest } from '../FetchProvider'; @Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/\S+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('comicbrise', `Comic-Brise`, 'https://www.comic-brise.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); @@ -23,7 +23,7 @@ export default class extends DecoratableMangaScraper { const request = new FetchRequest(uri.href); const data = await FetchCSS(request, '.modal.modal-chapter .modal-body'); return data.reverse() - .filter(e => e.querySelector(".banner-trial img").getAttribute("alt") == "FREE") + //.filter(e => e.querySelector(".banner-trial img").getAttribute("alt") == "FREE") //dont filter for free chapter .map(element => new Chapter(this, manga, element.querySelector('.banner-trial a').pathname, element.querySelector('.primary-title').textContent.trim())); } } \ No newline at end of file diff --git a/web/src/engine/websites/ComicBrise_e2e.ts b/web/src/engine/websites/ComicBrise_e2e.ts new file mode 100644 index 0000000000..934ce8b26c --- /dev/null +++ b/web/src/engine/websites/ComicBrise_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'comicbrise', + title: 'Comic-Brise' + }, + container: { + url: 'https://www.comic-brise.com/contents/mobu/', + id: '/contents/mobu/', + title: 'モブ顔令嬢~乙女ゲー世界の悪役令嬢に転生したのにどうしてこうなった~' + }, + child: { + id: '/comic_ep/mobu_ep1', + title: '第1話' + }, + entry: { + index: 0, + size: 4_580_541, + 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/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index 2694e49d03..d435229b23 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -14,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/\S+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('comicmeteor', `COMICメテオ (COMIC Meteor)`, 'https://comic-meteor.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); @@ -27,7 +27,7 @@ export default class extends DecoratableMangaScraper { const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); const contents = await FetchCSS(request, 'div#contents'); const data = contents[0]; - let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a')] + let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn.work_episode_link_orange a')] .map(element => new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim())); if (chapterList.length == 0) { chapterList = [...data.querySelectorAll('div.latest_info_box div.latest_info_link_btn01 a')] diff --git a/web/src/engine/websites/ComicMeteor_e2e.ts b/web/src/engine/websites/ComicMeteor_e2e.ts new file mode 100644 index 0000000000..c029f5b584 --- /dev/null +++ b/web/src/engine/websites/ComicMeteor_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'comicmeteor', + title: 'COMICメテオ (COMIC Meteor)' + }, + container: { + url: 'https://comic-meteor.jp/isekaiseihukuki/', + id: '/isekaiseihukuki/', + title: '異世界征服記~不遇種族たちの最強国家~' + }, + child: { + id: '/ptdata/isekaiseihukuki/0001/', + title: '第1話' + }, + entry: { + index: 0, + size: 3_838_458, + 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/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 5969fdd269..42e7539706 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -14,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/comic-polaris\.jp\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPolaris_e2e.ts b/web/src/engine/websites/ComicPolaris_e2e.ts new file mode 100644 index 0000000000..f25ec24f6d --- /dev/null +++ b/web/src/engine/websites/ComicPolaris_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'comicpolaris', + title: 'COMICポラリス (COMIC Polaris)' + }, + container: { + url: 'https://comic-polaris.jp/ekidemita/', + id: '/ekidemita/', + title: '今日、駅で見た可愛い女の子。' + }, + child: { + id: '/ptdata/ekidemita/0001/', + title: '第1話' + }, + entry: { + index: 0, + size: 1_854_679, + 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 fa49d3abc9..89fd6f703b 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -21,7 +21,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/', 'ul li.p-update-list__item', MangaExtractor) @Common.ChaptersSinglePageCSS('article.p-modal-org', ChapterExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('comicride', `ComicRide`, 'https://www.comicride.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts new file mode 100644 index 0000000000..704140fb17 --- /dev/null +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'comicride', + title: 'ComicRide', + timeout : 45000 + }, + container: { + url: 'https://www.comicride.jp/book/kamihatsu/', + id: '/book/kamihatsu/', + title: '神の遣いの少女は初恋の将軍にすべてを捧ぐ' + }, + child: { + id: '/viewer/kamihatsu/kamihatsu_001/', + title: '-第1話-' + }, + entry: { + index: 0, + size: 2_549_444, + 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/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 6cad8340ea..08eb7f1ceb 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -6,13 +6,13 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(element: HTMLElement) { - const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '').slice(1); + const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', ''); const title = element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim(); return { id, title }; } function ChapterExtractor(element: HTMLElement) { - const a: HTMLAnchorElement = element.parentElement.querySelector('a.read_bt'); - const id = a.href; + const a = element.parentElement.querySelector('a.read_bt'); + const id = a.pathname; const title = element.textContent.trim(); return { id, title }; } @@ -20,7 +20,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('comicvalkyrie', `Comic Valkyrie`, 'https://www.comic-valkyrie.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); @@ -30,14 +30,14 @@ export default class extends DecoratableMangaScraper { } public override ValidateMangaURL(url: string): boolean { - return /^https?:\/\/www\.comic-valkyrie\.com\/\S+\/new.html$/.test(url); + return /^https?:\/\/www\.comic-valkyrie\.com\/\S+(\/|\/new.html)?$/.test(url); } public override async FetchManga(provider: MangaPlugin, url: string): Promise { const uri = new URL(url); const request = new FetchRequest(uri.href); const data = await FetchCSS(request, 'meta[property = "og:title"]'); - const id = uri.pathname.replace('/new.html', '').slice(1); + const id = uri.pathname.replace('/new.html', ''); const title = data[0].content.replace(/\s*THE COMIC\s*/i, '').trim(); return new Manga(this, provider, id, title); } diff --git a/web/src/engine/websites/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts new file mode 100644 index 0000000000..58ee4461bd --- /dev/null +++ b/web/src/engine/websites/ComicValkyrie_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'comicvalkyrie', + title: 'Comic Valkyrie' + }, + container: { + url: 'https://www.comic-valkyrie.com/teisou/', + id: '/teisou/', + title: '貞操逆転世界' + }, + child: { + id: '/samplebook/val_teisou01/', + title: '第1話' + }, + entry: { + index: 0, + size: 1_233_245, + 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/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index b59b3392d1..68a83752e9 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -19,7 +19,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number',ChapterExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/DigitalMargaret_e2e.ts b/web/src/engine/websites/DigitalMargaret_e2e.ts new file mode 100644 index 0000000000..a7da6f1277 --- /dev/null +++ b/web/src/engine/websites/DigitalMargaret_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'digitalmargaret', + title: 'デジタルマーガレット (Digital Margaret)' + }, + container: { + url: 'https://digitalmargaret.jp/detail/sakuranoyouna/', + id: '/detail/sakuranoyouna/', + title: '桜のような僕の恋人' + }, + child: { + id: '/contents/sakuranoyouna/230101_1-1Tx3bCnGJ', + title: '第1-1話' + }, + entry: { + index: 0, + size: 964_808, + 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/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 586a512f31..036cb3cdab 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -18,7 +18,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) @SpeedBinb.PagesSinglePage('https://reader.futabanet.jp') -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts new file mode 100644 index 0000000000..be88ed456e --- /dev/null +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'futabanet', + title: 'がうがうモンスター (Futabanet Monster)' + }, + container: { + url: 'https://gaugau.futabanet.jp/list/work/62591706776561c83f010000', + id: '/list/work/62591706776561c83f010000', + title: 'ポイントギフター《経験値分配能力者》の異世界最強ソロライフ~ブラックギルドから解放された男は万能最強職として無双する~' + }, + child: { + id: 'https://reader.futabanet.jp/62591706776561c83f010000_001-001_1?wurl=https%3A%2F%2Fgaugau.futabanet.jp%2Flist%2Fwork%2F62591706776561c83f010000', + title: '第1話(1)' + }, + entry: { + index: 0, + size: 1_850_824, + 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/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index 2c62b315c1..f66e02f58b 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -22,10 +22,10 @@ function MangaExtractor(element: HTMLElement) { }; } -@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/\S+\/$/, 'div.detail__main h2.detail__title') +@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/\S+$/, 'div.detail__main h2.detail__title') @Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { super('getsuaku', `Getsuaku`, 'https://getsuaku.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); diff --git a/web/src/engine/websites/Getsuaku_e2e.ts b/web/src/engine/websites/Getsuaku_e2e.ts new file mode 100644 index 0000000000..a86f037dc7 --- /dev/null +++ b/web/src/engine/websites/Getsuaku_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'getsuaku', + title: 'Getsuaku' + }, + container: { + url: 'https://getsuaku.com/episode/001_gaw_maidragon', + id: '/episode/001_gaw_maidragon', + title: '小林さんちのメイドラゴン', + timeout : 15000 + }, + child: { + id: '/episode/001_gaw_maidragon', + title: '第1話' + }, + entry: { + index: 0, + size: 1_428_394, + 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/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index a06998c553..ae983e5114 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -14,7 +14,7 @@ function MangaExtractor(element: HTMLElement) { @Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/\S+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list',1,1,0, MangaExtractor) @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/MangaPlanet_e2e.ts b/web/src/engine/websites/MangaPlanet_e2e.ts new file mode 100644 index 0000000000..32523bc058 --- /dev/null +++ b/web/src/engine/websites/MangaPlanet_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'mangaplanet', + title: 'MangaPlanet' + }, + container: { + url: 'https://mangaplanet.com/comic/64eeceb86e1e3', + id: '/comic/64eeceb86e1e3', + title: 'Concerned About My Virginity: I Wanna Give It to My Boss!', + }, + child: { + id: '/reader?cid=64f300af38575&sk=1', + title: 'Volume 1 - Free Preview' + }, + entry: { + index: 0, + size: 1_688_910, + 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/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index bf86431663..57aec7434d 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -13,7 +13,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/\S+\/$/, 'h2.contentTitle') @Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/Ohtabooks_e2e.ts b/web/src/engine/websites/Ohtabooks_e2e.ts new file mode 100644 index 0000000000..82ecdfbf53 --- /dev/null +++ b/web/src/engine/websites/Ohtabooks_e2e.ts @@ -0,0 +1,27 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'ohtabooks', + title: 'Ohtabooks' + }, + container: { + url: 'https://webcomic.ohtabooks.com/kumazo/', + id: '/kumazo/', + title: 'クマ蔵とゲームなご主人', + }, + child: { + id: 'https://yondemill.jp/contents/55155?view=1&u0=1', + title: '第1話「ご主人とゲーム」' + },/* + //since page id redirect to another url, test is failing despites us getting images + //https://yondemill.jp/contents/55155?view=1&u0=1' redirect to https://binb.bricks.pub/contents/b0baf48e-9a1e-4ac7-b331-f4b978714dc7_1673856049/speed_reader + entry: { + index: 0, + size: 1_385_998, + 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/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index ef1a0026a3..f4543ebc3f 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -14,7 +14,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[\S]+\/web-comic\/[\S]+\/$/, 'div.title-area h2') @SpeedBinb.PagesSinglePage() -@SpeedBinb.ImageDescrambler() +@SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -40,8 +40,8 @@ export default class extends DecoratableMangaScraper { const data = await FetchCSS(request, 'div.read-episode li'); return data.map(element => { if (element.querySelector('a')) { // otherwise chapter not available - return new Chapter(this, manga, new URL(element.querySelector('a').href.replace(/index.html$/, ''), this.URI).href, element.innerText.match(/\s*(.*?)\s+/)[1]); + return new Chapter(this, manga, new URL(element.querySelector('a').pathname.replace(/index.html$/, ''), this.URI).pathname, element.innerText.match(/\s*(.*?)\s+/)[1]); } - }).filter(element => element !== undefined).filter(element => !/#comics-store/.test(element.Identifier)); + }).filter(element => element !== undefined).filter(element => element.Identifier != '/'); } } \ No newline at end of file diff --git a/web/src/engine/websites/OneTwoThreeHon_e2e.ts b/web/src/engine/websites/OneTwoThreeHon_e2e.ts new file mode 100644 index 0000000000..b25a8322a2 --- /dev/null +++ b/web/src/engine/websites/OneTwoThreeHon_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'onetwothreehon', + title: '123hon' + }, + container: { + url: 'https://www.123hon.com/polca/web-comic/spxsp/', + id: '/polca/web-comic/spxsp/', + title: '異世界温泉冒険譚~スプラッシュ×スプラッシュ~', + }, + child: { + id: '/vw/spxsp/sv_pt000644b1883c326d_1a/', + title: '第1話(1/2)' + }, + entry: { + index: 0, + size: 1_457_423, + 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/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 3ec6778635..eae5cbeecc 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -458,7 +458,7 @@ async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Prom * 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 ImageDescrambler(detectMimeType = false) { +export function ImageAjax(detectMimeType = false) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { if (context && context.kind !== 'class') { throw new Error(context.name); From 0c68ea22388c9ae3bd44dd54f72809697a0f272f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Oct 2023 13:38:05 +0200 Subject: [PATCH 11/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 452a67815a..f28e6634be 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -28,6 +28,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -36,15 +37,21 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicBushi } from './ComicBushi'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicK } from './ComicK'; +export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as ComikeyArchive } from './ComikeyArchive'; @@ -57,6 +64,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -85,8 +93,10 @@ export { default as FreeManga } from './FreeManga'; export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GoldenMangas } from './GoldenMangas'; export { default as GolDragon } from './GolDragon'; @@ -225,6 +235,7 @@ export { default as MangaNel } from './MangaNel'; export { default as MangaNexus } from './MangaNexus'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaRockTeam } from './MangaRockTeam'; @@ -303,7 +314,9 @@ export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -461,14 +474,12 @@ export { default as BatoScan } from './legacy/BatoScan'; export { default as Biamam } from './legacy/Biamam'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; export { default as CatManga } from './legacy/CatManga'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicBoost } from './legacy/ComicBoost'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicClear } from './legacy/ComicClear'; export { default as ComicDays } from './legacy/ComicDays'; @@ -477,11 +488,8 @@ export { default as ComicExtra } from './legacy/ComicExtra'; export { default as ComicFire } from './legacy/ComicFire'; export { default as ComicFX } from './legacy/ComicFX'; export { default as COMICMeDu } from './legacy/COMICMeDu'; -export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicoNovel } from './legacy/ComicoNovel'; -export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicRyu } from './legacy/ComicRyu'; -export { default as ComicValkyrie } from './legacy/ComicValkyrie'; export { default as ComicVN } from './legacy/ComicVN'; export { default as ComicWalker } from './legacy/ComicWalker'; export { default as CopyToon } from './legacy/CopyToon'; @@ -504,7 +512,6 @@ export { default as ForgottenScans } from './legacy/ForgottenScans'; export { default as FRScan } from './legacy/FRScan'; export { default as FudidoScanlator } from './legacy/FudidoScanlator'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GanGanOnline } from './legacy/GanGanOnline'; export { default as Ganma } from './legacy/Ganma'; @@ -738,12 +745,10 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as OnePunchMan } from './legacy/OnePunchMan'; export { default as OneShotScans } from './legacy/OneShotScans'; export { default as OneTimeScans } from './legacy/OneTimeScans'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PelaTeam } from './legacy/PelaTeam'; export { default as Penlab } from './legacy/Penlab'; export { default as PervEden } from './legacy/PervEden'; From 0afeeaef143cc85e35ed4d5ce6c369b3b16fe30b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Oct 2023 13:45:22 +0200 Subject: [PATCH 12/88] fix spacing and use new error in decorator --- web/src/engine/websites/ComicRide_e2e.ts | 2 +- web/src/engine/websites/DigitalMargaret.ts | 2 +- web/src/engine/websites/Getsuaku_e2e.ts | 2 +- web/src/engine/websites/MangaPlanet.ts | 2 +- web/src/engine/websites/Ohtabooks_e2e.ts | 2 +- .../engine/websites/decorators/SpeedBinb.ts | 60 +++++++++---------- 6 files changed, 34 insertions(+), 36 deletions(-) diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index 704140fb17..97fb745433 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -4,7 +4,7 @@ const config: Config = { plugin: { id: 'comicride', title: 'ComicRide', - timeout : 45000 + timeout: 45000 }, container: { url: 'https://www.comicride.jp/book/kamihatsu/', diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 68a83752e9..4e5081a33c 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -17,7 +17,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/\S+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) -@Common.ChaptersSinglePageCSS('section#product div.list div.box div.number',ChapterExtractor) +@Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/Getsuaku_e2e.ts b/web/src/engine/websites/Getsuaku_e2e.ts index a86f037dc7..1055cfe3d7 100644 --- a/web/src/engine/websites/Getsuaku_e2e.ts +++ b/web/src/engine/websites/Getsuaku_e2e.ts @@ -9,7 +9,7 @@ const config: Config = { url: 'https://getsuaku.com/episode/001_gaw_maidragon', id: '/episode/001_gaw_maidragon', title: '小林さんちのメイドラゴン', - timeout : 15000 + timeout: 15000 }, child: { id: '/episode/001_gaw_maidragon', diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index ae983e5114..583ef1181e 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -12,7 +12,7 @@ function MangaExtractor(element: HTMLElement) { } @Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/\S+$/, '.card-body.book-detail h3') -@Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list',1,1,0, MangaExtractor) +@Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/Ohtabooks_e2e.ts b/web/src/engine/websites/Ohtabooks_e2e.ts index 82ecdfbf53..b2d068ab45 100644 --- a/web/src/engine/websites/Ohtabooks_e2e.ts +++ b/web/src/engine/websites/Ohtabooks_e2e.ts @@ -13,7 +13,7 @@ const config: Config = { child: { id: 'https://yondemill.jp/contents/55155?view=1&u0=1', title: '第1話「ご主人とゲーム」' - },/* + }, /* //since page id redirect to another url, test is failing despites us getting images //https://yondemill.jp/contents/55155?view=1&u0=1' redirect to https://binb.bricks.pub/contents/b0baf48e-9a1e-4ac7-b331-f4b978714dc7_1673856049/speed_reader entry: { diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index eae5cbeecc..22e8b28c9e 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -115,9 +115,8 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, */ export function PagesSinglePage(baseUrl = '') { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - if (context && context.kind !== 'class') { - throw new Error(context.name); - } + Common.ThrowOnUnsupportedDecoratorContext(context); + return class extends ctor { public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { return FetchPagesSinglePage.call(this, chapter, baseUrl); @@ -207,7 +206,7 @@ async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Co ************************* */ -async function getPageList_v016201(scraper: MangaScraper,chapter: Chapter, apiURL: string, baseURL: string): Promise { +async function getPageList_v016201(scraper: MangaScraper, chapter: Chapter, apiURL: string, baseURL: string): Promise { const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); const u = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); const sharingKey = _tt(cid); @@ -460,9 +459,8 @@ async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Prom */ export function ImageAjax(detectMimeType = false) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - if (context && context.kind !== 'class') { - throw new Error(context.name); - } + Common.ThrowOnUnsupportedDecoratorContext(context); + return class extends ctor { public async FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal): Promise { return FetchImage.call(this, page, priority, signal, detectMimeType); @@ -575,8 +573,8 @@ function _lt_002(s, u) { const _speedbinb_f = function () { function s(t, i) { this.Mt = null; - const n = t.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/) - , r = i.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/); + const n = t.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/), + r = i.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/); if (null !== n && null !== r && n[1] === r[1] && n[2] === r[2] && n[4] === r[4] && "+" === n[3] && "-" === r[3] && (this.C = parseInt(n[1], 10), this.I = parseInt(n[2], 10), @@ -584,8 +582,8 @@ const _speedbinb_f = function () { !(8 < this.C || 8 < this.I || 64 < this.C * this.I))) { const e = this.C + this.I + this.C * this.I; if (n[5].length === e && r[5].length === e) { - const s = this.yt(n[5]) - , u = this.yt(r[5]); + const s = this.yt(n[5]), + u = this.yt(r[5]); this.xt = s.n, this.Et = s.t, this.It = u.n, @@ -601,8 +599,8 @@ const _speedbinb_f = function () { } , s.prototype.bt = function (t) { - const i = 2 * this.C * this.jt - , n = 2 * this.I * this.jt; + const i = 2 * this.C * this.jt, + n = 2 * this.I * this.jt; return t.width >= 64 + i && t.height >= 64 + n && t.width * t.height >= (320 + i) * (320 + n); } , @@ -635,16 +633,16 @@ const _speedbinb_f = function () { u = n - (this.I - 1) * s; for (let o = 0; o < this.C * this.I; ++o) { - const a = o % this.C - , f = Math.floor(o / this.C) - , c = this.jt + a * (r + 2 * this.jt) + (this.It[f] < a ? e - r : 0) - , l = this.jt + f * (s + 2 * this.jt) + (this.St[a] < f ? u - s : 0) - , v = this.Mt[o] % this.C - , d = Math.floor(this.Mt[o] / this.C) - , g = v * r + (this.xt[d] < v ? e - r : 0) - , p = d * s + (this.Et[v] < d ? u - s : 0) - , b = this.It[f] === a ? e : r - , m = this.St[a] === f ? u : s; + const a = o % this.C, + f = Math.floor(o / this.C), + c = this.jt + a * (r + 2 * this.jt) + (this.It[f] < a ? e - r : 0), + l = this.jt + f * (s + 2 * this.jt) + (this.St[a] < f ? u - s : 0), + v = this.Mt[o] % this.C, + d = Math.floor(this.Mt[o] / this.C), + g = v * r + (this.xt[d] < v ? e - r : 0), + p = d * s + (this.Et[v] < d ? u - s : 0), + b = this.It[f] === a ? e : r, + m = this.St[a] === f ? u : s; 0 < i && 0 < n && h.push({ xsrc: c, ysrc: l, @@ -723,8 +721,8 @@ const _speedbinb_a = function () { ydest: 0 }]; for (let a = 0; a < o; a++) { - const f = this.mt.piece[a] - , c = this.wt.piece[a]; + const f = this.mt.piece[a], + c = this.wt.piece[a]; i.push({ xsrc: Math.floor(f.x / 2) * r + f.x % 2 * e, ysrc: Math.floor(f.y / 2) * u + f.y % 2 * h, @@ -734,8 +732,8 @@ const _speedbinb_a = function () { ydest: Math.floor(c.y / 2) * u + c.y % 2 * h }); } - const l = r * (this.mt.ndx - 1) + e - , v = u * (this.mt.ndy - 1) + h; + const l = r * (this.mt.ndx - 1) + e, + v = u * (this.mt.ndy - 1) + h; return l < t.width && i.push({ xsrc: l, ysrc: 0, @@ -761,9 +759,9 @@ const _speedbinb_a = function () { const i = t.split("-"); if (3 != i.length) return null; - const n = parseInt(i[0], 10) - , r = parseInt(i[1], 10) - , e = i[2]; + const n = parseInt(i[0], 10), + r = parseInt(i[1], 10), + e = i[2]; if (e.length != n * r * 2) return null; const v = []; @@ -775,7 +773,7 @@ const _speedbinb_a = function () { for (let s, u, h, o, d = 0;d < n * r;d++) s = this.Ot(e.charAt(2 * d)), u = this.Ot(e.charAt(2 * d + 1)), - d <= a ? o = h = 2 : d <= f ? (h = 2,o = 1) : d <= c ? (h = 1,o = 2) : d <= l && (o = h = 1), + d <= a ? o = h = 2 : d <= f ? (h = 2, o = 1) : d <= c ? (h = 1, o = 2) : d <= l && (o = h = 1), v.push({ x: s, y: u, From f7a8e5c20ca5a452248139119effb3a39b2124e6 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 21 Oct 2023 15:25:45 +0200 Subject: [PATCH 13/88] use quality from settings --- web/src/engine/websites/decorators/SpeedBinb.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 22e8b28c9e..02d69c9919 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -2,6 +2,8 @@ import { Fetch, FetchCSS, FetchJSON, FetchRequest, FetchWindowCSS } from '../../ import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; +import type { Numeric, Text } from '../../SettingsManager'; +import { Key as GlobalKey } from '../../SettingsGlobal'; type JSONPageData_v016452 = { items: Configuration_v016452[] @@ -432,6 +434,11 @@ async function process_v016130(scraper: MangaScraper, page: Page, priority: Prio async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Promise { return new Promise(resolve => { + + const settings = HakuNeko.SettingsManager.OpenScope(); + const format = settings.Get(GlobalKey.DescramblingFormat).Value; + const quality = settings.Get(GlobalKey.DescramblingQuality).Value; + const view: PageView_v016130 = _getImageDescrambleCoords(keys.s, keys.u, bitmap.width, bitmap.height); const canvas = document.createElement('canvas'); canvas.width = view.width; @@ -449,7 +456,7 @@ async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Prom } canvas.toBlob(data => { resolve(data); - }, 'image/png', parseFloat('90') / 100); + }, format, quality / 100); }); } From 920984d3725171b98d4e13fbcf72964ebc9d782c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 21 Oct 2023 21:15:57 +0200 Subject: [PATCH 14/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 870ccb1547..2cddbcd7ca 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -28,6 +28,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -36,15 +37,21 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicBushi } from './ComicBushi'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicK } from './ComicK'; +export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as ComikeyArchive } from './ComikeyArchive'; @@ -57,6 +64,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -86,8 +94,10 @@ export { default as FreeManga } from './FreeManga'; export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GoldenMangas } from './GoldenMangas'; export { default as GolDragon } from './GolDragon'; @@ -226,6 +236,7 @@ export { default as MangaNel } from './MangaNel'; export { default as MangaNexus } from './MangaNexus'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaRockTeam } from './MangaRockTeam'; @@ -312,7 +323,9 @@ export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -475,14 +488,12 @@ export { default as BatoScan } from './legacy/BatoScan'; export { default as Biamam } from './legacy/Biamam'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as Buka } from './legacy/Buka'; export { default as Bx117 } from './legacy/Bx117'; export { default as Caisemh } from './legacy/Caisemh'; export { default as CatManga } from './legacy/CatManga'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicBoost } from './legacy/ComicBoost'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicClear } from './legacy/ComicClear'; export { default as ComicDays } from './legacy/ComicDays'; @@ -491,11 +502,8 @@ export { default as ComicExtra } from './legacy/ComicExtra'; export { default as ComicFire } from './legacy/ComicFire'; export { default as ComicFX } from './legacy/ComicFX'; export { default as COMICMeDu } from './legacy/COMICMeDu'; -export { default as ComicMeteor } from './legacy/ComicMeteor'; export { default as ComicoNovel } from './legacy/ComicoNovel'; -export { default as ComicPolaris } from './legacy/ComicPolaris'; export { default as ComicRyu } from './legacy/ComicRyu'; -export { default as ComicValkyrie } from './legacy/ComicValkyrie'; export { default as ComicVN } from './legacy/ComicVN'; export { default as ComicWalker } from './legacy/ComicWalker'; export { default as CopyToon } from './legacy/CopyToon'; @@ -517,7 +525,6 @@ export { default as ForgottenScans } from './legacy/ForgottenScans'; export { default as FRScan } from './legacy/FRScan'; export { default as FudidoScanlator } from './legacy/FudidoScanlator'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GanGanOnline } from './legacy/GanGanOnline'; export { default as Ganma } from './legacy/Ganma'; @@ -743,12 +750,10 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as OnePunchMan } from './legacy/OnePunchMan'; export { default as OneShotScans } from './legacy/OneShotScans'; export { default as OneTimeScans } from './legacy/OneTimeScans'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PervEden } from './legacy/PervEden'; export { default as PervEdenIT } from './legacy/PervEdenIT'; export { default as PhoenixScans } from './legacy/PhoenixScans'; From 786bbf436561104ed7df97418d29c14b3b229593 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 24 Oct 2023 18:37:50 +0200 Subject: [PATCH 15/88] better regexp --- web/src/engine/websites/ComicBrise.ts | 2 +- web/src/engine/websites/ComicMeteor.ts | 2 +- web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/ComicValkyrie.ts | 2 +- web/src/engine/websites/DigitalMargaret.ts | 2 +- web/src/engine/websites/Futabanet.ts | 2 +- web/src/engine/websites/Getsuaku.ts | 2 +- web/src/engine/websites/MangaPlanet.ts | 2 +- web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/OneTwoThreeHon.ts | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index b83677d932..f6f89661aa 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/\S+\/$/, '.post-title') +@Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index d435229b23..4221b84e03 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -11,7 +11,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/\S+\/$/, 'div.h2ttl_other') +@Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index 89fd6f703b..13eb332910 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -32,7 +32,7 @@ export default class extends DecoratableMangaScraper { } public override ValidateMangaURL(url: string): boolean { - return /^https?:\/\/www\.comicride\.jp\/(\/)?book\/\S+\/(index\.html)?$/.test(url); + return /^https?:\/\/www\.comicride\.jp\/(\/)?book\/[^/]+\/(index\.html)?$/.test(url); } public override async FetchManga(provider: MangaPlugin, url: string): Promise { diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 08eb7f1ceb..47d69d21e2 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -30,7 +30,7 @@ export default class extends DecoratableMangaScraper { } public override ValidateMangaURL(url: string): boolean { - return /^https?:\/\/www\.comic-valkyrie\.com\/\S+(\/|\/new.html)?$/.test(url); + return /^https?:\/\/www\.comic-valkyrie\.com\/[^/]+(\/|\/new.html)?$/.test(url); } public override async FetchManga(provider: MangaPlugin, url: string): Promise { diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 4e5081a33c..a0588623d2 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -15,7 +15,7 @@ function ChapterExtractor(element: HTMLElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/\S+\/$/, 'section#product div.content h3') +@Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/[^/]+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) @SpeedBinb.PagesSinglePage() diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 036cb3cdab..d6674e65a1 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -14,7 +14,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/gaugau\.futabanet\.jp\/list\/work\/\S+$/, 'h1.detail-ex__title') +@Common.MangaCSS(/^https?:\/\/gaugau\.futabanet\.jp\/list\/work\/[^/]+$/, 'h1.detail-ex__title') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) @SpeedBinb.PagesSinglePage('https://reader.futabanet.jp') diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index f66e02f58b..41bba48015 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -22,7 +22,7 @@ function MangaExtractor(element: HTMLElement) { }; } -@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/\S+$/, 'div.detail__main h2.detail__title') +@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/[^/]+$/, 'div.detail__main h2.detail__title') @Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 583ef1181e..91b940aaca 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -11,7 +11,7 @@ function MangaExtractor(element: HTMLElement) { return {id, title}; } -@Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/\S+$/, '.card-body.book-detail h3') +@Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/[^/]+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 57aec7434d..e3b7b3b9f4 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -11,7 +11,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/\S+\/$/, 'h2.contentTitle') +@Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/[^/]+\/$/, 'h2.contentTitle') @Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index f4543ebc3f..e37a7f92ea 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -8,11 +8,11 @@ import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { console.log(anchor.pathname); const id = anchor.pathname; - const title = anchor.pathname.match(/[\w]+\/web-comic\/([\S]+)\//)[1]; + const title = anchor.pathname.match(/[^/]+\/web-comic\/([^/]+)\//)[1]; return { id, title }; } -@Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[\S]+\/web-comic\/[\S]+\/$/, 'div.title-area h2') +@Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { From db8af242ebe4fd969f693ed71fc0d8103600aa80 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 2 Nov 2023 10:15:04 +0100 Subject: [PATCH 16/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 11d3cb7440..a390bd4c22 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -28,6 +28,7 @@ export { default as Batoto } from './Batoto'; export { default as BestManga } from './BestManga'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -36,18 +37,24 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicBushi } from './ComicBushi'; export { default as ComicDays } from './ComicDays'; export { default as ComicExtra } from './ComicExtra'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicK } from './ComicK'; +export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicWalker } from './ComicWalker'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -60,6 +67,7 @@ export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -90,9 +98,11 @@ export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FRScan } from './FRScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as GanGanOnline } from './GanGanOnline'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GloryManga } from './GloryManga'; export { default as GoldenMangas } from './GoldenMangas'; export { default as GolDragon } from './GolDragon'; @@ -239,6 +249,7 @@ export { default as MangaNel } from './MangaNel'; export { default as MangaNexus } from './MangaNexus'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaReader } from './MangaReader'; @@ -325,7 +336,9 @@ export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -489,18 +502,13 @@ export { default as AstralLibrary } from './legacy/AstralLibrary'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicBoost } from './legacy/ComicBoost'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicEarthStar } from './legacy/ComicEarthStar'; export { default as ComicFire } from './legacy/ComicFire'; export { default as ComicFX } from './legacy/ComicFX'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -512,7 +520,6 @@ export { default as EHentai } from './legacy/EHentai'; export { default as ElevenToon } from './legacy/ElevenToon'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Ganma } from './legacy/Ganma'; export { default as GekkouScans } from './legacy/GekkouScans'; @@ -633,9 +640,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PhoenixScansIT } from './legacy/PhoenixScansIT'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; From 3d5b471d8ad832825cc5c7068402018200cbed44 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 12 Nov 2023 17:57:42 +0100 Subject: [PATCH 17/88] use origin placeholder --- web/src/engine/websites/BookLive.ts | 2 +- web/src/engine/websites/Cmoa.ts | 2 +- web/src/engine/websites/ComicBrise.ts | 2 +- web/src/engine/websites/ComicMeteor.ts | 2 +- web/src/engine/websites/ComicPolaris.ts | 2 +- web/src/engine/websites/ComicRide.ts | 7 ++++--- web/src/engine/websites/ComicRide_e2e.ts | 2 +- web/src/engine/websites/ComicValkyrie.ts | 6 +++--- web/src/engine/websites/ComicValkyrie_e2e.ts | 2 +- web/src/engine/websites/DigitalMargaret.ts | 2 +- web/src/engine/websites/Futabanet.ts | 2 +- web/src/engine/websites/Getsuaku.ts | 2 +- web/src/engine/websites/MangaPlanet.ts | 2 +- web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/OneTwoThreeHon.ts | 2 +- 15 files changed, 20 insertions(+), 19 deletions(-) diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index 7b44441a64..25a2ffe4ff 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -9,7 +9,7 @@ function ChapterExtractor(element: HTMLElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/booklive\.jp\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') +@Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) @SpeedBinb.PagesSinglePage() diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 9a8784ba73..abe9d17312 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^https?:\/\/www\.cmoa\.jp\/title\/\d+\/(vol\/\d+\/)?$/, '#GA_this_page_title_name') +@Common.MangaCSS(/^{origin}\/title\/\d+\/(vol\/\d+\/)?$/, '#GA_this_page_title_name') @Common.MangasNotSupported() @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index f6f89661aa..a1729b2e3e 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^https?:\/\/www\.comic-brise\.com\/contents\/[^/]+\/$/, '.post-title') +@Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index 4221b84e03..b3cb3076a9 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -11,7 +11,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/comic-meteor\.jp\/[^/]+\/$/, 'div.h2ttl_other') +@Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 42e7539706..da29be72f4 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -11,7 +11,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/comic-polaris\.jp\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') +@Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index 13eb332910..86e85cff8a 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -6,7 +6,7 @@ import * as SpeedBinb from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { - id: element.querySelector('a.p-update-list__main').pathname.replace(/\/\//g, "/"), + id: element.querySelector('a.p-update-list__main').pathname.replace(/\/\//g, "/").replace('/index.html', '/'), title: element.querySelector('.p-update-list__title').textContent.trim() }; } @@ -32,11 +32,12 @@ export default class extends DecoratableMangaScraper { } public override ValidateMangaURL(url: string): boolean { - return /^https?:\/\/www\.comicride\.jp\/(\/)?book\/[^/]+\/(index\.html)?$/.test(url); + return new RegExp(`^${this.URI.origin}/(/)?book/[^/]+/(index.html)?$`).test(url); + } public override async FetchManga(provider: MangaPlugin, url: string): Promise { - return await Common.FetchMangaCSS.call(this, provider, url.replace(/\/\//g, "/"), '.p-detail-head__title'); + return await Common.FetchMangaCSS.call(this, provider, url.replace(/\/\//g, "/").replace('/index.html', '/'), '.p-detail-head__title'); } diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts index 97fb745433..53b323fe34 100644 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ b/web/src/engine/websites/ComicRide_e2e.ts @@ -7,7 +7,7 @@ const config: Config = { timeout: 45000 }, container: { - url: 'https://www.comicride.jp/book/kamihatsu/', + url: 'https://www.comicride.jp//book/kamihatsu/index.html', //purposedly test a bad url like comicride can give us id: '/book/kamihatsu/', title: '神の遣いの少女は初恋の将軍にすべてを捧ぐ' }, diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 47d69d21e2..970889e932 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -6,7 +6,7 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaExtractor(element: HTMLElement) { - const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', ''); + const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'); const title = element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim(); return { id, title }; } @@ -30,14 +30,14 @@ export default class extends DecoratableMangaScraper { } public override ValidateMangaURL(url: string): boolean { - return /^https?:\/\/www\.comic-valkyrie\.com\/[^/]+(\/|\/new.html)?$/.test(url); + return new RegExp(`^${this.URI.origin}/[^/]+(/|/new.html)?$`).test(url); } public override async FetchManga(provider: MangaPlugin, url: string): Promise { const uri = new URL(url); const request = new FetchRequest(uri.href); const data = await FetchCSS(request, 'meta[property = "og:title"]'); - const id = uri.pathname.replace('/new.html', ''); + const id = uri.pathname.replace('/new.html', '/'); const title = data[0].content.replace(/\s*THE COMIC\s*/i, '').trim(); return new Manga(this, provider, id, title); } diff --git a/web/src/engine/websites/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts index 58ee4461bd..e5d8a26759 100644 --- a/web/src/engine/websites/ComicValkyrie_e2e.ts +++ b/web/src/engine/websites/ComicValkyrie_e2e.ts @@ -6,7 +6,7 @@ const config: Config = { title: 'Comic Valkyrie' }, container: { - url: 'https://www.comic-valkyrie.com/teisou/', + url: 'https://www.comic-valkyrie.com/teisou/new.html', //testing the removing of new.html on purpose id: '/teisou/', title: '貞操逆転世界' }, diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index a0588623d2..227296f6aa 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -15,7 +15,7 @@ function ChapterExtractor(element: HTMLElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/digitalmargaret\.jp\/detail\/[^/]+\/$/, 'section#product div.content h3') +@Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) @SpeedBinb.PagesSinglePage() diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index d6674e65a1..69293663f5 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -14,7 +14,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/gaugau\.futabanet\.jp\/list\/work\/[^/]+$/, 'h1.detail-ex__title') +@Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'h1.detail-ex__title') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) @SpeedBinb.PagesSinglePage('https://reader.futabanet.jp') diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index 41bba48015..2b8c3d6040 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -22,7 +22,7 @@ function MangaExtractor(element: HTMLElement) { }; } -@Common.MangaCSS(/^https?:\/\/getsuaku\.com\/episode\/[^/]+$/, 'div.detail__main h2.detail__title') +@Common.MangaCSS(/^{origin}\/episode\/[^/]+$/, 'div.detail__main h2.detail__title') @Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 91b940aaca..2c48a0104e 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -11,7 +11,7 @@ function MangaExtractor(element: HTMLElement) { return {id, title}; } -@Common.MangaCSS(/^https?:\/\/mangaplanet\.com\/comic\/[^/]+$/, '.card-body.book-detail h3') +@Common.MangaCSS(/^{origin}\/comic\/[^/]+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index e3b7b3b9f4..8047e6ac92 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -11,7 +11,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/webcomic\.ohtabooks\.com\/[^/]+\/$/, 'h2.contentTitle') +@Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'h2.contentTitle') @Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index e37a7f92ea..2dae6c7f28 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -12,7 +12,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { return { id, title }; } -@Common.MangaCSS(/^https?:\/\/www\.123hon\.com\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') +@Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { From f79b1bd3ac75846ae8f95c8a38c8daba7d29bf33 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 27 Nov 2023 22:13:43 +0100 Subject: [PATCH 18/88] Update _index.ts --- web/src/engine/websites/_index.ts | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index ce241026dc..722183333f 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -38,6 +38,7 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -46,11 +47,13 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicBushi } from './ComicBushi'; export { default as ComicDays } from './ComicDays'; export { default as ComicExtra } from './ComicExtra'; @@ -58,10 +61,14 @@ export { default as ComicFuz } from './ComicFuz'; export { default as ComicFX } from './ComicFX'; export { default as ComicGardo } from './ComicGardo'; export { default as ComicK } from './ComicK'; +export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicWalker } from './ComicWalker'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -80,6 +87,7 @@ export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -115,6 +123,7 @@ export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FRScan } from './FRScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -122,6 +131,7 @@ export { default as GanGanOnline } from './GanGanOnline'; export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; export { default as Gntai } from './Gntai'; @@ -285,6 +295,7 @@ export { default as MangaNel } from './MangaNel'; export { default as MangaNexus } from './MangaNexus'; export { default as MangaOkur } from './MangaOkur'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaReader } from './MangaReader'; @@ -371,7 +382,9 @@ export { default as NineHentai } from './NineHentai'; export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as OzulScans } from './OzulScans'; @@ -540,17 +553,12 @@ export { default as AstralLibrary } from './legacy/AstralLibrary'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicBoost } from './legacy/ComicBoost'; -export { default as ComicBrise } from './legacy/ComicBrise'; export { default as ComicBunch } from './legacy/ComicBunch'; export { default as ComicEarthStar } from './legacy/ComicEarthStar'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -560,7 +568,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GekkouScans } from './legacy/GekkouScans'; export { default as GManga } from './legacy/GManga'; @@ -672,9 +679,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as Qimiaomh } from './legacy/Qimiaomh'; From 73eebd5147ae0e39f1bab7ad0f96e661b5e56bb6 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 1 Dec 2023 11:44:43 +0100 Subject: [PATCH 19/88] [futabanet] reflect website changes --- web/src/engine/websites/Futabanet.ts | 32 +++++++++++++----------- web/src/engine/websites/Futabanet_e2e.ts | 2 +- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 69293663f5..20c2f07f7b 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -1,23 +1,13 @@ import { Tags } from '../Tags'; import icon from './Futabanet.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('.m-result-list__title').textContent.trim(); - return { id, title }; -} -function ChapterExtractor(anchor: HTMLAnchorElement) { - const title = anchor.querySelector('span:not(.new)').innerText.replace(/\(\d+\.\d+(.*)\)$/, '').trim(); - const id = anchor.href; - return { id, title }; -} +import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'h1.detail-ex__title') -@Common.MangasMultiPageCSS('/list/works?page={page}', 'div.m-result-list__item a', 1, 1, 0, MangaExtractor) -@Common.ChaptersSinglePageCSS('section.detail-sec.detail-ex div.detail-ex__btn-item a[href*="reader.futabanet"]', ChapterExtractor) -@SpeedBinb.PagesSinglePage('https://reader.futabanet.jp') +@Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') +@Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') +@SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -27,4 +17,16 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async FetchChapters(manga: Manga): Promise { + const request = new FetchRequest(`${this.URI.origin}${manga.Identifier}/episodes`); + const data = await FetchCSS(request, 'div.episode__grid a'); + return data.map(chapter => { + const epnum = chapter.querySelector('.episode__num').textContent.trim(); + const title = chapter.querySelector('.episode__title').textContent.trim(); + return new Chapter(this, manga, chapter.pathname, title ? [epnum, title].join(' - ') : epnum); + }); + + } + } \ No newline at end of file diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index be88ed456e..8a192ff6fd 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -11,7 +11,7 @@ const config: Config = { title: 'ポイントギフター《経験値分配能力者》の異世界最強ソロライフ~ブラックギルドから解放された男は万能最強職として無双する~' }, child: { - id: 'https://reader.futabanet.jp/62591706776561c83f010000_001-001_1?wurl=https%3A%2F%2Fgaugau.futabanet.jp%2Flist%2Fwork%2F62591706776561c83f010000', + id: '/list/work/62591706776561c83f010000/episodes/1', title: '第1話(1)' }, entry: { From 513c06ee5502c506ea344fb7843371b49261fa99 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 12 Dec 2023 17:55:19 +0100 Subject: [PATCH 20/88] Add Yanmaga --- web/src/engine/websites/Yanmaga.ts | 46 +++++++++++++++++++++++++ web/src/engine/websites/Yanmaga.webp | Bin 0 -> 5116 bytes web/src/engine/websites/Yanmaga_e2e.ts | 25 ++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 72 insertions(+) create mode 100644 web/src/engine/websites/Yanmaga.ts create mode 100644 web/src/engine/websites/Yanmaga.webp create mode 100644 web/src/engine/websites/Yanmaga_e2e.ts diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts new file mode 100644 index 0000000000..f847c43e28 --- /dev/null +++ b/web/src/engine/websites/Yanmaga.ts @@ -0,0 +1,46 @@ +import { Tags } from '../Tags'; +import icon from './Yanmaga.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; + +function MangaExtractor(anchor: HTMLAnchorElement) { + const id = anchor.pathname; + const title = anchor.querySelector('.mod-book-title').textContent.trim(); + return { id, title }; +} + +const chapterScript = ` +new Promise(resolve => { + const interval = setInterval(() => { + let morebtn = document.querySelector('.mod-episode-more-button') ; + if (morebtn) morebtn.click() + else { + clearInterval(interval); + const chapters = [...document.querySelectorAll('a.mod-episode-link')]; + resolve(chapters.map(chapter => { + return { + id: chapter.pathname, + title: chapter.querySelector('.mod-episode-title').textContent.trim() + } + })); + } + }, 1000); +}); + +`; + +@Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') +@Common.MangasSinglePageCSS('/comics', 'a.ga-comics-book-item', MangaExtractor) +@Common.ChaptersSinglePageJS(chapterScript, 200) +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('yanmaga', `Yanmaga`, 'https://yanmaga.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/Yanmaga.webp b/web/src/engine/websites/Yanmaga.webp new file mode 100644 index 0000000000000000000000000000000000000000..caae45605638fa5883b1cede6fa9afc11c7fa224 GIT binary patch literal 5116 zcmbW52{@G9`^V2SGiL1DpzLGp%gmU;Fk?4}O4hQZGG+#YSsG)FsAxeuB9%x9mC}op zQd+clE0s3Yt9pf2DiPxMOua4t|8@2L|JU!iW}fSF?(@CRxzBy>=bGnCkgvD*M=SuL zULFC90vy6*0RTqu*Y)eim%#||k%yZ=-e*3SFF+^*z~hTWL32ECVc`)t%yobOG5`(8 z05DleLcd_|5Q*B?i-AjmMH2pbeYy)EN$WPjCjf{0Y5#wb3QH&w0{{iUY8y5ui3M{m z%!#RDp~OB6vs!e5gb^qSi{JoZo-N_nZ*28d^Nrmk%;xdgutpNIkj-OD_yWx9Q<6C_ zBj>}sHigSch4~K5Mv2KhF3jUFtMNF@Bmhv7>==nTtT>phVU`z#1TkQC0zg_m_7{%+ zg~gmSI8Fc<0%5v{8yhFanX$}qWE#x@=fg=&v6Q_|s;z7XYPP0Ge<7vK|ddy~K&dLOO|*nwm=Fa#%!3LVsNUr{IV3_wdVn zM9F+Va)jOM96(0yfqS4I z`!-)@5s*B2q51>g>K0(n96p&%$6ih^Px zK9me)LTjJ`XdAQ>s)TBxV^Aw}4!Qz$Ll2;*&=B+S#`t5H7%^rorVMik(~h}?>Bo#q%Sr1?Q>4A6Bc%D# ztEEe%>!i;}-;y4Xo|I9RF_xjr_{*?m(q%TwRLh){xgpapGbyVgYbxt38zLJoyGpiH z_K567*+;S;Ij&reT&dhqxyy1-YizdmY`58*+4-{@X7|jV(8OtaX(niH)ojsx ztcB9D&i?O5^suM zh+mCwz&|#WHFPkHF)T9dFdR10H}W&eG^#gxXe?vwU>s+>!?@FU%*50r)MTAWi^-tr zY*Sy;4AXkkM`j9Uu4c>4s?6?~qs<-66U=v;-?Ttj*jdC`lv~`eL|9TSxt6;vyRD?G zXjXiyDyw@0d4fA3g-}m;O4K0EC$1*85Z{uFND-v1q)yVbwVidMb+vUbS(QAOyqbKH z{GMV#VNuE{cWe}Fylt{=PS}jtTH11K_t@UI!`k`Tt+VT}`$Dy+il|4ZL-t1YQTDs+ z?>VSB1UM8rT&79UJZRapHri)8l`f_?(%(4}91|St90#3Doj6X_PS2h3&P?Y@=ROyl zOO(rAmp)emSEg%~>oYe)H@4dWw*hx^_jvb1?r%M;JwzT&9%BqTBa3m?6X`j}GvD*N zm#Wu7ubo~`yz$<#-u2$YbL{4R-b#my1p#mTHoQh_H(o5UYI98FL>V0 zdC%rs%ooi+>4)%}>$lzS(E{TI`~@xkz~9$@yZ_?=(}3jxrvlM|0fFU#FM`NHnL(Yw z*x+Tsb-|xPJVG{y^e!}8n7puKkX#!%swDA{Ip) zh!|b$wYYe3f23XH+Q_?0OqZlBxw2GiY2wn;%aoQemmQCiiVBUYi<)BkGpm@R(Z12U zqK8=w)(+Mywi~;MJ;ZV5Y~u{XILB;@8H{y~-5xs>=NeZM_nOP#?&OZd`@~nok0tmg z)FjL#h9)-fqUgz)4I|v(l?|JWO!%nUx8Y|TG5edkhv=JX_k9dbmvd zHkEA|+n#Ut+umG+E6OkWSiG$GN{MYr#SYmW$vgT==a-%+Gb-CsHnlTuXHU6DdBZN9 zT^n|d?Pl-3wa0DGkqX_4f{KZ~+`acJ=TtUVnN*eRL+?x3_o8}Hb?1JE{j~?Q4ip^t zQp2z5I~a8ELalvmZJkct=6XbZa{bVu$U`>|dmcVs9{s;14Lt^Bn5>CI`dsX}=N-#Bde4WQzjGn*!u5;uE?&Omed&CsduRJ)=gVzZ=vP{= zI$UkJM!nYDW!Kg8r`?}T*QwW=Z`j{Bag%oQWVciInOm;6&fWIBed&(xoohV{db;l} zynFv%cv1{#QdEweR#(&!=6_f}iz1 zXFY%QchcWe{kbm`UX%>z57Z7)2HS?bhi<-H{IdU*@YUq&wQp43?0ReV_K$aN@4AM= zhWkfEBQx&{KWKia`DpvGV>Dp&$tT{Y$+7%#&GCbu9X@wXgiZ`hrcPm|O23$YIXOLV z`q2z;W(GcC;P~)sz?NBHH)P=k|LD8$h}*oY@s*Vp8obLn3L9A9+6tT|PW!@{1)&)g z)WNZl>cTSqn~!7fv?tGvEuO+`JN)2n;1~NZvmR8?^sSzVoOmMzGmHnz#&1mO_dC6w z8ku2CtvgG4KQlD*YWk@Q>-3uGn=8mGPt#V*G}I`@yRPxwvzs8jn24SoT<@nVJ9SP@ zVE4&<93M(rW0Bbw`NU1nmf?b+??u&2x@$@Ft6PC*xM(%&p$oiJF@=qnoYOPaadFip%xS7$gdkE@QY zD&l>pF;}y!w-0BChRU`$1}1%Kr`h((Lt0@XC$YJrVW(a4z?{*3|5uFzE7htvwIpqe z_Ro=yj$4&o_j?uIZE3nJhu>@=-SKR-5&vEGWN%~C?c(eMuJ7LV6#q4}L11|-*eK`v z{XC>%u(xei^Wf*4nz`Mv%@5Np7p9sv<}5h1K-|%OCCjha^P%bOHW|G*&@k2ZPm1i1ULf*f18YZVK`%r7<+Qy-p)-{+0J~;a! zt+8wm{zVN9zhcQG$3{FyH6~qT7=hR0W~=98>P}4D3Vb2M?XurccP~Guz^tLfP`^$) zKH>68I)B55~?MSJ%N?=b)YJI``T@Q{o4XjHF zE*@{4@W{nD9@3DmTI*mzA}j85OqTmCFvFfda3Me;V}Ug`1KKLm!nMyzPp;9XE!spRy~j^jIEpEyn4z zg;K#t&KtJeuH3!%bOMgmU4{DA9C&mvXt}ViG;iY|L+fnxlsC064j(!NbUO;2 zLc{%Y;o;dt>==5Gr}sZ|!7XR}FDK(v8=^oIOM?F?ppmR8BnpK9D+o#Hd@(bPz)v## zK7uFw2Z@L){Cbd-jL3`@B#WK#aHQXsz!Ux$mY+oYx*Q@)z$2wGg(Nc3TC$|?LO;KM zm-2W&)JbCaK>P3Nq>ywWhZMv~f=}5j4lFm6OeLf#7AAPNx(62E6LAWk3_B*h7Y zI0}VG!I}9nSzNxvV*b^|&yViQPZBfX)3dLqGaep<$mO!>-d^4`ikG#AwYwLCO!o40 zXE@k-+uA#LQ9Ni22Y2dsUrzxmnaAOazx%R(`Z9j&E2##a5T4nSBjToT*xn)m5BGJ| zbnfqCq5XEee|*`$kH!7Bz9cvpl4Ngx+3W8nxPT=1qjKTKkJ{((;er>zl@0y_a2O^8 literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/Yanmaga_e2e.ts b/web/src/engine/websites/Yanmaga_e2e.ts new file mode 100644 index 0000000000..383b970d65 --- /dev/null +++ b/web/src/engine/websites/Yanmaga_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture, type Config } from '../../../test/WebsitesFixture'; + +const config: Config = { + plugin: { + id: 'yanmaga', + title: 'Yanmaga' + }, + container: { + url: 'https://yanmaga.jp/comics/%E5%A4%A2%E3%81%86%E3%81%A4%E3%81%A4%E3%81%AE%E8%8A%B1%E3%81%AE%E5%9C%92', + id: '/comics/%E5%A4%A2%E3%81%86%E3%81%A4%E3%81%A4%E3%81%AE%E8%8A%B1%E3%81%AE%E5%9C%92', + title: '夢うつつの花の園', + }, + child: { + id: '/comics/%E5%A4%A2%E3%81%86%E3%81%A4%E3%81%A4%E3%81%AE%E8%8A%B1%E3%81%AE%E5%9C%92/351192c0f7d1cf3b88175f3d9dfae594', + title: '第1夢 幽体離脱' + }, + entry: { + index: 0, + size: 2_071_327, + 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/_index.ts b/web/src/engine/websites/_index.ts index 722183333f..90e84211b9 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -529,6 +529,7 @@ export { default as XCaliBRScans } from './XCaliBRScans'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; export { default as YaoiScan } from './YaoiScan'; From 556d00d7c75a6f3be044076b65c3be4137639763 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 12 Dec 2023 19:32:18 +0100 Subject: [PATCH 21/88] add YoungJump && Speebinb improvements --- web/src/engine/websites/YoungJump.ts | 35 ++++ .../websites/{legacy => }/YoungJump.webp | Bin web/src/engine/websites/_index.ts | 2 +- .../engine/websites/decorators/SpeedBinb.ts | 155 +++++++++++------- web/src/engine/websites/legacy/YoungJump.ts | 66 -------- 5 files changed, 131 insertions(+), 127 deletions(-) create mode 100644 web/src/engine/websites/YoungJump.ts rename web/src/engine/websites/{legacy => }/YoungJump.webp (100%) mode change 100755 => 100644 delete mode 100755 web/src/engine/websites/legacy/YoungJump.ts diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts new file mode 100644 index 0000000000..5131e4fa09 --- /dev/null +++ b/web/src/engine/websites/YoungJump.ts @@ -0,0 +1,35 @@ +import { Tags } from '../Tags'; +import icon from './YoungJump.webp'; +import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchJSON, FetchRequest } from '../FetchProvider'; + +type APIMagazine = { + url: string, + issue: string, + number: string +} + +//@Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') +@Common.ChaptersUniqueFromManga() +@SpeedBinb.PagesSinglePage() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('youngjump', `ヤングジャンプ / ウルトラジャンプ (young jump/ultra jump)`, 'https://www.youngjump.world', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override async FetchMangas(provider: MangaPlugin): Promise { + const request = new FetchRequest(new URL('/yj-rest-apis/getBookInfo.php', this.URI).href); + const data = await FetchJSON(request); + return data.map(magazine => new Manga(this, provider, magazine.url, `${magazine.issue} - ${magazine.number}`.trim())); + + } + +} \ No newline at end of file diff --git a/web/src/engine/websites/legacy/YoungJump.webp b/web/src/engine/websites/YoungJump.webp old mode 100755 new mode 100644 similarity index 100% rename from web/src/engine/websites/legacy/YoungJump.webp rename to web/src/engine/websites/YoungJump.webp diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 90e84211b9..c0a8709172 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -535,6 +535,7 @@ export { default as YaoiHavenReborn } from './YaoiHavenReborn'; export { default as YaoiScan } from './YaoiScan'; export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YawarakaSpirits } from './YawarakaSpirits'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasES } from './YugenMangasES'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YuriVerso } from './YuriVerso'; @@ -745,6 +746,5 @@ export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; export { default as xianman123 } from './legacy/xianman123'; export { default as YesMangasBR } from './legacy/YesMangasBR'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 02d69c9919..31cc1c7e84 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -1,4 +1,4 @@ -import { Fetch, FetchCSS, FetchJSON, FetchRequest, FetchWindowCSS } from '../../FetchProvider'; +import { Fetch, FetchJSON, FetchRequest, FetchWindowCSS } from '../../FetchProvider'; import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; @@ -13,7 +13,7 @@ type Configuration_v016452 = { ContentID : string, ctbl: string[], ptbl: string[], - ServerType: number, + ServerType: number | string ContentsServer: string, p: string, ViewMode: number, @@ -65,6 +65,13 @@ type DescrambleKP = { u: string } +function getSanitizedURL(base: string, append: string): URL { + const baseURI = new URL(append, base+'/'); + baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); + return baseURI; + +} + /********************************************** ******** Page List Extraction Methods ******** **********************************************/ @@ -77,34 +84,45 @@ type DescrambleKP = { * @param baseUrl - sdcqds */ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { - const url = baseUrl ? new URL(baseUrl) : new URL(this.URI); - const uri = new URL(chapter.Identifier, this.URI); - const request = new FetchRequest(uri.href, { + const websiteUrl = baseUrl ? new URL(baseUrl) : new URL(this.URI); + let viewerUrl = new URL(chapter.Identifier, this.URI); + const request = new FetchRequest(viewerUrl.href, { headers: { Referer: this.URI.href - } });//referer needed for ManpaPlanet - const data = await FetchCSS(request, 'div#content.pages'); + } + });//referer needed for ManpaPlanet + + //const data = await FetchCSS(request, 'div#content.pages'); + const response = await Fetch(request); + const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); + const data = [...dom.querySelectorAll('div#content.pages')]; + + //handle redirection + if (response.redirected) { + viewerUrl = new URL(response.url); + } + if (data.length == 0) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully const el = data[0]; if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { - const uri = new URL(chapter.Identifier, url); - uri.searchParams.set('cid', el.dataset['ptbinbCid']); - return await getPageList_v016113(this, uri.pathname + uri.search, el.dataset.ptbinb, url.href, chapter); + viewerUrl.searchParams.set('cid', el.dataset['ptbinbCid']); + return await getPageList_v016113(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); } - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && uri.searchParams.get('u0') && uri.searchParams.get('u1')) { - return await getPageList_v016452(this, chapter, el.dataset.ptbinb, url.href); + + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u0') && viewerUrl.searchParams.get('u1')) { + return await getPageList_v016452(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); } - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && uri.searchParams.get('u1')) { - return await getPageList_v016201(this, chapter, el.dataset.ptbinb, url.href); + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u1')) { + return await getPageList_v016201(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); } if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { - return await getPageList_v016130(this, chapter.Identifier, el.dataset.ptbinb, url.href, chapter); + return await getPageList_v016130(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); } + const imageConfigurations = el.querySelectorAll('div[data-ptimg$="ptimg.json"]'); if (imageConfigurations.length > 0) { - // TODO: Use the response URL instead of the request URL (in case of redirection ...) - return await _getPageList_v016061(this, [...imageConfigurations], request.url, chapter); + return await getPageList_v016061(this, viewerUrl.href, [...imageConfigurations], chapter); } throw new Error('Unsupported version of SpeedBinb reader!'); @@ -130,19 +148,12 @@ export function PagesSinglePage(baseUrl = '') { /** ************************* *** SpeedBinb v01.6061 *** -* ** Comic Meteor, Comic Valkyrie, ZeroSum, DigitalMargaRet, ComicBrise, ComicRide +* ** Comic Meteor, Comic Valkyrie, DigitalMargaRet, ComicBrise, ComicRide ************************* */ -async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: HTMLDivElement[], url: string, parent: Chapter): Promise { +async function getPageList_v016061(scraper: MangaScraper, url: string, imageConfigurations: HTMLDivElement[], chapter: Chapter): Promise { return imageConfigurations.map(element => { - //Zerosum & digital margaret, 123hon fix (missing "/").. Other ending must have been filtered from the plugin itself (like "/index.html") - const baseURI = new URL(url); - - if (!baseURI.href.endsWith('/') && !element.dataset.ptimg.startsWith('/')) { - baseURI.href += '/'; - } - - return new Page(scraper, parent, new URL(element.dataset.ptimg, baseURI.href)); + return new Page(scraper, chapter, getSanitizedURL(url, element.dataset.ptimg)); }); } @@ -153,8 +164,8 @@ async function _getPageList_v016061(scraper : MangaScraper, imageConfigurations: * Getsuaku, which is v01.6700 ************************* */ -async function getPageList_v016113(scraper: MangaScraper, chapterID: string, apiURL: string, baseURL: string, chapter: Chapter): Promise { - return await getPageList_v016130(scraper, chapterID, apiURL, baseURL, chapter); +async function getPageList_v016113(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { + return await getPageList_v016130(scraper, viewerURL, apiEndpoint, baseURL, chapter); } /** @@ -163,12 +174,12 @@ async function getPageList_v016113(scraper: MangaScraper, chapterID: string, api * ** Cmoa *** ************************* */ -async function getPageList_v016452(scraper : MangaScraper, chapter: Chapter, apiURL: string, baseURL: string): Promise { - const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); - const u0 = new URL(chapter.Identifier, baseURL).searchParams.get('u0'); - const u1 = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); +async function getPageList_v016452(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter,): Promise { + const cid = viewerURL.searchParams.get('cid'); + const u0 = viewerURL.searchParams.get('u0'); + const u1 = viewerURL.searchParams.get('u1'); const sharingKey = _tt(cid); - const uri = new URL(apiURL, baseURL + '/'); + const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', String(Date.now())); uri.searchParams.set('k', sharingKey); @@ -182,7 +193,11 @@ async function getPageList_v016452(scraper : MangaScraper, chapter: Chapter, api async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter): Promise { configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl); configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl); - //configuration.ServerType = parseInt(configuration.ServerType); + try { + configuration.ServerType = parseInt(configuration.ServerType as string); + } catch (error) { + // + } if (configuration.ServerType === 0) { return await getPageLinksSBC_v016452(scraper, configuration, params, baseURL, chapter); } @@ -190,7 +205,8 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config } async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter) { - const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + //const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); uri.searchParams.set('cid', params.cid); uri.searchParams.set('p', configuration.p); uri.searchParams.set('q', '1'); @@ -208,16 +224,20 @@ async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Co ************************* */ -async function getPageList_v016201(scraper: MangaScraper, chapter: Chapter, apiURL: string, baseURL: string): Promise { - const cid = new URL(chapter.Identifier, baseURL).searchParams.get('cid'); - const u = new URL(chapter.Identifier, baseURL).searchParams.get('u1'); +async function getPageList_v016201(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { + const cid = viewerURL.searchParams.get('cid'); + const u = viewerURL.searchParams.get('u1'); const sharingKey = _tt(cid); - const uri = new URL(apiURL, baseURL + '/'); + const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', String(Date.now())); uri.searchParams.set('k', sharingKey); uri.searchParams.set('u1', u); - const request = new FetchRequest(uri.href); + + let request = new FetchRequest(uri.href); + await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet + + request = new FetchRequest(uri.href); const data: JSONPageData_v016452 = await FetchJSON(request); return await getPageLinks_v016201(scraper, data.items[0], sharingKey, u, chapter); } @@ -226,17 +246,23 @@ async function getPageLinks_v016201(scraper : MangaScraper, configuration: Confi const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); - //configuration.ServerType = parseInt(configuration.ServerType); + try { + configuration.ServerType = parseInt(configuration.ServerType as string); + } catch (error) { + // + } - if (configuration['ServerType'] === 2) { + if (configuration.ServerType === 2) { return await _getPageLinksContent_v016201(scraper, configuration, u, chapter); } return Promise.reject(new Error('Content server type not supported!')); } async function _getPageLinksContent_v016201(scraper: MangaScraper, configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { - const uri = new URL(configuration.ContentsServer); - uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; - uri.pathname += 'content'; + //const uri = new URL(configuration.ContentsServer); + //uri.pathname += '/content'; + //uri.pathname = uri.pathname.replaceAll(/\/\/+/g, '/'); + const uri = getSanitizedURL(configuration.ContentsServer, 'content'); + uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('u1', u); const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); @@ -252,15 +278,14 @@ async function _getPageLinksContent_v016201(scraper: MangaScraper, configuration /** ***************************** *** SpeedBinb v01.6130 ****** - * ** BookLive, MangaPlanet*** + * ** BookLive, MangaPlanet, Yanmaga*** ***************************** */ -async function getPageList_v016130(scraper: MangaScraper, chapterID: string, apiURL: string, baseURL: string, chapter: Chapter): Promise { - const cid = new URL(chapterID, baseURL).searchParams.get('cid'); +async function getPageList_v016130(scraper: MangaScraper, chapterUrl: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { + const cid = chapterUrl.searchParams.get('cid'); const sharingKey = _tt(cid); - const uri = new URL(apiURL, baseURL + '/'); - uri.href = uri.href.replace(/\/\//g, '/'); + const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', String(Date.now())); uri.searchParams.set('k', sharingKey); @@ -282,12 +307,16 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config */ configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); - //configuration.ServerType = parseInt(configuration.ServerType); + try { + configuration.ServerType = parseInt(configuration.ServerType as string); + } catch (error) { + // + } if (configuration.ServerType === 0) { //Booklive return await getPageLinksSBC_v016130(scraper, configuration, baseURL, chapter); } - if (configuration.ServerType === 1) {//Futabanet + if (configuration.ServerType === 1) {//Futabanet, Getsuaku return await getPageLinksContentJS_v016130(scraper, configuration, chapter); } if (configuration.ServerType === 2) {//MangaPlanet @@ -297,7 +326,9 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config } async function getPageLinksSBC_v016130(scraper: MangaScraper, configuration: Configuration_v016452, baseURL: string, chapter: Chapter) { - const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + //const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); + const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); + uri.searchParams.set('cid', configuration.ContentID); uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('p', configuration.p); @@ -306,9 +337,11 @@ async function getPageLinksSBC_v016130(scraper: MangaScraper, configuration: Con } async function getPageLinksContent_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter : Chapter) { - const uri = new URL(configuration.ContentsServer); - uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; - uri.pathname += 'content'; + //const uri = new URL(configuration.ContentsServer); + //uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; + //uri.pathname += 'content'; + const uri = getSanitizedURL(configuration.ContentsServer, 'content'); + uri.searchParams.set('dmytime', configuration.ContentDate); const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href, { headers: { Referer: scraper.URI.href } })); @@ -322,9 +355,11 @@ async function getPageLinksContent_v016130(scraper: MangaScraper, configuration: } async function getPageLinksContentJS_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter: Chapter) { - const uri = new URL(configuration.ContentsServer); - uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; - uri.pathname += 'content.js'; + //const uri = new URL(configuration.ContentsServer); + //uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; + //uri.pathname += 'content.js'; + const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); + if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); const response = await Fetch(new FetchRequest(uri.href)); const data = await response.text(); diff --git a/web/src/engine/websites/legacy/YoungJump.ts b/web/src/engine/websites/legacy/YoungJump.ts deleted file mode 100755 index f90da2a8c5..0000000000 --- a/web/src/engine/websites/legacy/YoungJump.ts +++ /dev/null @@ -1,66 +0,0 @@ -// Auto-Generated export from HakuNeko Legacy -// See: https://gist.github.com/ronny1982/0c8d5d4f0bd9c1f1b21dbf9a2ffbfec9 - -//import { Tags } from '../../Tags'; -import icon from './YoungJump.webp'; -import { DecoratableMangaScraper } from '../../providers/MangaPlugin'; - -export default class extends DecoratableMangaScraper { - - public constructor() { - super('youngjump', `ヤングジャンプ / ウルトラジャンプ (young jump/ultra jump)`, 'https://www.youngjump.world' /*, Tags.Language.English, Tags ... */); - } - - public override get Icon() { - return icon; - } -} - -// Original Source -/* -class YoungJump extends SpeedBinb { - - constructor() { - super(); - super.id = 'youngjump'; - super.label = 'ヤングジャンプ / ウルトラジャンプ (young jump/ultra jump)'; - this.tags = [ 'manga', 'japanese' ]; - this.url = 'https://www.youngjump.world'; - this.links = { - login: 'https://www.youngjump.world/?login=1' - }; - } - - async _getMangas() { - return [ - { - id: 'free_uj/', - title: 'ウルトラジャンプ - ultra jump' - }, - { - id: 'free_yj/', - title: 'ヤングジャンプ - young jump' - } - ]; - } - - async _getChapters(manga) { - const request = new Request(new URL(manga.id, this.url), this.requestOptions); - const data = await this.fetchDOM(request); - - let chapters = []; - for (const year of data.querySelectorAll('section.sp-w')) { - const mangas = [...year.querySelectorAll('a.p-my__list-link')]; - chapters.push(...mangas.map(element => { - return { - id: this.getAbsolutePath(element.href, this.url), - title: year.querySelector('h3').innerText.trim() +' - ' + element.querySelector('h4').innerText.trim() - }; - })); - } - - return chapters; - } - -} -*/ \ No newline at end of file From a258412c32458dcd907963959faf0dfeb9dce07f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 13 Dec 2023 12:54:36 +0100 Subject: [PATCH 22/88] Update _index.ts --- web/src/engine/websites/_index.ts | 81 ++++++++++++++++++++++--------- 1 file changed, 57 insertions(+), 24 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index c0a8709172..c3f05a96e6 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -10,6 +10,7 @@ export { default as Alphapolis } from './Alphapolis'; export { default as AnataNoMotokare } from './AnataNoMotokare'; export { default as AniGliScans } from './AniGliScans'; export { default as Anikiga } from './Anikiga'; +export { default as AnimeSama } from './AnimeSama'; export { default as Anisamanga } from './Anisamanga'; export { default as AnshScans } from './AnshScans'; export { default as AnzManga } from './AnzManga'; @@ -74,12 +75,14 @@ export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as ComikeyArchive } from './ComikeyArchive'; export { default as ConstellarScans } from './ConstellarScans'; +export { default as CopyManga } from './CopyManga'; export { default as CopyPasteScan } from './CopyPasteScan'; export { default as CosmicScans } from './CosmicScans'; export { default as CosmicScansID } from './CosmicScansID'; export { default as CovenScan } from './CovenScan'; export { default as CrunchyScan } from './CrunchyScan'; export { default as CyComi } from './CyComi'; +export { default as CypherScans } from './CypherScans'; export { default as DankeFursLesen } from './DankeFursLesen'; export { default as Daysneo } from './Daysneo'; export { default as DeathTollScans } from './DeathTollScans'; @@ -131,6 +134,7 @@ export { default as GanGanOnline } from './GanGanOnline'; export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as GekkouScans } from './GekkouScans'; export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; @@ -179,6 +183,7 @@ export { default as InfraFandub } from './InfraFandub'; export { default as InManga } from './InManga'; export { default as InmortalScan } from './InmortalScan'; export { default as InstaManhwa } from './InstaManhwa'; +export { default as iqiyi } from './iqiyi'; export { default as IrisScanlator } from './IrisScanlator'; export { default as IsekaiScan } from './IsekaiScan'; export { default as ItsYourRightManhua } from './ItsYourRightManhua'; @@ -186,9 +191,11 @@ export { default as JapScan } from './JapScan'; export { default as Jmana1 } from './Jmana1'; export { default as Jpmangas } from './Jpmangas'; export { default as KaiScans } from './KaiScans'; +export { default as Kakaopage } from './Kakaopage'; export { default as Kanjiku } from './Kanjiku'; export { default as Kanzenin } from './Kanzenin'; export { default as Katakomik } from './Katakomik'; +export { default as KingOfManga } from './KingOfManga'; export { default as Kiryuu } from './Kiryuu'; export { default as KissmangaIN } from './KissmangaIN'; export { default as KissmangaORG } from './KissmangaORG'; @@ -209,9 +216,11 @@ export { default as Komiku } from './Komiku'; export { default as KomikuCOM } from './KomikuCOM'; export { default as KSGroupScans } from './KSGroupScans'; export { default as Kuaikanmanhua } from './Kuaikanmanhua'; +export { default as kuimh } from './kuimh'; export { default as KumoTran } from './KumoTran'; export { default as KurageBunch } from './KurageBunch'; export { default as LamiManga } from './LamiManga'; +export { default as LeerCapitulo } from './LeerCapitulo'; export { default as LegacyScans } from './LegacyScans'; export { default as Leitor } from './Leitor'; export { default as LELManga } from './LELManga'; @@ -228,9 +237,11 @@ export { default as LireScan } from './LireScan'; export { default as LittleGarden } from './LittleGarden'; export { default as LSHiver } from './LSHiver'; export { default as LuminousScans } from './LuminousScans'; +export { default as LunarScans } from './LunarScans'; export { default as LupiTeam } from './LupiTeam'; export { default as Luscious } from './Luscious'; export { default as LynxScans } from './LynxScans'; +export { default as MadaraDex } from './MadaraDex'; export { default as MagComi } from './MagComi'; export { default as MagicalTranslators } from './MagicalTranslators'; export { default as MaID } from './MaID'; @@ -245,9 +256,11 @@ export { default as MangaAy } from './MangaAy'; export { default as MangaBat } from './MangaBat'; export { default as Mangabaz } from './Mangabaz'; export { default as MangaBob } from './MangaBob'; +export { default as Mangabox } from './Mangabox'; export { default as MangaBuddy } from './MangaBuddy'; export { default as MangaCanBlog } from './MangaCanBlog'; export { default as MangaChan } from './MangaChan'; +export { default as MangaChill } from './MangaChill'; export { default as Mangacim } from './Mangacim'; export { default as MangaClash } from './MangaClash'; export { default as MangaCrab } from './MangaCrab'; @@ -266,8 +279,9 @@ export { default as MangaForest } from './MangaForest'; export { default as MangaForFree } from './MangaForFree'; export { default as MangaFort } from './MangaFort'; export { default as MangaFox } from './MangaFox'; +export { default as MangaFoxFull } from './MangaFoxFull'; +export { default as MangaGecko } from './MangaGecko'; export { default as MangaGG } from './MangaGG'; -export { default as MangaGreat } from './MangaGreat'; export { default as MangaHasu } from './MangaHasu'; export { default as MangaHentai } from './MangaHentai'; export { default as MangaHere } from './MangaHere'; @@ -276,11 +290,10 @@ export { default as MangaID } from './MangaID'; export { default as MangaInn } from './MangaInn'; export { default as MangaIro } from './MangaIro'; export { default as MangaJar } from './MangaJar'; +export { default as Mangajp } from './Mangajp'; export { default as MangaKakalot } from './MangaKakalot'; export { default as MangaKatana } from './MangaKatana'; export { default as MangaKawaii } from './MangaKawaii'; -export { default as MangaKeyfi } from './MangaKeyfi'; -export { default as MangaKid } from './MangaKid'; export { default as MangaKik } from './MangaKik'; export { default as MangaKiss } from './MangaKiss'; export { default as MangaKita } from './MangaKita'; @@ -288,23 +301,38 @@ export { default as MangaKitsu } from './MangaKitsu'; export { default as MangaKomi } from './MangaKomi'; export { default as Mangakyo } from './Mangakyo'; export { default as Mangalek } from './Mangalek'; +export { default as MangaLib } from './MangaLib'; +export { default as MangaLife } from './MangaLife'; export { default as MangaLike } from './MangaLike'; +export { default as MangaLink } from './MangaLink'; export { default as MangaLover } from './MangaLover'; export { default as MangaMonarca } from './MangaMonarca'; -export { default as MangaNel } from './MangaNel'; +export { default as MangaNato } from './MangaNato'; export { default as MangaNexus } from './MangaNexus'; export { default as MangaOkur } from './MangaOkur'; +export { default as MangaOkuTR } from './MangaOkuTR'; +export { default as MangaOni } from './MangaOni'; +export { default as MangaOnlineTeam } from './MangaOnlineTeam'; +export { default as MangaOwlio } from './MangaOwlio'; +export { default as MangaPanda } from './MangaPanda'; +export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPro } from './MangaPro'; +export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; export { default as MangaReadCO } from './MangaReadCO'; export { default as MangaReader } from './MangaReader'; export { default as MangaRockTeam } from './MangaRockTeam'; export { default as MangaRocky } from './MangaRocky'; +export { default as MangaRolls } from './MangaRolls'; +export { default as MangaRomance } from './MangaRomance'; export { default as MangaRose } from './MangaRose'; export { default as MangaSail } from './MangaSail'; export { default as MangaScantrad } from './MangaScantrad'; export { default as MangasChan } from './MangasChan'; +export { default as MangaSect } from './MangaSect'; +export { default as MangaSee } from './MangaSee'; export { default as MangaSehri } from './MangaSehri'; export { default as MangaShiro } from './MangaShiro'; export { default as MangasOrigines } from './MangasOrigines'; @@ -327,7 +355,7 @@ export { default as MangaWOW } from './MangaWOW'; export { default as MangaWT } from './MangaWT'; export { default as MangaYeh } from './MangaYeh'; export { default as Mangaz } from './Mangaz'; -export { default as Mangkomik } from './Mangkomik'; +export { default as ManHatic } from './ManHatic'; export { default as ManhuaAZ } from './ManhuaAZ'; export { default as ManHuaDex } from './ManHuaDex'; export { default as ManhuaFast } from './ManhuaFast'; @@ -340,17 +368,24 @@ export { default as ManhuaScan } from './ManhuaScan'; export { default as Manhuass } from './Manhuass'; export { default as ManhuaUs } from './ManhuaUs'; export { default as Manhwa18 } from './Manhwa18'; +export { default as Manhwa18cc } from './Manhwa18cc'; +export { default as Manhwa68 } from './Manhwa68'; export { default as ManhwaEighteen } from './ManhwaEighteen'; +export { default as ManhwaFreak } from './ManhwaFreak'; export { default as ManhwaFull } from './ManhwaFull'; export { default as ManhwaHentai } from './ManhwaHentai'; export { default as ManhwaHentaiMe } from './ManhwaHentaiMe'; +export { default as ManhwaHub } from './ManhwaHub'; export { default as ManhwaIndo } from './ManhwaIndo'; export { default as Manhwaland } from './Manhwaland'; export { default as ManhwaLatino } from './ManhwaLatino'; +export { default as ManhwaList } from './ManhwaList'; export { default as ManhwaRaw } from './ManhwaRaw'; export { default as ManhwasNet } from './ManhwasNet'; export { default as ManhwaTop } from './ManhwaTop'; export { default as ManhwaWorld } from './ManhwaWorld'; +export { default as Manhwax } from './Manhwax'; +export { default as Manjanoon } from './Manjanoon'; export { default as ManmanApp } from './ManmanApp'; export { default as ManWe } from './ManWe'; export { default as ManyToon } from './ManyToon'; @@ -364,36 +399,49 @@ export { default as Migudm } from './Migudm'; export { default as MilfToon } from './MilfToon'; export { default as MindaFanSub } from './MindaFanSub'; export { default as MiniTwoScan } from './MiniTwoScan'; +export { default as mkzhan } from './mkzhan'; export { default as MMScans } from './MMScans'; export { default as ModeScanlator } from './ModeScanlator'; export { default as MomoNoHanaScan } from './MomoNoHanaScan'; export { default as MonochromeScans } from './MonochromeScans'; export { default as MonoManga } from './MonoManga'; export { default as MoonWitchInLove } from './MoonWitchInLove'; +export { default as NatsuID } from './NatsuID'; export { default as Nekomik } from './Nekomik'; export { default as NeoxScan } from './NeoxScan'; export { default as NeuManga } from './NeuManga'; export { default as NewType } from './NewType'; +export { default as NextScan } from './NextScan'; export { default as Ngomik } from './Ngomik'; +export { default as NHentaiCom } from './NHentaiCom'; export { default as NightComic } from './NightComic'; export { default as Nightow } from './Nightow'; +export { default as NightScans } from './NightScans'; export { default as NijiTranslations } from './NijiTranslations'; export { default as NineHentai } from './NineHentai'; +export { default as NirvanaManga } from './NirvanaManga'; +export { default as NitroManga } from './NitroManga'; export { default as NiveraFansub } from './NiveraFansub'; +export { default as Nonbiri } from './Nonbiri'; export { default as NoraNoFansub } from './NoraNoFansub'; +export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; -export { default as OzulScans } from './OzulScans'; +export { default as Oremanga } from './Oremanga'; +export { default as OrigamiOrpheans } from './OrigamiOrpheans'; +export { default as Otsugami } from './Otsugami'; export { default as PairOfTwo } from './PairOfTwo'; export { default as PatyScans } from './PatyScans'; export { default as PCNet } from './PCNet'; export { default as PelaTeam } from './PelaTeam'; export { default as Penlab } from './Penlab'; export { default as PhoenixScansIT } from './PhoenixScansIT'; +export { default as Piccoma } from './Piccoma'; +export { default as PiccomaFR } from './PiccomaFR'; export { default as PiedPiper } from './PiedPiper'; export { default as PijamaliKoi } from './PijamaliKoi'; export { default as PixivComics } from './PixivComics'; @@ -407,6 +455,7 @@ export { default as PrismaScan } from './PrismaScan'; export { default as ProjetoScanlator } from './ProjetoScanlator'; export { default as Pururin } from './Pururin'; export { default as Pzykosis666HFansub } from './Pzykosis666HFansub'; +export { default as QuantumScans } from './QuantumScans'; export { default as Rackus } from './Rackus'; export { default as RagnarokScan } from './RagnarokScan'; export { default as RaikiScan } from './RaikiScan'; @@ -453,6 +502,7 @@ export { default as SenManga } from './SenManga'; export { default as SenpaiEdiciones } from './SenpaiEdiciones'; export { default as SeriManga } from './SeriManga'; export { default as SetsuScans } from './SetsuScans'; +export { default as Seven8te } from './Seven8te'; export { default as ShadowMangas } from './ShadowMangas'; export { default as Shakai } from './Shakai'; export { default as SheaKomik } from './SheaKomik'; @@ -473,7 +523,6 @@ export { default as Siyahmelek } from './Siyahmelek'; export { default as StickHorse } from './StickHorse'; export { default as Sukima } from './Sukima'; export { default as SundayWebry } from './SundayWebry'; -export { default as SushiScanFR } from './SushiScanFR'; export { default as SushiScans } from './SushiScans'; export { default as SweetTimeScan } from './SweetTimeScan'; export { default as Tapread } from './Tapread'; @@ -526,6 +575,7 @@ export { default as Wnacg } from './Wnacg'; export { default as WonderlandWebtoons } from './WonderlandWebtoons'; export { default as WordHero } from './WordHero'; export { default as XCaliBRScans } from './XCaliBRScans'; +export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; @@ -571,7 +621,6 @@ export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; export { default as GammaPlus } from './legacy/GammaPlus'; -export { default as GekkouScans } from './legacy/GekkouScans'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -582,14 +631,11 @@ export { default as HoduComics } from './legacy/HoduComics'; export { default as HolyManga } from './legacy/HolyManga'; export { default as Imgur } from './legacy/Imgur'; export { default as ImiTui } from './legacy/ImiTui'; -export { default as iqiyi } from './legacy/iqiyi'; export { default as JapanRead } from './legacy/JapanRead'; export { default as JokerFansub } from './legacy/JokerFansub'; -export { default as kakaopage } from './legacy/kakaopage'; export { default as KanMan } from './legacy/KanMan'; export { default as KirishimaFansub } from './legacy/KirishimaFansub'; export { default as KissAway } from './legacy/KissAway'; -export { default as kuimh } from './legacy/kuimh'; export { default as kuman5 } from './legacy/kuman5'; export { default as KuManga } from './legacy/KuManga'; export { default as LectorManga } from './legacy/LectorManga'; @@ -604,7 +650,6 @@ export { default as LineWebtoonTH } from './legacy/LineWebtoonTH'; export { default as LineWebtoonTranslate } from './legacy/LineWebtoonTranslate'; export { default as LineWebtoonZH } from './legacy/LineWebtoonZH'; export { default as LxHentai } from './legacy/LxHentai'; -export { default as MagaParkPublisher } from './legacy/MagaParkPublisher'; export { default as MagKan } from './legacy/MagKan'; export { default as Manatoki } from './legacy/Manatoki'; export { default as Manga3x } from './legacy/Manga3x'; @@ -620,23 +665,14 @@ export { default as MangaHome } from './legacy/MangaHome'; export { default as MangaHub } from './legacy/MangaHub'; export { default as MangaKakalotFun } from './legacy/MangaKakalotFun'; export { default as MangaKu } from './legacy/MangaKu'; -export { default as MangaLife } from './legacy/MangaLife'; -export { default as MangaLink } from './legacy/MangaLink'; export { default as MangaLivre } from './legacy/MangaLivre'; -export { default as Manganelos } from './legacy/Manganelos'; -export { default as MangaOnline } from './legacy/MangaOnline'; -export { default as MangaOnlineBR } from './legacy/MangaOnlineBR'; export { default as MangaOnlineFun } from './legacy/MangaOnlineFun'; -export { default as MangaPanda } from './legacy/MangaPanda'; export { default as MangaPark } from './legacy/MangaPark'; export { default as MangaParkEN } from './legacy/MangaParkEN'; -export { default as MangaRaw } from './legacy/MangaRaw'; export { default as MangaReaderSite } from './legacy/MangaReaderSite'; export { default as MangaReaderTo } from './legacy/MangaReaderTo'; -export { default as MangaRomance } from './legacy/MangaRomance'; export { default as MangaRussia } from './legacy/MangaRussia'; export { default as MangAs } from './legacy/MangAs'; -export { default as MangaSee } from './legacy/MangaSee'; export { default as MangaShip } from './legacy/MangaShip'; export { default as MangaToonCN } from './legacy/MangaToonCN'; export { default as MangaToonEN } from './legacy/MangaToonEN'; @@ -653,7 +689,6 @@ export { default as ManhwasMen } from './legacy/ManhwasMen'; export { default as Manmankan } from './legacy/Manmankan'; export { default as MeioNovel } from './legacy/MeioNovel'; export { default as MintManga } from './legacy/MintManga'; -export { default as mkzhan } from './legacy/mkzhan'; export { default as MoreNovel } from './legacy/MoreNovel'; export { default as MuchoHentai } from './legacy/MuchoHentai'; export { default as MyAnimeListManga } from './legacy/MyAnimeListManga'; @@ -692,7 +727,6 @@ export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; export { default as SakuraManga } from './legacy/SakuraManga'; export { default as ScanManga } from './legacy/ScanManga'; export { default as SelfManga } from './legacy/SelfManga'; -export { default as Seven8te } from './legacy/Seven8te'; export { default as ShinobiScans } from './legacy/ShinobiScans'; export { default as ShonenJumpRookie } from './legacy/ShonenJumpRookie'; export { default as ShueishaMangaPlus } from './legacy/ShueishaMangaPlus'; @@ -744,7 +778,6 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as xianman123 } from './legacy/xianman123'; export { default as YesMangasBR } from './legacy/YesMangasBR'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 800d1c5a96f96e6c2bce8a2570134761dd620e67 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 13 Dec 2023 14:39:26 +0100 Subject: [PATCH 23/88] SpeedBinb : fix cookies problem --- .../engine/websites/decorators/SpeedBinb.ts | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 31cc1c7e84..1e7a46e351 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -1,4 +1,4 @@ -import { Fetch, FetchJSON, FetchRequest, FetchWindowCSS } from '../../FetchProvider'; +import { Fetch, FetchJSON, FetchRequest, FetchWindowScript } from '../../FetchProvider'; import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; @@ -65,6 +65,14 @@ type DescrambleKP = { u: string } +const JsonScript = ` + new Promise(resolve => { + fetch('{URI}') + .then(response => response.json()) + .then(json => resolve(json)) + }); +`; + function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base+'/'); baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); @@ -97,7 +105,7 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); const data = [...dom.querySelectorAll('div#content.pages')]; - //handle redirection + //handle redirection. Sometimes chapter is redirected if (response.redirected) { viewerUrl = new URL(response.url); } @@ -185,8 +193,7 @@ async function getPageList_v016452(scraper: MangaScraper, viewerURL: URL, apiEnd uri.searchParams.set('k', sharingKey); uri.searchParams.set('u0', u0); uri.searchParams.set('u1', u1); - const request = new FetchRequest(uri.href); - const data: JSONPageData_v016452 = await FetchJSON(request); + const data = await FetchJSON(new FetchRequest(uri.href)); const params: Params_v016452 = { cid, sharingKey, u0, u1 }; return await getPageLinks_v016452(scraper, data.items[0], params, baseURL, chapter); } @@ -234,11 +241,12 @@ async function getPageList_v016201(scraper: MangaScraper, viewerURL: URL, apiEnd uri.searchParams.set('k', sharingKey); uri.searchParams.set('u1', u); - let request = new FetchRequest(uri.href); - await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet + //let request = new FetchRequest(uri.href); + //await FetchWindowCSS(request, 'body');//dummy request set cookies for Youngjump + //const data: JSONPageData_v016452 = await FetchJSON(request - request = new FetchRequest(uri.href); - const data: JSONPageData_v016452 = await FetchJSON(request); + const request = new FetchRequest(uri.href); + const data = await FetchWindowScript(request, JsonScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(scraper, data.items[0], sharingKey, u, chapter); } @@ -291,10 +299,11 @@ async function getPageList_v016130(scraper: MangaScraper, chapterUrl: URL, apiEn uri.searchParams.set('k', sharingKey); const request = new FetchRequest(uri.href); - await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet + //await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet - const response = await fetch(new FetchRequest(uri.href)); - const data: JSONPageData_v016452 = await response.json(); + //const response = await Fetch(new FetchRequest(uri.href)); + //const data: JSONPageData_v016452 = await response.json(); + const data = await FetchWindowScript(request, JsonScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(scraper, data.items[0], sharingKey, baseURL, chapter); } From 684071d25b65f62e612296d690d43fe80168e30d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 13 Dec 2023 14:40:22 +0100 Subject: [PATCH 24/88] YoungJump : Fix ClipBoard --- web/src/engine/websites/YoungJump.ts | 14 +++++++++++-- web/src/engine/websites/YoungJump_e2e.ts | 26 ++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 2 deletions(-) create mode 100644 web/src/engine/websites/YoungJump_e2e.ts diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index 5131e4fa09..2f3d32c1cd 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -3,7 +3,7 @@ import icon from './YoungJump.webp'; import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchJSON, FetchRequest } from '../FetchProvider'; +import { FetchJSON, FetchRequest, FetchWindowScript } from '../FetchProvider'; type APIMagazine = { url: string, @@ -11,7 +11,6 @@ type APIMagazine = { number: string } -//@Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') @Common.ChaptersUniqueFromManga() @SpeedBinb.PagesSinglePage() @SpeedBinb.ImageAjax() @@ -25,6 +24,17 @@ export default class extends DecoratableMangaScraper { return icon; } + public override ValidateMangaURL(url: string): boolean { + return /^https:\/\/www\.youngjump\.world\/reader\/reader.html\?/.test(url); + } + + public override async FetchManga(provider: MangaPlugin, url: string): Promise { + const mangatitle = await FetchWindowScript(new FetchRequest(url), 'document.title', 3000); + const uri = new URL(url); + return new Manga(this, provider, uri.pathname + uri.search, mangatitle.trim()); + + } + public override async FetchMangas(provider: MangaPlugin): Promise { const request = new FetchRequest(new URL('/yj-rest-apis/getBookInfo.php', this.URI).href); const data = await FetchJSON(request); diff --git a/web/src/engine/websites/YoungJump_e2e.ts b/web/src/engine/websites/YoungJump_e2e.ts new file mode 100644 index 0000000000..81beed0089 --- /dev/null +++ b/web/src/engine/websites/YoungJump_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'youngjump', + title: 'となりのヤングジャンプ (Tonari no Young Jump)' + }, + /* Content is accebile after login + container: { + url: 'https://www.youngjump.world/reader/reader.html?cid=101012340&u1=10001', + id: '/reader/reader.html?cid=101012340&u1=10001', + title: '俺だけ不遇スキルの異世界召喚叛逆記~最弱スキル【吸収】が全てを飲み込むまで~' + }, + child: { + id: '/reader/reader.html?cid=101012340&u1=10001', + title: 'YJ2024_01 - 1' + }, + entry: { + index: 0, + size: 4_627_863, + type: 'image/png' + }*/ +}; + +const fixture = new TestFixture(config); +describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file From f456d8a259b673e04565de99e6e919fc298c1dec Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 13 Dec 2023 15:03:18 +0100 Subject: [PATCH 25/88] SpeedBinb : use DeScramble --- web/src/engine/websites/BookLive.ts | 2 +- web/src/engine/websites/Cmoa.ts | 2 +- web/src/engine/websites/ComicBrise.ts | 2 +- web/src/engine/websites/ComicMeteor.ts | 2 +- web/src/engine/websites/ComicPolaris.ts | 2 +- web/src/engine/websites/ComicRide.ts | 2 +- web/src/engine/websites/ComicValkyrie.ts | 2 +- web/src/engine/websites/DigitalMargaret.ts | 2 +- web/src/engine/websites/Futabanet.ts | 2 +- web/src/engine/websites/Getsuaku.ts | 2 +- web/src/engine/websites/MangaPlanet.ts | 2 +- web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/OneTwoThreeHon.ts | 2 +- web/src/engine/websites/Yanmaga.ts | 2 +- web/src/engine/websites/YoungJump.ts | 2 +- .../engine/websites/decorators/SpeedBinb.ts | 71 ++++++------------- 16 files changed, 35 insertions(+), 66 deletions(-) diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index 25a2ffe4ff..8b105d0332 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -12,7 +12,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index abe9d17312..614edaf58e 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -7,7 +7,7 @@ import { FetchCSS, FetchRequest } from '../FetchProvider'; @Common.MangaCSS(/^{origin}\/title\/\d+\/(vol\/\d+\/)?$/, '#GA_this_page_title_name') @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index a1729b2e3e..1e1a23f580 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -7,7 +7,7 @@ import { FetchCSS, FetchRequest } from '../FetchProvider'; @Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index b3cb3076a9..d6050ce105 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -13,7 +13,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index da29be72f4..5f5dbfd966 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -13,7 +13,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts index 86e85cff8a..8feae13bce 100644 --- a/web/src/engine/websites/ComicRide.ts +++ b/web/src/engine/websites/ComicRide.ts @@ -20,7 +20,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/', 'ul li.p-update-list__item', MangaExtractor) @Common.ChaptersSinglePageCSS('article.p-modal-org', ChapterExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 970889e932..064c39178d 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -19,7 +19,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 227296f6aa..3f8cc1b3dc 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -18,7 +18,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 20c2f07f7b..69d6300520 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -7,7 +7,7 @@ import { FetchCSS, FetchRequest } from '../FetchProvider'; @Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index 2b8c3d6040..7b5ff37edf 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -24,7 +24,7 @@ function MangaExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/episode\/[^/]+$/, 'div.detail__main h2.detail__title') @Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 2c48a0104e..fa3d048a2d 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -13,7 +13,7 @@ function MangaExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/comic\/[^/]+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 8047e6ac92..a28c42e3c9 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -28,7 +28,7 @@ export default class extends DecoratableMangaScraper { //find real reader url to send to SpeedBinb, since redirection is done by Javascript const data = await FetchCSS(new FetchRequest(chapter.Identifier), 'body'); const reallink = data[0].innerHTML.match(/location.href='(.*)'/)[1]; - return await SpeedBinb.FetchPagesSinglePage.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); + return await SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index 2dae6c7f28..d69cb7d34f 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -13,7 +13,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index f847c43e28..e6e5f3b082 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -33,7 +33,7 @@ new Promise(resolve => { @Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') @Common.MangasSinglePageCSS('/comics', 'a.ga-comics-book-item', MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 200) -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index 2f3d32c1cd..1993ad6e85 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -12,7 +12,7 @@ type APIMagazine = { } @Common.ChaptersUniqueFromManga() -@SpeedBinb.PagesSinglePage() +@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 1e7a46e351..b40a3de237 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -2,8 +2,7 @@ import { Fetch, FetchJSON, FetchRequest, FetchWindowScript } from '../../FetchPr import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; -import type { Numeric, Text } from '../../SettingsManager'; -import { Key as GlobalKey } from '../../SettingsGlobal'; +import DeScramble from '../../transformers/ImageDescrambler'; type JSONPageData_v016452 = { items: Configuration_v016452[] @@ -91,7 +90,7 @@ function getSanitizedURL(base: string, append: string): URL { * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages * @param baseUrl - sdcqds */ -export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { +export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { const websiteUrl = baseUrl ? new URL(baseUrl) : new URL(this.URI); let viewerUrl = new URL(chapter.Identifier, this.URI); const request = new FetchRequest(viewerUrl.href, { @@ -100,7 +99,6 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, } });//referer needed for ManpaPlanet - //const data = await FetchCSS(request, 'div#content.pages'); const response = await Fetch(request); const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); const data = [...dom.querySelectorAll('div#content.pages')]; @@ -139,15 +137,15 @@ export async function FetchPagesSinglePage(this: MangaScraper, chapter: Chapter, /** * A class decorator that adds the ability to extract all pages for a given chapter using the given CSS {@link query}. * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. - * @param baseUrl - sdcqds + * @param baseUrl - base url to use. Used to create full url when partial endpoint are found */ -export function PagesSinglePage(baseUrl = '') { +export function PagesSinglePageAjax(baseUrl = '') { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { Common.ThrowOnUnsupportedDecoratorContext(context); return class extends ctor { public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePage.call(this, chapter, baseUrl); + return FetchPagesSinglePageAjax.call(this, chapter, baseUrl); } }; }; @@ -388,7 +386,7 @@ async function getPageLinksContentJS_v016130(scraper: MangaScraper, configuratio //**************** async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configuration_v016452, chapter: Chapter) { - const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); + const data = await FetchJSON(new FetchRequest(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); @@ -415,19 +413,19 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si let promise; switch (true) { case page.Link.href.endsWith('ptimg.json'): - promise = await process_v016061(this, page, priority, signal, detectMimeType); + promise = await descramble_v016061(this, page, priority, signal, detectMimeType); break; case page.Link.href.includes('sbcGetImg'): - promise = await process_v016130(this, page, priority, signal, detectMimeType); + promise = await descramble_v016130(this, page, priority, signal, detectMimeType); break; case page.Link.href.includes('M_L.jpg'): - promise = await process_v016130(this, page, priority, signal, detectMimeType); + promise = await descramble_v016130(this, page, priority, signal, detectMimeType); break; case page.Link.href.includes('M_H.jpg'): - promise = await process_v016130(this, page, priority, signal, detectMimeType); + promise = await descramble_v016130(this, page, priority, signal, detectMimeType); break; case page.Link.href.includes('/img/'): - promise = await process_v016130(this, page, priority, signal, detectMimeType); + promise = await descramble_v016130(this, page, priority, signal, detectMimeType); break; default: promise = Promise.reject('Unsupported version of SpeedBinb reader!'); @@ -436,24 +434,15 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si return promise; } -async function process_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { - const data: JSONImageData_v016061 = await FetchJSON(new FetchRequest(page.Link.href)); +async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { + const data = await FetchJSON(new FetchRequest(page.Link.href)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); - const bmpdata = await createImageBitmap(imagedata); - return await descramble_v016061(bmpdata, data.views); -} -async function descramble_v016061(bitmap: ImageBitmap, views: PageView_v016061[]): Promise { - return new Promise(resolve => { - const view = views[0]; - const canvas = document.createElement('canvas'); - canvas.width = view.width; - canvas.height = view.height; - const ctx = canvas.getContext('2d'); + return DeScramble(imagedata, async (image, ctx) => { + const view = data.views[0]; for (const part of view.coords) { - // sample => 'i:119,4+107,150>428,900' const num = part.split(/[:,+>]/); const sourceX = parseInt(num[1]); const sourceY = parseInt(num[2]); @@ -461,34 +450,17 @@ async function descramble_v016061(bitmap: ImageBitmap, views: PageView_v016061[] const targetY = parseInt(num[6]); const partWidth = parseInt(num[3]); const partHeight = parseInt(num[4]); - ctx.drawImage(bitmap, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); + ctx.drawImage(image, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); } - canvas.toBlob(data => { - resolve(data); - }, 'image/png', parseFloat('90') / 100); }); } -async function process_v016130(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType: boolean): Promise { +async function descramble_v016130(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType: boolean): Promise { const imagedata: Blob = await Common.FetchImageAjax.call(scraper, page, priority, signal, detectMimeType); const descrambleKeyPair: DescrambleKP = JSON.parse(window.atob(page.Link.hash.slice(1))); - const bmpdata = await createImageBitmap(imagedata); - return await descramble_v016130(bmpdata, descrambleKeyPair); -} - -async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Promise { - return new Promise(resolve => { - - const settings = HakuNeko.SettingsManager.OpenScope(); - const format = settings.Get(GlobalKey.DescramblingFormat).Value; - const quality = settings.Get(GlobalKey.DescramblingQuality).Value; - - const view: PageView_v016130 = _getImageDescrambleCoords(keys.s, keys.u, bitmap.width, bitmap.height); - const canvas = document.createElement('canvas'); - canvas.width = view.width; - canvas.height = view.height; - const ctx = canvas.getContext('2d'); + return DeScramble(imagedata, async (image, ctx) => { + const view: PageView_v016130 = _getImageDescrambleCoords(descrambleKeyPair.s, descrambleKeyPair.u, image.width, image.height); for (const part of view.transfers[0].coords) { const sourceX = part.xsrc; const sourceY = part.ysrc; @@ -496,11 +468,8 @@ async function descramble_v016130(bitmap: ImageBitmap, keys: DescrambleKP): Prom const targetY = part.ydest; const partWidth = part.width; const partHeight = part.height; - ctx.drawImage(bitmap, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); + ctx.drawImage(image, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); } - canvas.toBlob(data => { - resolve(data); - }, format, quality / 100); }); } From 15be17270dfd4a2b65c6582c0abdc9c65dbf18fd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 13 Dec 2023 15:51:28 +0100 Subject: [PATCH 26/88] fix tests and delete ComiRide * using default deascrambler means changing image size :) => fix tests * ComicRide is now using ComiciViewer --- web/src/engine/websites/BookLive_e2e.ts | 2 +- web/src/engine/websites/Cmoa_e2e.ts | 2 +- web/src/engine/websites/ComicBrise_e2e.ts | 2 +- web/src/engine/websites/ComicMeteor_e2e.ts | 2 +- web/src/engine/websites/ComicPolaris_e2e.ts | 2 +- web/src/engine/websites/ComicRide.ts | 44 ------------------ web/src/engine/websites/ComicRide.webp | Bin 446 -> 0 bytes web/src/engine/websites/ComicRide_e2e.ts | 26 ----------- web/src/engine/websites/ComicValkyrie_e2e.ts | 2 +- .../engine/websites/DigitalMargaret_e2e.ts | 10 ++-- web/src/engine/websites/Futabanet_e2e.ts | 2 +- web/src/engine/websites/Getsuaku_e2e.ts | 2 +- web/src/engine/websites/MangaPlanet_e2e.ts | 2 +- web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/Ohtabooks_e2e.ts | 8 ++-- web/src/engine/websites/OneTwoThreeHon_e2e.ts | 2 +- web/src/engine/websites/Yanmaga_e2e.ts | 2 +- web/src/engine/websites/_index.ts | 1 - 18 files changed, 21 insertions(+), 92 deletions(-) delete mode 100644 web/src/engine/websites/ComicRide.ts delete mode 100644 web/src/engine/websites/ComicRide.webp delete mode 100644 web/src/engine/websites/ComicRide_e2e.ts diff --git a/web/src/engine/websites/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts index a34f364c1b..c6057b9abc 100644 --- a/web/src/engine/websites/BookLive_e2e.ts +++ b/web/src/engine/websites/BookLive_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 2_200_103, + size: 2_217_427, type: 'image/png' } }; diff --git a/web/src/engine/websites/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts index 2d42023204..878c0104b8 100644 --- a/web/src/engine/websites/Cmoa_e2e.ts +++ b/web/src/engine/websites/Cmoa_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 2_861_208, + size: 2_879_995, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicBrise_e2e.ts b/web/src/engine/websites/ComicBrise_e2e.ts index 934ce8b26c..9f02fb595e 100644 --- a/web/src/engine/websites/ComicBrise_e2e.ts +++ b/web/src/engine/websites/ComicBrise_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 4_580_541, + size: 4_606_656, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicMeteor_e2e.ts b/web/src/engine/websites/ComicMeteor_e2e.ts index c029f5b584..ada4d566cd 100644 --- a/web/src/engine/websites/ComicMeteor_e2e.ts +++ b/web/src/engine/websites/ComicMeteor_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 3_838_458, + size: 3_858_581, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicPolaris_e2e.ts b/web/src/engine/websites/ComicPolaris_e2e.ts index f25ec24f6d..00248baa89 100644 --- a/web/src/engine/websites/ComicPolaris_e2e.ts +++ b/web/src/engine/websites/ComicPolaris_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_854_679, + size: 1_864_432, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicRide.ts b/web/src/engine/websites/ComicRide.ts deleted file mode 100644 index 8feae13bce..0000000000 --- a/web/src/engine/websites/ComicRide.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './ComicRide.webp'; -import { DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import * as SpeedBinb from './decorators/SpeedBinb'; - -function MangaExtractor(element: HTMLElement) { - return { - id: element.querySelector('a.p-update-list__main').pathname.replace(/\/\//g, "/").replace('/index.html', '/'), - title: element.querySelector('.p-update-list__title').textContent.trim() - }; -} - -function ChapterExtractor(element: HTMLElement) { - return { - id: element.querySelector('span.p-backnumber-d__view a.u-over-opacity-img').pathname.replace(/\/\//g, "/"), - title: element.querySelector('.p-backnumber-d .p-backnumber-d__title').textContent.trim() - }; -} - -@Common.MangasSinglePageCSS('/', 'ul li.p-update-list__item', MangaExtractor) -@Common.ChaptersSinglePageCSS('article.p-modal-org', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() -@SpeedBinb.ImageAjax() -export default class extends DecoratableMangaScraper { - public constructor() { - super('comicride', `ComicRide`, 'https://www.comicride.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}/(/)?book/[^/]+/(index.html)?$`).test(url); - - } - - public override async FetchManga(provider: MangaPlugin, url: string): Promise { - return await Common.FetchMangaCSS.call(this, provider, url.replace(/\/\//g, "/").replace('/index.html', '/'), '.p-detail-head__title'); - - } - -} \ No newline at end of file diff --git a/web/src/engine/websites/ComicRide.webp b/web/src/engine/websites/ComicRide.webp deleted file mode 100644 index cf51ae3d888fb38445c9440c9fab9d8fda0c032c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 446 zcmV;v0YUy!Nk&Gt0RRA3MM6+kP&go}0RRAS3ILq}Dj)zL06uLhl0~E!SZvgY)^a1}z(=(_8pI_M5$pRz|YXO3pr;6VF`#=2_n-;lx zXpK+UZUZRJuoPeVjPig0{{P$_^sV|b>(D4?Hl=kEqL9wn|IfeuuNeR6JpzBX{fZfJ z8ES+D)qVft#r4_A3|>%LmVUq||N5I+1}8fxFldjJcsjnl?zr-Wx5~9^t>y9mIwlTh zx=8Qz2hUtPNm?2oEnPjW4pfEx{8M@)v9qvym#8F2TereVvc9SoEn{vhdwgrI5`mFmpFd$c1mE6zh22Eq zok;iFzHr;kyhu8-*ze3KOQ^={HBC|2)B{_DM@@G+^Yi59WG5>1^hE>6XPb<37VK+N zF=uhF#N`W8eHD9Pwn$!u4Oz6yW{fr1Ya7onu3s=p)@-(jk@|I)v44*N$MnZWEF)3q oqZ@{ixNnak-mi;qgtW7w(0V8O)!?~u(T;2O9;;9;#t;Ai0M(S*Pyhe` diff --git a/web/src/engine/websites/ComicRide_e2e.ts b/web/src/engine/websites/ComicRide_e2e.ts deleted file mode 100644 index 53b323fe34..0000000000 --- a/web/src/engine/websites/ComicRide_e2e.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { TestFixture, type Config } from '../../../test/WebsitesFixture'; - -const config: Config = { - plugin: { - id: 'comicride', - title: 'ComicRide', - timeout: 45000 - }, - container: { - url: 'https://www.comicride.jp//book/kamihatsu/index.html', //purposedly test a bad url like comicride can give us - id: '/book/kamihatsu/', - title: '神の遣いの少女は初恋の将軍にすべてを捧ぐ' - }, - child: { - id: '/viewer/kamihatsu/kamihatsu_001/', - title: '-第1話-' - }, - entry: { - index: 0, - size: 2_549_444, - 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/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts index e5d8a26759..1315d4c3f0 100644 --- a/web/src/engine/websites/ComicValkyrie_e2e.ts +++ b/web/src/engine/websites/ComicValkyrie_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_233_245, + size: 1_249_371, type: 'image/png' } }; diff --git a/web/src/engine/websites/DigitalMargaret_e2e.ts b/web/src/engine/websites/DigitalMargaret_e2e.ts index a7da6f1277..2eacbb3352 100644 --- a/web/src/engine/websites/DigitalMargaret_e2e.ts +++ b/web/src/engine/websites/DigitalMargaret_e2e.ts @@ -6,17 +6,17 @@ const config: Config = { title: 'デジタルマーガレット (Digital Margaret)' }, container: { - url: 'https://digitalmargaret.jp/detail/sakuranoyouna/', - id: '/detail/sakuranoyouna/', - title: '桜のような僕の恋人' + url: 'https://digitalmargaret.jp/detail/seijyokankin/', + id: '/detail/seijyokankin/', + title: '私、聖女。いま、監禁されているの' }, child: { - id: '/contents/sakuranoyouna/230101_1-1Tx3bCnGJ', + id: '/contents/seijyokankin/231001_1-17f812664eb968b5aab01e76f7c2a6335/', title: '第1-1話' }, entry: { index: 0, - size: 964_808, + size: 1_317_928, type: 'image/png' } }; diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index 8a192ff6fd..13eed60746 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_850_824, + size: 1_869_624, type: 'image/png' } }; diff --git a/web/src/engine/websites/Getsuaku_e2e.ts b/web/src/engine/websites/Getsuaku_e2e.ts index 1055cfe3d7..c3ede35b9b 100644 --- a/web/src/engine/websites/Getsuaku_e2e.ts +++ b/web/src/engine/websites/Getsuaku_e2e.ts @@ -17,7 +17,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_428_394, + size: 1_441_630, type: 'image/png' } }; diff --git a/web/src/engine/websites/MangaPlanet_e2e.ts b/web/src/engine/websites/MangaPlanet_e2e.ts index 32523bc058..807b567f6d 100644 --- a/web/src/engine/websites/MangaPlanet_e2e.ts +++ b/web/src/engine/websites/MangaPlanet_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_688_910, + size: 1_709_465, type: 'image/png' } }; diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index a28c42e3c9..68d993d998 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -17,7 +17,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { export default class extends DecoratableMangaScraper { public constructor() { - super('ohtabooks', `Ohtabooks`, 'http://webcomic.ohtabooks.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + super('ohtabooks', `Ohtabooks`, 'https://webcomic.ohtabooks.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); } public override get Icon() { diff --git a/web/src/engine/websites/Ohtabooks_e2e.ts b/web/src/engine/websites/Ohtabooks_e2e.ts index b2d068ab45..c5d7bac39a 100644 --- a/web/src/engine/websites/Ohtabooks_e2e.ts +++ b/web/src/engine/websites/Ohtabooks_e2e.ts @@ -12,10 +12,10 @@ const config: Config = { }, child: { id: 'https://yondemill.jp/contents/55155?view=1&u0=1', - title: '第1話「ご主人とゲーム」' - }, /* - //since page id redirect to another url, test is failing despites us getting images - //https://yondemill.jp/contents/55155?view=1&u0=1' redirect to https://binb.bricks.pub/contents/b0baf48e-9a1e-4ac7-b331-f4b978714dc7_1673856049/speed_reader + title: '第1話「ご主人とゲーム」', + timeout: 10000 + }, /*since page id redirect to another url, test is failing despites us getting images + https://yondemill.jp/contents/55155?view=1&u0=1' redirect to https://binb.bricks.pub/contents/b0baf48e-9a1e-4ac7-b331-f4b978714dc7_1673856049/speed_reader entry: { index: 0, size: 1_385_998, diff --git a/web/src/engine/websites/OneTwoThreeHon_e2e.ts b/web/src/engine/websites/OneTwoThreeHon_e2e.ts index b25a8322a2..0dac77d6e0 100644 --- a/web/src/engine/websites/OneTwoThreeHon_e2e.ts +++ b/web/src/engine/websites/OneTwoThreeHon_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_457_423, + size: 1_468_883, type: 'image/png' } }; diff --git a/web/src/engine/websites/Yanmaga_e2e.ts b/web/src/engine/websites/Yanmaga_e2e.ts index 383b970d65..2740edcf4d 100644 --- a/web/src/engine/websites/Yanmaga_e2e.ts +++ b/web/src/engine/websites/Yanmaga_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 2_071_327, + size: 2_088_299, type: 'image/png' } }; diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index c3f05a96e6..97226a8407 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -65,7 +65,6 @@ export { default as ComicK } from './ComicK'; export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicPolaris } from './ComicPolaris'; -export { default as ComicRide } from './ComicRide'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; From 9916cfa141db9270949a348e62fe400abed0ba5a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 15 Dec 2023 20:26:56 +0100 Subject: [PATCH 27/88] Update Yanmaga.ts --- web/src/engine/websites/Yanmaga.ts | 33 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index e6e5f3b082..2cc7a255a6 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -11,23 +11,22 @@ function MangaExtractor(anchor: HTMLAnchorElement) { } const chapterScript = ` -new Promise(resolve => { - const interval = setInterval(() => { - let morebtn = document.querySelector('.mod-episode-more-button') ; - if (morebtn) morebtn.click() - else { - clearInterval(interval); - const chapters = [...document.querySelectorAll('a.mod-episode-link')]; - resolve(chapters.map(chapter => { - return { - id: chapter.pathname, - title: chapter.querySelector('.mod-episode-title').textContent.trim() - } - })); - } - }, 1000); -}); - + new Promise(resolve => { + const interval = setInterval(() => { + let morebtn = document.querySelector('.mod-episode-more-button') ; + if (morebtn) morebtn.click() + else { + clearInterval(interval); + const chapters = [...document.querySelectorAll('a.mod-episode-link')]; + resolve(chapters.map(chapter => { + return { + id: chapter.pathname, + title: chapter.querySelector('.mod-episode-title').textContent.trim() + } + })); + } + }, 1000); + }); `; @Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') From a40151ba3e6735ca36d33ae586be7980b98140c7 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 21 Dec 2023 15:11:31 +0100 Subject: [PATCH 28/88] Update _index.ts --- web/src/engine/websites/_index.ts | 38 +++++++++++++++++++------------ 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 97226a8407..8e43f7f74a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -55,12 +55,13 @@ export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; export { default as ComicBrise } from './ComicBrise'; -export { default as ComicBushi } from './ComicBushi'; export { default as ComicDays } from './ComicDays'; +export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; export { default as ComicFuz } from './ComicFuz'; 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; @@ -87,6 +88,7 @@ export { default as Daysneo } from './Daysneo'; export { default as DeathTollScans } from './DeathTollScans'; export { default as DecadenceScans } from './DecadenceScans'; export { default as DemoneCeleste } from './DemoneCeleste'; +export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DigitalMargaret } from './DigitalMargaret'; @@ -98,6 +100,7 @@ export { default as Dmzj } from './Dmzj'; export { default as Doujin69 } from './Doujin69'; export { default as DoujinDesu } from './DoujinDesu'; export { default as DoujinHentai } from './DoujinHentai'; +export { default as Doujinku } from './Doujinku'; export { default as Doujins } from './Doujins'; export { default as DoujinZa } from './DoujinZa'; export { default as DragonTea } from './DragonTea'; @@ -111,6 +114,7 @@ export { default as EightMusesXXX } from './EightMusesXXX'; export { default as ElevenToon } from './ElevenToon'; export { default as EvilFlowers } from './EvilFlowers'; export { default as FallenAngelsScans } from './FallenAngelsScans'; +export { default as FayScans } from './FayScans'; export { default as FbSquads } from './FbSquads'; export { default as FenixScan } from './FenixScan'; export { default as FinalScans } from './FinalScans'; @@ -187,6 +191,7 @@ export { default as IrisScanlator } from './IrisScanlator'; export { default as IsekaiScan } from './IsekaiScan'; export { default as ItsYourRightManhua } from './ItsYourRightManhua'; export { default as JapScan } from './JapScan'; +export { default as JiangzaiToon } from './JiangzaiToon'; export { default as Jmana1 } from './Jmana1'; export { default as Jpmangas } from './Jpmangas'; export { default as KaiScans } from './KaiScans'; @@ -225,6 +230,7 @@ export { default as Leitor } from './Leitor'; export { default as LELManga } from './LELManga'; export { default as LELScan } from './LELScan'; export { default as LELScanVF } from './LELScanVF'; +export { default as LerYaoi } from './LerYaoi'; export { default as LeviatanScans } from './LeviatanScans'; export { default as LewdManhwa } from './LewdManhwa'; export { default as LHTranslation } from './LHTranslation'; @@ -296,7 +302,6 @@ export { default as MangaKawaii } from './MangaKawaii'; export { default as MangaKik } from './MangaKik'; export { default as MangaKiss } from './MangaKiss'; export { default as MangaKita } from './MangaKita'; -export { default as MangaKitsu } from './MangaKitsu'; export { default as MangaKomi } from './MangaKomi'; export { default as Mangakyo } from './Mangakyo'; export { default as Mangalek } from './Mangalek'; @@ -308,7 +313,7 @@ export { default as MangaLover } from './MangaLover'; export { default as MangaMonarca } from './MangaMonarca'; export { default as MangaNato } from './MangaNato'; export { default as MangaNexus } from './MangaNexus'; -export { default as MangaOkur } from './MangaOkur'; +export { default as MangaOku } from './MangaOku'; export { default as MangaOkuTR } from './MangaOkuTR'; export { default as MangaOni } from './MangaOni'; export { default as MangaOnlineTeam } from './MangaOnlineTeam'; @@ -340,7 +345,6 @@ export { default as MangaStarz } from './MangaStarz'; export { default as MangaSushi } from './MangaSushi'; export { default as MangaSY } from './MangaSY'; export { default as MangaTale } from './MangaTale'; -export { default as MangaTeca } from './MangaTeca'; export { default as Mangatellers } from './Mangatellers'; export { default as MangaTepesi } from './MangaTepesi'; export { default as MangaTitan } from './MangaTitan'; @@ -436,8 +440,10 @@ export { default as Otsugami } from './Otsugami'; export { default as PairOfTwo } from './PairOfTwo'; export { default as PatyScans } from './PatyScans'; export { default as PCNet } from './PCNet'; +export { default as PeanuToon } from './PeanuToon'; export { default as PelaTeam } from './PelaTeam'; export { default as Penlab } from './Penlab'; +export { default as PhenixScans } from './PhenixScans'; export { default as PhoenixScansIT } from './PhoenixScansIT'; export { default as Piccoma } from './Piccoma'; export { default as PiccomaFR } from './PiccomaFR'; @@ -450,7 +456,6 @@ export { default as PornComix } from './PornComix'; export { default as PornComixOnline } from './PornComixOnline'; export { default as PowerManga } from './PowerManga'; export { default as PrismaHentai } from './PrismaHentai'; -export { default as PrismaScan } from './PrismaScan'; export { default as ProjetoScanlator } from './ProjetoScanlator'; export { default as Pururin } from './Pururin'; export { default as Pzykosis666HFansub } from './Pzykosis666HFansub'; @@ -477,8 +482,12 @@ export { default as ReaperScans } from './ReaperScans'; export { default as ReaperScansBR } from './ReaperScansBR'; export { default as ReaperScansFR } from './ReaperScansFR'; export { default as ReaperScansTR } from './ReaperScansTR'; +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 RightDarkScan } from './RightDarkScan'; +export { default as Rio2Manga } from './Rio2Manga'; export { default as RizzComics } from './RizzComics'; export { default as RomantikManga } from './RomantikManga'; export { default as S2Manga } from './S2Manga'; @@ -486,12 +495,12 @@ export { default as Sadscans } from './Sadscans'; export { default as SamuraiScan } from './SamuraiScan'; export { default as ScamberTraslator } from './ScamberTraslator'; export { default as ScanFR } from './ScanFR'; -export { default as ScansMangas } from './ScansMangas'; export { default as ScansMangasme } from './ScansMangasme'; export { default as ScantradUnion } from './ScantradUnion'; export { default as ScanVF } from './ScanVF'; export { default as ScyllaScans } from './ScyllaScans'; export { default as SDLScans } from './SDLScans'; +export { default as SectScans } from './SectScans'; export { default as SeinagiAdultoFansub } from './SeinagiAdultoFansub'; export { default as SeinagiFansubEN } from './SeinagiFansubEN'; export { default as SeinagiFansubES } from './SeinagiFansubES'; @@ -507,9 +516,8 @@ export { default as Shakai } from './Shakai'; export { default as SheaKomik } from './SheaKomik'; export { default as SheepManga } from './SheepManga'; export { default as SheepMangaBroken } from './SheepMangaBroken'; -export { default as ShieldManga } from './ShieldManga'; -export { default as ShimadaScans } from './ShimadaScans'; export { default as ShinigamiID } from './ShinigamiID'; +export { default as Shirakami } from './Shirakami'; export { default as ShonenJumpPlus } from './ShonenJumpPlus'; export { default as ShonenMagazine } from './ShonenMagazine'; export { default as ShootingStarScans } from './ShootingStarScans'; @@ -519,8 +527,15 @@ export { default as SilentSkyScans } from './SilentSkyScans'; export { default as SinensisScan } from './SinensisScan'; export { default as SirenKomik } from './SirenKomik'; export { default as Siyahmelek } from './Siyahmelek'; +export { default as SkyMangas } from './SkyMangas'; +export { default as SMangaVF } from './SMangaVF'; +export { default as SoulScans } from './SoulScans'; export { default as StickHorse } from './StickHorse'; +export { default as Submanga } from './Submanga'; +export { default as SugarLab } from './SugarLab'; export { default as Sukima } from './Sukima'; +export { default as SumManga } from './SumManga'; +export { default as Summertoon } from './Summertoon'; export { default as SundayWebry } from './SundayWebry'; export { default as SushiScans } from './SushiScans'; export { default as SweetTimeScan } from './SweetTimeScan'; @@ -532,6 +547,7 @@ export { default as TecnoScan } from './TecnoScan'; export { default as Tempestfansub } from './Tempestfansub'; export { default as TenshiID } from './TenshiID'; export { default as TheGuildScans } from './TheGuildScans'; +export { default as TitanManga } from './TitanManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; export { default as ToonGod } from './ToonGod'; @@ -552,7 +568,6 @@ export { default as TuMangaOnlineHentai } from './TuMangaOnlineHentai'; export { default as TuManhwas } from './TuManhwas'; export { default as Turktoon } from './Turktoon'; export { default as TvYManga } from './TvYManga'; -export { default as UnionMangas } from './UnionMangas'; export { default as UraSunday } from './UraSunday'; export { default as UzayManga } from './UzayManga'; export { default as ViyaFansub } from './ViyaFansub'; @@ -607,7 +622,6 @@ export { default as BilibiliManhua } from './legacy/BilibiliManhua'; export { default as CocoManHua } from './legacy/CocoManHua'; export { default as ComicBoost } from './legacy/ComicBoost'; export { default as ComicBunch } from './legacy/ComicBunch'; -export { default as ComicEarthStar } from './legacy/ComicEarthStar'; export { default as ComicFire } from './legacy/ComicFire'; export { default as COMICMeDu } from './legacy/COMICMeDu'; export { default as CopyToon } from './legacy/CopyToon'; @@ -718,10 +732,7 @@ export { default as NovelRingan } from './legacy/NovelRingan'; export { default as OnePieceTube } from './legacy/OnePieceTube'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; -export { default as Qimiaomh } from './legacy/Qimiaomh'; export { default as RawMangatop } from './legacy/RawMangatop'; -export { default as ReadHentaiManga } from './legacy/ReadHentaiManga'; -export { default as Remangas } from './legacy/Remangas'; export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; export { default as SakuraManga } from './legacy/SakuraManga'; export { default as ScanManga } from './legacy/ScanManga'; @@ -736,7 +747,6 @@ export { default as SleepyTranslations } from './legacy/SleepyTranslations'; export { default as SoftKomik } from './legacy/SoftKomik'; export { default as SouDongMan } from './legacy/SouDongMan'; export { default as StoriaDash } from './legacy/StoriaDash'; -export { default as Submanga } from './legacy/Submanga'; export { default as TAADD } from './legacy/TAADD'; export { default as TaoManhua } from './legacy/TaoManhua'; export { default as Tapas } from './legacy/Tapas'; From 3beb3df96ac5f21275d7e2f77be694e10099f30a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 23 Dec 2023 16:24:21 +0100 Subject: [PATCH 29/88] Update YoungJump_e2e.ts --- web/src/engine/websites/YoungJump_e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/YoungJump_e2e.ts b/web/src/engine/websites/YoungJump_e2e.ts index 81beed0089..e538b03eed 100644 --- a/web/src/engine/websites/YoungJump_e2e.ts +++ b/web/src/engine/websites/YoungJump_e2e.ts @@ -5,7 +5,7 @@ const config = { id: 'youngjump', title: 'となりのヤングジャンプ (Tonari no Young Jump)' }, - /* Content is accebile after login + /* Content is accessible after login container: { url: 'https://www.youngjump.world/reader/reader.html?cid=101012340&u1=10001', id: '/reader/reader.html?cid=101012340&u1=10001', From 34e74687b49b632072ec2a5ca62466d28b2901ec Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 29 Dec 2023 18:56:44 +0100 Subject: [PATCH 30/88] cmoa : fix paginated chapters and manga regex --- web/src/engine/websites/Cmoa.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 614edaf58e..4bbd2550b0 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^{origin}\/title\/\d+\/(vol\/\d+\/)?$/, '#GA_this_page_title_name') +@Common.MangaCSS(/^{origin}\/title\/\d+(\/vol\/\d+\/)?$/, '#GA_this_page_title_name') @Common.MangasNotSupported() @SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() @@ -19,9 +19,9 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); - const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li'); + const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li:nth-last-child(2) a'); const chapters = []; - const totalPage = pages.length == 0 ? 1 : pages.length - 1; + const totalPage = pages.length == 0 ? 1 : parseInt(new URL(pages[0].href).searchParams.get('page')); for (let i = 0; i < totalPage; i++) { const uri = new URL(manga.Identifier, this.URI); uri.searchParams.set('page', String(i + 1)); From 2fb4e05bd168c2fb78ef893a16c680628c09ac23 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 30 Dec 2023 14:47:56 +0100 Subject: [PATCH 31/88] Update _index.ts --- web/src/engine/websites/_index.ts | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 49c77a4439..1491cbf36a 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -38,6 +38,7 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -46,11 +47,13 @@ export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CizgiRomanArsivi } from './CizgiRomanArsivi'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColoredManga } from './ColoredManga'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -59,10 +62,13 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicWalker } from './ComicWalker'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -84,6 +90,7 @@ export { default as DemoneCeleste } from './DemoneCeleste'; export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -121,6 +128,7 @@ export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FRScan } from './FRScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -129,6 +137,7 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GekkouScans } from './GekkouScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; export { default as Gntai } from './Gntai'; @@ -311,6 +320,7 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -419,7 +429,9 @@ export { default as Nonbiri } from './Nonbiri'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -588,12 +600,14 @@ export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; export { default as YaoiScan } from './YaoiScan'; export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YawarakaSpirits } from './YawarakaSpirits'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasES } from './YugenMangasES'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; @@ -615,16 +629,11 @@ export { default as AstralLibrary } from './legacy/AstralLibrary'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -634,7 +643,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -731,9 +739,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RawMangatop } from './legacy/RawMangatop'; @@ -789,6 +795,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 65ea78b68352b3a3c3e42249907622ba7df1c689 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 17:06:30 +0100 Subject: [PATCH 32/88] 123Hon : remove debug --- web/src/engine/websites/OneTwoThreeHon.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index d69cb7d34f..6a3c3ef36c 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -6,7 +6,6 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { - console.log(anchor.pathname); const id = anchor.pathname; const title = anchor.pathname.match(/[^/]+\/web-comic\/([^/]+)\//)[1]; return { id, title }; From b2bb34e515329c27c7f27b2ffb73548ed50edb21 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 17:07:21 +0100 Subject: [PATCH 33/88] booklive : fix chapter gathering --- web/src/engine/websites/BookLive.ts | 9 +++++---- web/src/engine/websites/BookLive_e2e.ts | 6 +++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index 8b105d0332..e84bbcdeea 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -4,14 +4,15 @@ import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; function ChapterExtractor(element: HTMLElement) { - const id = '/bviewer/s/?cid=' + element.dataset.title + '_' + element.dataset.vol; - const title = element.dataset.vol.trim(); + const linkElement = element.querySelector('a.bl-bviewer'); + const id = '/bviewer/s/?cid=' + linkElement.dataset.title + '_' + linkElement.dataset.vol; + const title = element.querySelector('a.cart_action').dataset.vol.trim(); return { id, title }; } -@Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'div#product_detail_area div.product_info > h1#product_display_1') +@Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'li.contents span.book_title') @Common.MangasNotSupported() -@Common.ChaptersSinglePageCSS('div#product_detail_area div.product_actions ul a.bl-bviewer', ChapterExtractor) +@Common.ChaptersSinglePageCSS('div#slide_up_top li.item div.buttons', ChapterExtractor) @SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() diff --git a/web/src/engine/websites/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts index c6057b9abc..081189421e 100644 --- a/web/src/engine/websites/BookLive_e2e.ts +++ b/web/src/engine/websites/BookLive_e2e.ts @@ -8,15 +8,15 @@ const config: Config = { container: { url: 'https://booklive.jp/product/index/title_id/20063601/vol_no/001', id: '/product/index/title_id/20063601/vol_no/001', - title: '火の神さまの掃除人ですが、いつの間にか花嫁として溺愛されています【単話】 1' + title: '火の神さまの掃除人ですが、いつの間にか花嫁として溺愛されています【単話】' }, child: { - id: '/bviewer/s/?cid=60095158_001', + id: '/bviewer/s/?cid=20063601_001', title: '001' }, entry: { index: 0, - size: 2_217_427, + size: 2_218_525, type: 'image/png' } }; From f381c7c7be527e1c2964a5d794a94000db5ac5d9 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 17:12:59 +0100 Subject: [PATCH 34/88] Cmoa fixes manga id --- web/src/engine/websites/Cmoa.ts | 12 ++++++++++-- web/src/engine/websites/Cmoa_e2e.ts | 2 +- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 4bbd2550b0..9ef7ad5c6f 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -1,11 +1,10 @@ import { Tags } from '../Tags'; import icon from './Cmoa.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type MangaPlugin, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchRequest } from '../FetchProvider'; -@Common.MangaCSS(/^{origin}\/title\/\d+(\/vol\/\d+\/)?$/, '#GA_this_page_title_name') @Common.MangasNotSupported() @SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() @@ -17,6 +16,15 @@ export default class extends DecoratableMangaScraper { return icon; } + public override ValidateMangaURL(url: string): boolean { + return /https:\/\/www\.cmoa\.jp\/title\/\d+\/(vol\/\d+\/)?$/.test(url); + } + + public override async FetchManga(provider: MangaPlugin, url: string): Promise { + const newUrl = url.replace(/\/vol\/\d+\/$/, '/'); + return await Common.FetchMangaCSS.call(this, provider, newUrl, '#GA_this_page_title_name'); + } + public override async FetchChapters(manga: Manga): Promise { const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li:nth-last-child(2) a'); diff --git a/web/src/engine/websites/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts index 878c0104b8..6241f6d6df 100644 --- a/web/src/engine/websites/Cmoa_e2e.ts +++ b/web/src/engine/websites/Cmoa_e2e.ts @@ -7,7 +7,7 @@ const config: Config = { }, container: { url: 'https://www.cmoa.jp/title/151961/vol/24/', - id: '/title/151961/vol/24/', + id: '/title/151961/', title: '呪術廻戦' }, child: { From dae7b902c988ba84e57cf01e366d35f2e88e8701 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 17:13:22 +0100 Subject: [PATCH 35/88] Fix ComicPolaris icon --- web/src/engine/websites/ComicPolaris.webp | Bin 1302 -> 736 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/web/src/engine/websites/ComicPolaris.webp b/web/src/engine/websites/ComicPolaris.webp index 4382357e097b403b1bb5084b2ca74064a01e5e01..a18789f9567cc1218629aac6b53e7b654ae59931 100644 GIT binary patch literal 736 zcmV<60w4WSNk&H40ssJ4MM6+kP&gpW0ssK;4FH`1DnI~006v96p-`nGqav^v4fvoC zfCDo8-#G2GMyGDh;?FyNqFv=0?GF$G1G5akl>^;)I7dt)rL10ZU0YDY5phz^vWH~Z z6HTLz92SCd(dRE3;VkWN#Vp@AUO#oh_^9)0n7yC0cHJ!nVfDIsJd8j9{`p%=x(W^h zXfXrOs1#MSO)(d_97hW?fk|JLW!t6(?K9{H07_*To_g8o9)mM@ADfjyZo8V?`tH4C ztwV5;d9H;(e+zD0F++*I7gXr=0~XR~d_xgv_x<{FS8MA#U?MkMEC+VWo_9M#!5*#n zB*S=*?SbkiSQepY_8c{9%+)!b#1Agg`mG~c;7r8TY*Q_7zy5)r zMiC?SzmPc(b0+Rm8cnMdDpsgdU_wzA0s~QP#5KjSr?fF=tsDva;>USN!2VG{RncN3 zF)}In4n*@DaXm}`XY>YKL*R6p-yl_9>Q69&W8M#IC?RI7+37z*%ScIl!tDo+fZKQkIp zzN0vEiR{O+9^`T{GfWG+a^W8L^zom6A(BO=k)J&*-F8PEGC#MmlBOrZ)yOh7jvCj^dtFQ-?LL${PSyx4B_;u>^V!dlI)6WQ9e(Xk@q`?sff9w SoA`?=Gw@06{>#*~`2YYCbX?y6 literal 1302 zcmV+x1?l=yNk&Ev1pok7MM6+kP&gn01pol>766?ADnI~006x)DqfDqIBO)>P86f}~ z31$F-qvA#Zem^JuVPF3T`)~h1AMN+RH-Ue6xIgrPcQ^KL0Dofj?2N$^f1UR2*bm|V z{P}=?5B)0iHF<)_KCi?Fc`g)R|N3}&Yk#r+tI=20pJsnapQ-=u4}Dda%hE-X@x zQz#KBoEwwdQ^kbs@P2Ge>FKsIz~rSO2YUVUOBw;}v9LwALOA*wtnKsN1?6gFoIbz+{^(Pw-0M4r+X*xs6D zihGo48cM6FnAjRWUhp2;K^6#+Wq_r}*qD`J>v#YEkb3!H{gEEEkL-CUyzv|m;M@Kj z-qh$SB%Jl;JS#NQg^;uf|D&Hz^gMNpo0=WjIBi|X1UO~*7||9HV-^ZjmZ$G5?$2eI z1|dBt?v&j#2Gf0g*|vTT33k%JjRxO~C#Y9#h!6_;Y(xps12_*O>6E(@qs) zXM(kCC5h+|R&9f7j^j16o+aN$$)WX4^eOw+oOmJrW|9Kc)M=M+}a zgN_tNf7IZadS8lUuzfk81>L7DF1;w2 z%Eg0;R;ZqPBXP@nMV03N`5(2tQ{0QYhS3|ZJW(&*0pqSEyCPd=iVuv&g6ZC(HX=*-lWHp`x5JV$1{>zJ2HKxFXVK z#zh*_x(_Ulr0?`8D;5^dRqDF`fiz+o09jMd;InJP`?m7CWolod<*&|bon5Ak;;|=m zDM~j%DaW;9lsxK%U=RA#z=k}06buKOw%vHRgF5*_7Y~^K-k*g(ePXLUmT}>E#6cSZ z#Veu%G;{{li`V{r&I7=FQ8va=@8+-%|JcJ(9 zH57fyio`;)pYRGrAzDMmLNoklk?qOv?UnBZm;>yh8{ojIj?(+UItkd_DuDXXKnxv4~ALQsru6-pUoc zIA%qZZqxFE{uM~%)#+m)z*FTjr6(hMH&_w>*{#itdPRW zo`md)k{I7c9U#*;aK?#f6YunWhDVPGR`xNm2@^l}%)h!M MMD!7OtQA}U0EN_%K>z>% From 0a5e74b198c52e43dfbe6b5c32aa3e63dad70703 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 17:55:30 +0100 Subject: [PATCH 36/88] ComicValkyrie : small code chanages --- web/src/engine/websites/ComicValkyrie.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 064c39178d..4457659633 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -34,10 +34,8 @@ export default class extends DecoratableMangaScraper { } public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const uri = new URL(url); - const request = new FetchRequest(uri.href); - const data = await FetchCSS(request, 'meta[property = "og:title"]'); - const id = uri.pathname.replace('/new.html', '/'); + const data = await FetchCSS(new FetchRequest(url), 'meta[property = "og:title"]'); + const id = new URL(url).pathname.replace('/new.html', '/'); const title = data[0].content.replace(/\s*THE COMIC\s*/i, '').trim(); return new Manga(this, provider, id, title); } From 12551a8253c04b04ac4c5d5742ac43d2816479e5 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 14 Jan 2024 18:25:07 +0100 Subject: [PATCH 37/88] SpeedBinb : code refactoring --- .../engine/websites/decorators/SpeedBinb.ts | 371 +++++++----------- 1 file changed, 135 insertions(+), 236 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index b40a3de237..f3268e4443 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -9,14 +9,14 @@ type JSONPageData_v016452 = { } type Configuration_v016452 = { - ContentID : string, + ContentID: string, ctbl: string[], ptbl: string[], ServerType: number | string ContentsServer: string, p: string, ViewMode: number, - ContentDate : string + ContentDate: string } type Params_v016452 = { @@ -37,13 +37,13 @@ type JSONImageData_v016061 = { type PageView_v016061 = { coords: string[], width: number, - height : number + height: number } type PageView_v016130 = { transfers: { coords: { - height : number, + height: number, width: number, xdest: number, xsrc: number, @@ -64,21 +64,40 @@ type DescrambleKP = { u: string } -const JsonScript = ` +const JsonFetchScript = ` new Promise(resolve => { fetch('{URI}') .then(response => response.json()) .then(json => resolve(json)) }); `; - +enum SpeedBinbVersion { v016113, v016201, v016452, v016130, _default_v016061, vUnknown } function getSanitizedURL(base: string, append: string): URL { - const baseURI = new URL(append, base+'/'); + const baseURI = new URL(append, base + '/'); baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); return baseURI; } +function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion { + if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { + return SpeedBinbVersion.v016113; + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u0') && viewerUrl.searchParams.get('u1')) { + return SpeedBinbVersion.v016452; + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u1')) { + return SpeedBinbVersion.v016201; + } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { + return SpeedBinbVersion.v016130; + } + if (el.querySelectorAll('div[data-ptimg$="ptimg.json"]').length > 0) { + return SpeedBinbVersion._default_v016061; + } + return SpeedBinbVersion.vUnknown; +} + /********************************************** ******** Page List Extraction Methods ******** **********************************************/ @@ -88,11 +107,11 @@ function getSanitizedURL(base: string, append: string): URL { * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages - * @param baseUrl - sdcqds + * @param baseUrl - Override base chapter url */ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { - const websiteUrl = baseUrl ? new URL(baseUrl) : new URL(this.URI); - let viewerUrl = new URL(chapter.Identifier, this.URI); + const websiteUrl = baseUrl ? new URL(baseUrl).href : new URL(this.URI).href; + let viewerUrl = new URL(chapter.Identifier, websiteUrl); const request = new FetchRequest(viewerUrl.href, { headers: { Referer: this.URI.href @@ -102,33 +121,59 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const response = await Fetch(request); const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); const data = [...dom.querySelectorAll('div#content.pages')]; + if (data.length == 0) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully //handle redirection. Sometimes chapter is redirected if (response.redirected) { viewerUrl = new URL(response.url); } - if (data.length == 0) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully const el = data[0]; + const SBVersion = getSpeedBinbVersion(el, viewerUrl); - if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { + if (SBVersion == SpeedBinbVersion.v016113) { viewerUrl.searchParams.set('cid', el.dataset['ptbinbCid']); - return await getPageList_v016113(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); } - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u0') && viewerUrl.searchParams.get('u1')) { - return await getPageList_v016452(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); - } - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u1')) { - return await getPageList_v016201(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); - } - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { - return await getPageList_v016130(this, viewerUrl, el.dataset.ptbinb, websiteUrl.href, chapter); + //Handle _default_v016061 : there is no parameter at all + //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon + if (SBVersion == SpeedBinbVersion._default_v016061) { + const [...imageConfigurations] = el.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + return imageConfigurations.map(element => { + return new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg)); + }); } - const imageConfigurations = el.querySelectorAll('div[data-ptimg$="ptimg.json"]'); - if (imageConfigurations.length > 0) { - return await getPageList_v016061(this, viewerUrl.href, [...imageConfigurations], chapter); + const cid = viewerUrl.searchParams.get('cid'); + const sharingKey = _tt(cid); + const uri = getSanitizedURL(websiteUrl, el.dataset.ptbinb); + uri.searchParams.set('cid', cid); + uri.searchParams.set('dmytime', String(Date.now())); + uri.searchParams.set('k', sharingKey); + + switch (SBVersion) { + case SpeedBinbVersion.v016113: //Futabanet, Getsuaku (v016700), Ohtabooks + case SpeedBinbVersion.v016130: { //Booklive, MangaPlanet, Yanmaga + const data = await FetchWindowScript(new FetchRequest(uri.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); + } + //YoungJump + case SpeedBinbVersion.v016201: { + const u = viewerUrl.searchParams.get('u1'); + uri.searchParams.set('u1', u); + const data = await FetchWindowScript(new FetchRequest(uri.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); + } + //Cmoa + case SpeedBinbVersion.v016452: { + const u0 = viewerUrl.searchParams.get('u0'); + const u1 = viewerUrl.searchParams.get('u1'); + uri.searchParams.set('u0', u0); + uri.searchParams.set('u1', u1); + const data = await FetchJSON(new FetchRequest(uri.href)); + const params: Params_v016452 = { cid, sharingKey, u0, u1 }; + return await getPageLinks_v016452(this, data.items[0], params, chapter); + } } throw new Error('Unsupported version of SpeedBinb reader!'); @@ -151,51 +196,7 @@ export function PagesSinglePageAjax(baseUrl = '') { }; } -/** -************************* -*** SpeedBinb v01.6061 *** -* ** Comic Meteor, Comic Valkyrie, DigitalMargaRet, ComicBrise, ComicRide -************************* -*/ -async function getPageList_v016061(scraper: MangaScraper, url: string, imageConfigurations: HTMLDivElement[], chapter: Chapter): Promise { - return imageConfigurations.map(element => { - return new Page(scraper, chapter, getSanitizedURL(url, element.dataset.ptimg)); - }); -} - -/** - ************************* - *** SpeedBinb v01.6113 *** - * ** Ohtabooks, Futabanet*** - * Getsuaku, which is v01.6700 - ************************* - */ -async function getPageList_v016113(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { - return await getPageList_v016130(scraper, viewerURL, apiEndpoint, baseURL, chapter); -} - -/** - ************************* - *** SpeedBinb v01.6452 *** - * ** Cmoa *** - ************************* - */ -async function getPageList_v016452(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter,): Promise { - const cid = viewerURL.searchParams.get('cid'); - const u0 = viewerURL.searchParams.get('u0'); - const u1 = viewerURL.searchParams.get('u1'); - const sharingKey = _tt(cid); - const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); - uri.searchParams.set('cid', cid); - uri.searchParams.set('dmytime', String(Date.now())); - uri.searchParams.set('k', sharingKey); - uri.searchParams.set('u0', u0); - uri.searchParams.set('u1', u1); - const data = await FetchJSON(new FetchRequest(uri.href)); - const params: Params_v016452 = { cid, sharingKey, u0, u1 }; - return await getPageLinks_v016452(scraper, data.items[0], params, baseURL, chapter); -} -async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter): Promise { +async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, chapter: Chapter): Promise { configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl); configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl); try { @@ -204,51 +205,20 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config // } if (configuration.ServerType === 0) { - return await getPageLinksSBC_v016452(scraper, configuration, params, baseURL, chapter); + const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); + uri.searchParams.set('cid', params.cid); + uri.searchParams.set('p', configuration.p); + uri.searchParams.set('q', '1'); + uri.searchParams.set('vm', String(configuration.ViewMode)); + uri.searchParams.set('dmytime', configuration.ContentDate); + uri.searchParams.set('u0', params.u0); + uri.searchParams.set('u1', params.u1); + return await fetchSBC(scraper, uri, configuration, chapter); } return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinksSBC_v016452(scraper : MangaScraper, configuration: Configuration_v016452, params: Params_v016452, baseURL: string, chapter: Chapter) { - //const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); - const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); - uri.searchParams.set('cid', params.cid); - uri.searchParams.set('p', configuration.p); - uri.searchParams.set('q', '1'); - uri.searchParams.set('vm', String(configuration.ViewMode)); - uri.searchParams.set('dmytime', configuration.ContentDate); - uri.searchParams.set('u0', params.u0); - uri.searchParams.set('u1', params.u1); - return await fetchSBC(scraper, uri, configuration, chapter); -} - -/** -************************* -*** SpeedBinb v01.6201 *** -* ** YoungJump *** -************************* -*/ - -async function getPageList_v016201(scraper: MangaScraper, viewerURL: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { - const cid = viewerURL.searchParams.get('cid'); - const u = viewerURL.searchParams.get('u1'); - const sharingKey = _tt(cid); - const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); - uri.searchParams.set('cid', cid); - uri.searchParams.set('dmytime', String(Date.now())); - uri.searchParams.set('k', sharingKey); - uri.searchParams.set('u1', u); - - //let request = new FetchRequest(uri.href); - //await FetchWindowCSS(request, 'body');//dummy request set cookies for Youngjump - //const data: JSONPageData_v016452 = await FetchJSON(request - - const request = new FetchRequest(uri.href); - const data = await FetchWindowScript(request, JsonScript.replace('{URI}', uri.href), 2000); - return await getPageLinks_v016201(scraper, data.items[0], sharingKey, u, chapter); -} - -async function getPageLinks_v016201(scraper : MangaScraper, configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { +async function getPageLinks_v016201(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); @@ -259,59 +229,23 @@ async function getPageLinks_v016201(scraper : MangaScraper, configuration: Confi } if (configuration.ServerType === 2) { - return await _getPageLinksContent_v016201(scraper, configuration, u, chapter); + const uri = getSanitizedURL(configuration.ContentsServer, 'content'); + uri.searchParams.set('dmytime', configuration.ContentDate); + uri.searchParams.set('u1', u); + const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); + const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + const src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + }); + return pageLinks; } return Promise.reject(new Error('Content server type not supported!')); } -async function _getPageLinksContent_v016201(scraper: MangaScraper, configuration: Configuration_v016452, u: string, chapter: Chapter): Promise { - //const uri = new URL(configuration.ContentsServer); - //uri.pathname += '/content'; - //uri.pathname = uri.pathname.replaceAll(/\/\/+/g, '/'); - const uri = getSanitizedURL(configuration.ContentsServer, 'content'); - - uri.searchParams.set('dmytime', configuration.ContentDate); - uri.searchParams.set('u1', u); - const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); - const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); - return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); - }); - return pageLinks; -} - -/** - ***************************** - *** SpeedBinb v01.6130 ****** - * ** BookLive, MangaPlanet, Yanmaga*** - ***************************** - */ - -async function getPageList_v016130(scraper: MangaScraper, chapterUrl: URL, apiEndpoint: string, baseURL: string, chapter: Chapter): Promise { - const cid = chapterUrl.searchParams.get('cid'); - const sharingKey = _tt(cid); - const uri = getSanitizedURL(baseURL, apiEndpoint);//new URL(apiEndpoint, baseURL + '/'); - uri.searchParams.set('cid', cid); - uri.searchParams.set('dmytime', String(Date.now())); - uri.searchParams.set('k', sharingKey); - - const request = new FetchRequest(uri.href); - //await FetchWindowCSS(request, 'body');//dummy request set cookies for mangaplanet - - //const response = await Fetch(new FetchRequest(uri.href)); - //const data: JSONPageData_v016452 = await response.json(); - const data = await FetchWindowScript(request, JsonScript.replace('{URI}', uri.href), 2000); - - return await getPageLinks_v016130(scraper, data.items[0], sharingKey, baseURL, chapter); -} -async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey, baseURL: string, chapter: Chapter): Promise{ +async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey, chapter: Chapter): Promise { const cid = configuration.ContentID; - /* - *let stbl = this._pt( cid, sharingKey, configuration.stbl ); - *let ttbl = this._pt( cid, sharingKey, configuration.ttbl ); - */ configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); try { @@ -320,71 +254,48 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config // } - if (configuration.ServerType === 0) { //Booklive - return await getPageLinksSBC_v016130(scraper, configuration, baseURL, chapter); - } - if (configuration.ServerType === 1) {//Futabanet, Getsuaku - return await getPageLinksContentJS_v016130(scraper, configuration, chapter); - } - if (configuration.ServerType === 2) {//MangaPlanet - return await getPageLinksContent_v016130(scraper, configuration, chapter); + switch (configuration.ServerType as number) { + case 0: { //Booklive + const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); + uri.searchParams.set('cid', configuration.ContentID); + uri.searchParams.set('dmytime', configuration.ContentDate); + uri.searchParams.set('p', configuration.p); + uri.searchParams.set('vm', String(configuration.ViewMode)); + return await fetchSBC(scraper, uri, configuration, chapter); + } + case 1: {//Futabanet, Getsuaku + //return await getPageLinksContentJS_v016130(scraper, configuration, chapter); + const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); + if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); + const response = await Fetch(new FetchRequest(uri.href)); + const data = await response.text(); + const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); + const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + let src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + if (!src.startsWith('/')) src = '/' + src; + return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); + }); + return pageLinks; + } + case 2: {//MangaPlanet + //return await getPageLinksContent_v016130(scraper, configuration, chapter); + const uri = getSanitizedURL(configuration.ContentsServer, 'content'); + uri.searchParams.set('dmytime', configuration.ContentDate); + const data = await FetchJSON(new FetchRequest(uri.href, { headers: { Referer: scraper.URI.href } })); + const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + const src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + }); + return pageLinks; + } } return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinksSBC_v016130(scraper: MangaScraper, configuration: Configuration_v016452, baseURL: string, chapter: Chapter) { - //const uri = new URL(configuration.ContentsServer + '/sbcGetCntnt.php', baseURL + '/'); - const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); - - uri.searchParams.set('cid', configuration.ContentID); - uri.searchParams.set('dmytime', configuration.ContentDate); - uri.searchParams.set('p', configuration.p); - uri.searchParams.set('vm', String(configuration.ViewMode)); - return await fetchSBC(scraper, uri, configuration, chapter); -} - -async function getPageLinksContent_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter : Chapter) { - //const uri = new URL(configuration.ContentsServer); - //uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; - //uri.pathname += 'content'; - const uri = getSanitizedURL(configuration.ContentsServer, 'content'); - - uri.searchParams.set('dmytime', configuration.ContentDate); - const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href, { headers: { Referer: scraper.URI.href } })); - - const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); - return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); - }); - return pageLinks; -} - -async function getPageLinksContentJS_v016130(scraper: MangaScraper, configuration: Configuration_v016452, chapter: Chapter) { - //const uri = new URL(configuration.ContentsServer); - //uri.pathname += uri.pathname.endsWith('/') ? '' : '/'; - //uri.pathname += 'content.js'; - const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); - - if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - const response = await Fetch(new FetchRequest(uri.href)); - const data = await response.text(); - const jsonObj = JSON.parse(data.slice(16, -1)); - const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - let src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); - if (!src.startsWith('/')) src = '/' + src; - return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); - }); - return pageLinks; -} - -//**************** -// COMMON -//**************** - async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configuration_v016452, chapter: Chapter) { const data = await FetchJSON(new FetchRequest(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); @@ -410,28 +321,16 @@ async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configur * @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 { - let promise; switch (true) { case page.Link.href.endsWith('ptimg.json'): - promise = await descramble_v016061(this, page, priority, signal, detectMimeType); - break; + return await descramble_v016061(this, page, priority, signal, detectMimeType); case page.Link.href.includes('sbcGetImg'): - promise = await descramble_v016130(this, page, priority, signal, detectMimeType); - break; case page.Link.href.includes('M_L.jpg'): - promise = await descramble_v016130(this, page, priority, signal, detectMimeType); - break; case page.Link.href.includes('M_H.jpg'): - promise = await descramble_v016130(this, page, priority, signal, detectMimeType); - break; case page.Link.href.includes('/img/'): - promise = await descramble_v016130(this, page, priority, signal, detectMimeType); - break; - default: - promise = Promise.reject('Unsupported version of SpeedBinb reader!'); - break; + return await descramble_v016130(this, page, priority, signal, detectMimeType); } - return promise; + throw new Error('Unsupported version of SpeedBinb reader!'); } async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { @@ -489,7 +388,7 @@ export function ImageAjax(detectMimeType = false) { }; } -function _tt(t) : string { +function _tt(t): string { const n = Date.now().toString(16).padStart(16, 'x'); // w.getRandomString(16) const i = Array(Math.ceil(16 / t.length) + 1).join(t); const r = i.substring(0, 16); @@ -790,7 +689,7 @@ const _speedbinb_a = function () { const c = f + (r - 1); const l = c + 1; - for (let s, u, h, o, d = 0;d < n * r;d++) + for (let s, u, h, o, d = 0; d < n * r; d++) s = this.Ot(e.charAt(2 * d)), u = this.Ot(e.charAt(2 * d + 1)), d <= a ? o = h = 2 : d <= f ? (h = 2, o = 1) : d <= c ? (h = 1, o = 2) : d <= l && (o = h = 1), From 050bd9da11a8b4588795f1d1dd8e80f467634278 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 15 Jan 2024 17:29:35 +0100 Subject: [PATCH 38/88] Speedbind: minor modifications * adjust initial request for S-Manga, use viewerurl * use this.URI when using JSonFetchScript --- web/src/engine/websites/decorators/SpeedBinb.ts | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index f3268e4443..5708a41a72 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -146,22 +146,24 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const cid = viewerUrl.searchParams.get('cid'); const sharingKey = _tt(cid); - const uri = getSanitizedURL(websiteUrl, el.dataset.ptbinb); + const uri = getSanitizedURL(viewerUrl.href, el.dataset.ptbinb); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', String(Date.now())); uri.searchParams.set('k', sharingKey); switch (SBVersion) { case SpeedBinbVersion.v016113: //Futabanet, Getsuaku (v016700), Ohtabooks - case SpeedBinbVersion.v016130: { //Booklive, MangaPlanet, Yanmaga - const data = await FetchWindowScript(new FetchRequest(uri.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + case SpeedBinbVersion.v016130: { //Booklive, MangaPlanet, S-Manga, Yanmaga + //Doing it like that because of cookies needed for Mangaplanet + const data = await FetchWindowScript(new FetchRequest(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); } //YoungJump case SpeedBinbVersion.v016201: { const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); - const data = await FetchWindowScript(new FetchRequest(uri.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + //Doing it like that because of cookies needed + const data = await FetchWindowScript(new FetchRequest(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } //Cmoa From e233864fcafdd4f9ecf539c2881d242268c16966 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 15 Jan 2024 19:20:09 +0100 Subject: [PATCH 39/88] Add Smanga https://github.com/manga-download/hakuneko/issues/1537 --- web/src/engine/websites/SManga.ts | 53 ++++++++++++++++++++++++++ web/src/engine/websites/SManga.webp | Bin 0 -> 1166 bytes web/src/engine/websites/SManga_e2e.ts | 26 +++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 80 insertions(+) create mode 100644 web/src/engine/websites/SManga.ts create mode 100644 web/src/engine/websites/SManga.webp create mode 100644 web/src/engine/websites/SManga_e2e.ts diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts new file mode 100644 index 0000000000..70cb193105 --- /dev/null +++ b/web/src/engine/websites/SManga.ts @@ -0,0 +1,53 @@ +import { Tags } from '../Tags'; +import icon from './SManga.webp'; +import { Chapter, DecoratableMangaScraper, type MangaPlugin, Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchRequest, FetchWindowScript } from '../FetchProvider'; + +type SSD = { + datas?: [{ + series_data: { + series_name: string, + series_id: number + } + }], + data?: { + item_datas?: [{ + ssid: number, + isbn: string, + item_name: string + }] + } +} + +@Common.MangasNotSupported() +@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + public constructor() { + super('smanga', `S-Manga`, 'https://www.s-manga.net', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + public override ValidateMangaURL(url: string): boolean { + return /https:\/\/www\.s-manga\.net\/items\/contents.html\?isbn=/.test(url); + } + + public override async FetchManga(provider: MangaPlugin, url: string): Promise { + const { datas } = await FetchWindowScript(new FetchRequest(url), 'window.ssd', 2000); + return new Manga(this, provider, datas[0].series_data.series_id.toString(), datas[0].series_data.series_name.trim()); + } + + public override async FetchChapters(manga: Manga): Promise { + const url = new URL(`/search/search.html?seriesid=${manga.Identifier}&order=1`, this.URI); + const { data } = await FetchWindowScript(new FetchRequest(url.href), 'window.ssd', 2000); + return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.isbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); + } + + isbnToCid(ISBN: string): string { + return ISBN.replaceAll('-', ''); + } +} \ No newline at end of file diff --git a/web/src/engine/websites/SManga.webp b/web/src/engine/websites/SManga.webp new file mode 100644 index 0000000000000000000000000000000000000000..dcb9bfff416fb79fcb760fe2e28cc90e6e24f41c GIT binary patch literal 1166 zcmV;91abRPNk&G71ONb6MM6+kP&il$0000G0000#002J#06|PpNZkSe00E$cZL?`R z`m1WkPDV-Fw#|`k+vdn|GHTnlZQHhO_g%H>Z=AEvIjc2|hzY>|Sh1#`nOW1%RO-`4 zQEsL+Nh5%cTYZo5r=NTFxyK)|)xtvnsMR7Su%*U7^aF$K-@R(*8345^Ofh`Vr=4VY zUrH(Ur5p@?ckyz7O3%bFc)#};kvv$M-AUfI1k`$@hE<_BJbnQsk)6kJdrgG)nO z37Th_t8*TJrj=sGUl`RTo(^lb9D~(6?}4;3Y|30;=4%FN(O_?SeZfx#6zuyS&#*aj zeVK1H1uHS?bKZ}(idlYRRF`-*td(HEOU!?R!_c&X;WB!4!R28EJJ%QdU?ilCV$Saw zl{wFcp}pb;dS#jG6&W^St}FAEfsg`0|L2&iavlOhX@l`hHD$gt8d4${^EPu$iMyde zsbLbG6+7=SNQq+3?->;Ze^?NTvJ2>}*ts(drG_;a{A)xNeVhhEvEY6>$($l`?;`OW zQ7JNP&&+TqzyF-xtDJa_sGw9Z;ti%0!S|=mJ=0@MxhEbR4;2&}j^uCTZ?|ne6oSF0 zF+6w8onLJV6BH}v_=#b!UhmS$MZ~|4-iwdRlyA7-zP~=$^V*CkWBY&J^-rdTm{+)O4Wd28=d<$i+_Cd zm_-0Fbk!6cs{t6i$adq;yXlr&ZoTHjBi5Qx0ciyFiWxeTMp3(H)0l{eHjSy^e=7i1 zP&goh0RR9{2>_h|DnI~006v96p-`nHBO<69`%s_|fB;Wa*8<;9JC8~4_A{opokOF$ z;Gh64_L;jW5hC>J8EQ~AaDNfU+|6So**7&+40};pmCb!^&;S7b`OsQERA@aqYnojw zxu}q7+J)hJ=#dk~umKn2;mmoUb70zSvSI90t_SSi|EB97ni#tOjK#?D!lF|)2UQ2(Fjsw;9!g@8ceoe++^%HLqdmArl6uymu=&DRs?O9q{aF!@Qn69k%71-kDeDws|-fq^bSQ&Rn g!T*UcvKI3g=d|Aa7n@VFN{m2@K=IrpWD@`Y04qW)3IG5A literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/SManga_e2e.ts b/web/src/engine/websites/SManga_e2e.ts new file mode 100644 index 0000000000..6eca2d50d3 --- /dev/null +++ b/web/src/engine/websites/SManga_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'smanga', + title: 'S-Manga' + }, + container: { + url: 'https://www.s-manga.net/items/contents.html?isbn=978-4-08-883785-7', + id: '35169', + title: 'ONE PIECE', + timeout: 15000 + }, + child: { + id: '/reader/main.php?cid=9784088837857', + title: '107' + }, + entry: { + index: 0, + size: 2_610_174, + 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/_index.ts b/web/src/engine/websites/_index.ts index db6d2ecdcc..40cffc93a0 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -528,6 +528,7 @@ export { default as SinensisScan } from './SinensisScan'; export { default as SirenKomik } from './SirenKomik'; export { default as Siyahmelek } from './Siyahmelek'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoulScans } from './SoulScans'; export { default as StickHorse } from './StickHorse'; From 81e5dbe0f2d5244f1dfa3c05b280c615a1b67fec Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 16 Jan 2024 16:15:58 +0100 Subject: [PATCH 40/88] improve platform abstraction and enforcing more types --- web/src/engine/websites/Cmoa.ts | 6 +- web/src/engine/websites/ComicBrise.ts | 4 +- web/src/engine/websites/ComicMeteor.ts | 4 +- web/src/engine/websites/ComicPolaris.ts | 4 +- web/src/engine/websites/ComicValkyrie.ts | 4 +- web/src/engine/websites/Futabanet.ts | 4 +- web/src/engine/websites/Getsuaku.ts | 7 +- web/src/engine/websites/MangaPlanet.ts | 6 +- web/src/engine/websites/Ohtabooks.ts | 6 +- web/src/engine/websites/OneTwoThreeHon.ts | 4 +- web/src/engine/websites/SManga.ts | 6 +- web/src/engine/websites/YoungJump.ts | 6 +- .../engine/websites/decorators/SpeedBinb.ts | 126 +++++++++--------- 13 files changed, 93 insertions(+), 94 deletions(-) diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 9ef7ad5c6f..e45c65c49a 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -3,7 +3,7 @@ import icon from './Cmoa.webp'; import { Chapter, DecoratableMangaScraper, type MangaPlugin, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; @Common.MangasNotSupported() @SpeedBinb.PagesSinglePageAjax() @@ -26,14 +26,14 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const request = new Request(new URL(manga.Identifier, this.URI).href); const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li:nth-last-child(2) a'); const chapters = []; const totalPage = pages.length == 0 ? 1 : parseInt(new URL(pages[0].href).searchParams.get('page')); for (let i = 0; i < totalPage; i++) { const uri = new URL(manga.Identifier, this.URI); uri.searchParams.set('page', String(i + 1)); - const pageRequest = new FetchRequest(uri.href); + const pageRequest = new Request(uri.href); const data = await FetchCSS(pageRequest, '.title_vol_vox_vols .title_vol_vox_vols_i'); for (const element of data) { const chapterLink = element.querySelector('a[href^="/reader/"]'); diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index 1e1a23f580..e1931a4724 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -3,7 +3,7 @@ import icon from './ComicBrise.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') @@ -20,7 +20,7 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const uri = new URL(manga.Identifier, this.URI); - const request = new FetchRequest(uri.href); + const request = new Request(uri.href); const data = await FetchCSS(request, '.modal.modal-chapter .modal-body'); return data.reverse() //.filter(e => e.querySelector(".banner-trial img").getAttribute("alt") == "FREE") //dont filter for free chapter diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index d6050ce105..40149e6217 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -3,7 +3,7 @@ import icon from './ComicMeteor.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const request = new Request(new URL(manga.Identifier, this.URI).href); const contents = await FetchCSS(request, 'div#contents'); const data = contents[0]; let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn.work_episode_link_orange a')] diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 5f5dbfd966..a9769e987c 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -3,7 +3,7 @@ import icon from './ComicPolaris.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; @@ -24,7 +24,7 @@ export default class extends DecoratableMangaScraper { return icon; } public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const request = new Request(new URL(manga.Identifier, this.URI).href); const data = (await FetchCSS(request, 'div#contents'))[0]; let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a')] .map(element => { diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 4457659633..170dca903c 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -3,7 +3,7 @@ import icon from './ComicValkyrie.webp'; import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(element: HTMLElement) { const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'); @@ -34,7 +34,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const data = await FetchCSS(new FetchRequest(url), 'meta[property = "og:title"]'); + const data = await FetchCSS(new Request(url), 'meta[property = "og:title"]'); const id = new URL(url).pathname.replace('/new.html', '/'); const title = data[0].content.replace(/\s*THE COMIC\s*/i, '').trim(); return new Manga(this, provider, id, title); diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 69d6300520..151c35702c 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -3,7 +3,7 @@ import icon from './Futabanet.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') @@ -19,7 +19,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(`${this.URI.origin}${manga.Identifier}/episodes`); + const request = new Request(`${this.URI.origin}${manga.Identifier}/episodes`); const data = await FetchCSS(request, 'div.episode__grid a'); return data.map(chapter => { const epnum = chapter.querySelector('.episode__num').textContent.trim(); diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index 7b5ff37edf..eee8eba1f2 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -3,7 +3,7 @@ import icon from './Getsuaku.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchJSON, FetchRequest, FetchWindowScript } from '../FetchProvider'; +import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; type APIChapters = { objects: { @@ -36,10 +36,9 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const bookid = await FetchWindowScript(new FetchRequest(new URL(manga.Identifier, this.URI).href), 'book_id', 1500); + const bookid = await FetchWindowScript(new Request(new URL(manga.Identifier, this.URI).href), 'book_id', 1500); const url = new URL(`/api/sort_episodes?book_id=${bookid}&order=asc&mode=all`, this.URI); - const chapters = await FetchJSON(new FetchRequest(url.href)); + const chapters = await FetchJSON(new Request(url.href)); return chapters.objects.map(chapter => new Chapter(this, manga, `/episode/${chapter.cid}`, chapter.episode_number.trim())); } - } \ No newline at end of file diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index fa3d048a2d..484b0bcfec 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -3,7 +3,7 @@ import icon from './MangaPlanet.webp'; import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest, FetchWindowScript } from '../FetchProvider'; +import { FetchCSS, FetchWindowScript } from '../platform/FetchProvider'; function MangaExtractor(element: HTMLElement) { const id = element.querySelector('a').pathname; @@ -25,13 +25,13 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - const request = new FetchRequest(this.URI.href); + const request = new Request(this.URI.href); return FetchWindowScript(request, `window.cookieStore.set('mpaconf', '18')`); } public override async FetchChapters(manga: Manga): Promise { const uri = new URL(manga.Identifier, this.URI); - const request = new FetchRequest(uri.href); + const request = new Request(uri.href); const data = await FetchCSS(request, '#accordion div[id*="vol_"]'); const chapters : Chapter[] = []; for (const volume of data) { diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 68d993d998..08713216dd 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -3,7 +3,7 @@ import icon from './Ohtabooks.webp'; import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; @@ -26,14 +26,14 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { //find real reader url to send to SpeedBinb, since redirection is done by Javascript - const data = await FetchCSS(new FetchRequest(chapter.Identifier), 'body'); + const data = await FetchCSS(new Request(chapter.Identifier), 'body'); const reallink = data[0].innerHTML.match(/location.href='(.*)'/)[1]; return await SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } public override async FetchChapters(manga: Manga): Promise { const uri = new URL(manga.Identifier, this.URI); - const data = await FetchCSS(new FetchRequest(uri.href), 'a[onClick^="return !openBook("]'); + const data = await FetchCSS(new Request(uri.href), 'a[onClick^="return !openBook("]'); let chapterList = data.map(element => { let partId = element.getAttribute('onclick'); partId = partId.match(/\d+/)[0]; diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index 6a3c3ef36c..9dc1a515fc 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -3,7 +3,7 @@ import icon from './OneTwoThreeHon.webp'; import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS, FetchRequest } from '../FetchProvider'; +import { FetchCSS } from '../platform/FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { const id = anchor.pathname; @@ -35,7 +35,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new FetchRequest(new URL(manga.Identifier, this.URI).href); + const request = new Request(new URL(manga.Identifier, this.URI).href); const data = await FetchCSS(request, 'div.read-episode li'); return data.map(element => { if (element.querySelector('a')) { // otherwise chapter not available diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index 70cb193105..1affd7fa1e 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -3,7 +3,7 @@ import icon from './SManga.webp'; import { Chapter, DecoratableMangaScraper, type MangaPlugin, Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchRequest, FetchWindowScript } from '../FetchProvider'; +import { FetchWindowScript } from '../platform/FetchProvider'; type SSD = { datas?: [{ @@ -37,13 +37,13 @@ export default class extends DecoratableMangaScraper { } public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const { datas } = await FetchWindowScript(new FetchRequest(url), 'window.ssd', 2000); + const { datas } = await FetchWindowScript(new Request(url), 'window.ssd', 2000); return new Manga(this, provider, datas[0].series_data.series_id.toString(), datas[0].series_data.series_name.trim()); } public override async FetchChapters(manga: Manga): Promise { const url = new URL(`/search/search.html?seriesid=${manga.Identifier}&order=1`, this.URI); - const { data } = await FetchWindowScript(new FetchRequest(url.href), 'window.ssd', 2000); + const { data } = await FetchWindowScript(new Request(url.href), 'window.ssd', 2000); return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.isbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); } diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index 1993ad6e85..845ad556cf 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -3,7 +3,7 @@ import icon from './YoungJump.webp'; import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchJSON, FetchRequest, FetchWindowScript } from '../FetchProvider'; +import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; type APIMagazine = { url: string, @@ -29,14 +29,14 @@ export default class extends DecoratableMangaScraper { } public override async FetchManga(provider: MangaPlugin, url: string): Promise { - const mangatitle = await FetchWindowScript(new FetchRequest(url), 'document.title', 3000); + const mangatitle = await FetchWindowScript(new Request(url), 'document.title', 3000); const uri = new URL(url); return new Manga(this, provider, uri.pathname + uri.search, mangatitle.trim()); } public override async FetchMangas(provider: MangaPlugin): Promise { - const request = new FetchRequest(new URL('/yj-rest-apis/getBookInfo.php', this.URI).href); + const request = new Request(new URL('/yj-rest-apis/getBookInfo.php', this.URI).href); const data = await FetchJSON(request); return data.map(magazine => new Manga(this, provider, magazine.url, `${magazine.issue} - ${magazine.number}`.trim())); diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 5708a41a72..a86c6c7fd8 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -1,4 +1,4 @@ -import { Fetch, FetchJSON, FetchRequest, FetchWindowScript } from '../../FetchProvider'; +import { Fetch, FetchJSON, FetchWindowScript } from '../../platform/FetchProvider'; import { type MangaScraper, type Chapter, Page } from '../../providers/MangaPlugin'; import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; @@ -10,8 +10,8 @@ type JSONPageData_v016452 = { type Configuration_v016452 = { ContentID: string, - ctbl: string[], - ptbl: string[], + ctbl: string | string[], + ptbl: string | string[], ServerType: number | string ContentsServer: string, p: string, @@ -42,19 +42,22 @@ type PageView_v016061 = { type PageView_v016130 = { transfers: { - coords: { - height: number, - width: number, - xdest: number, - xsrc: number, - ydest: number, - ysrc: number - }[] + index: number, + coords: DrawImageCoords[] }[], width: number, height: number } +type DrawImageCoords = { + height: number, + width: number, + xdest: number, + xsrc: number, + ydest: number, + ysrc: number +} + type SBCDATA = { ttx: string; } @@ -64,6 +67,11 @@ type DescrambleKP = { u: string } +type Dimensions = { + width: number, + height: number +} + const JsonFetchScript = ` new Promise(resolve => { fetch('{URI}') @@ -112,7 +120,7 @@ function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { const websiteUrl = baseUrl ? new URL(baseUrl).href : new URL(this.URI).href; let viewerUrl = new URL(chapter.Identifier, websiteUrl); - const request = new FetchRequest(viewerUrl.href, { + const request = new Request(viewerUrl.href, { headers: { Referer: this.URI.href } @@ -155,7 +163,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap case SpeedBinbVersion.v016113: //Futabanet, Getsuaku (v016700), Ohtabooks case SpeedBinbVersion.v016130: { //Booklive, MangaPlanet, S-Manga, Yanmaga //Doing it like that because of cookies needed for Mangaplanet - const data = await FetchWindowScript(new FetchRequest(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); } //YoungJump @@ -163,7 +171,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); //Doing it like that because of cookies needed - const data = await FetchWindowScript(new FetchRequest(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } //Cmoa @@ -172,7 +180,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u1 = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u0', u0); uri.searchParams.set('u1', u1); - const data = await FetchJSON(new FetchRequest(uri.href)); + const data = await FetchJSON(new Request(uri.href)); const params: Params_v016452 = { cid, sharingKey, u0, u1 }; return await getPageLinks_v016452(this, data.items[0], params, chapter); } @@ -199,8 +207,8 @@ export function PagesSinglePageAjax(baseUrl = '') { } async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, chapter: Chapter): Promise { - configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl); - configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl); + configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl as string); + configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); } catch (error) { @@ -222,8 +230,8 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config async function getPageLinks_v016201(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { const cid = configuration.ContentID; - configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); - configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); + configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); + configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); } catch (error) { @@ -234,11 +242,11 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config const uri = getSanitizedURL(configuration.ContentsServer, 'content'); uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('u1', u); - const data: SBCDATA = await FetchJSON(new FetchRequest(uri.href)); + const data: SBCDATA = await FetchJSON(new Request(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); }); return pageLinks; @@ -248,8 +256,8 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey, chapter: Chapter): Promise { const cid = configuration.ContentID; - configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl); - configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl); + configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); + configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); } catch (error) { @@ -266,30 +274,28 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config return await fetchSBC(scraper, uri, configuration, chapter); } case 1: {//Futabanet, Getsuaku - //return await getPageLinksContentJS_v016130(scraper, configuration, chapter); const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - const response = await Fetch(new FetchRequest(uri.href)); + const response = await Fetch(new Request(uri.href)); const data = await response.text(); const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { let src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); if (!src.startsWith('/')) src = '/' + src; return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); }); return pageLinks; } case 2: {//MangaPlanet - //return await getPageLinksContent_v016130(scraper, configuration, chapter); const uri = getSanitizedURL(configuration.ContentsServer, 'content'); uri.searchParams.set('dmytime', configuration.ContentDate); - const data = await FetchJSON(new FetchRequest(uri.href, { headers: { Referer: scraper.URI.href } })); + const data = await FetchJSON(new Request(uri.href, { headers: { Referer: scraper.URI.href } })); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); }); return pageLinks; @@ -299,12 +305,12 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config } async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configuration_v016452, chapter: Chapter) { - const data = await FetchJSON(new FetchRequest(uri.href)); + const data = await FetchJSON(new Request(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); uri.searchParams.set('src', src); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl, configuration.ptbl))); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); return new Page(scraper, chapter, new URL(uri.href.replace('/sbcGetCntnt.php', '/sbcGetImg.php'))); }); return pageLinks; @@ -336,7 +342,7 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si } async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { - const data = await FetchJSON(new FetchRequest(page.Link.href)); + const data = await FetchJSON(new Request(page.Link.href)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); @@ -361,15 +367,9 @@ async function descramble_v016130(scraper: MangaScraper, page: Page, priority: P const descrambleKeyPair: DescrambleKP = JSON.parse(window.atob(page.Link.hash.slice(1))); return DeScramble(imagedata, async (image, ctx) => { - const view: PageView_v016130 = _getImageDescrambleCoords(descrambleKeyPair.s, descrambleKeyPair.u, image.width, image.height); + const view = getImageDescrambleCoords(descrambleKeyPair.s, descrambleKeyPair.u, image.width, image.height); for (const part of view.transfers[0].coords) { - const sourceX = part.xsrc; - const sourceY = part.ysrc; - const targetX = part.xdest; - const targetY = part.ydest; - const partWidth = part.width; - const partHeight = part.height; - ctx.drawImage(image, sourceX, sourceY, partWidth, partHeight, targetX, targetY, partWidth, partHeight); + ctx.drawImage(image, part.xsrc, part.ysrc, part.width, part.height, part.xdest, part.ydest, part.width, part.height); } }); } @@ -390,7 +390,7 @@ export function ImageAjax(detectMimeType = false) { }; } -function _tt(t): string { +function _tt(t: string): string { const n = Date.now().toString(16).padStart(16, 'x'); // w.getRandomString(16) const i = Array(Math.ceil(16 / t.length) + 1).join(t); const r = i.substring(0, 16); @@ -410,7 +410,7 @@ function _tt(t): string { }).join(""); } -function _pt(t, i, n) { +function _pt(t: string, i: string, n: string): string[] { const r = t + ':' + i; let e = 0; @@ -439,7 +439,7 @@ function _pt(t, i, n) { * Determine which descramble key pair from ctbl / ptbl shall be used * depending on the given image name 'pages/cu77gvXE.jpg' */ -function lt_001(t, ctbl, ptbl) { +function lt_001(t: string, ctbl: string[], ptbl: string[]): DescrambleKP { const i = [0, 0]; const n = t.lastIndexOf("/") + 1; const r = t.length - n; @@ -459,7 +459,7 @@ function lt_001(t, ctbl, ptbl) { * i width of descrambled image * n height of descrambled image */ -function _getImageDescrambleCoords(/*t*/s, u, i, n) { +function getImageDescrambleCoords(/*t*/s: string, u: string, i: number, n: number): PageView_v016130 { const r = _lt_002(s, u); // var r = this.lt(t.src); if (!r || !r.vt()) return null; @@ -483,7 +483,7 @@ function _getImageDescrambleCoords(/*t*/s, u, i, n) { /** * Get a descrambler based on the descramble key pair from ctbl / ptbl */ -function _lt_002(s, u) { +function _lt_002(s: string, u: string) { return "=" === u.charAt(0) && "=" === s.charAt(0) ? new _speedbinb_f(u, s) : u.match(/^[0-9]/) && s.match(/^[0-9]/) ? new _speedbinb_a(u, s) : "" === u && "" === s ? new _speedbinb_h : null; } @@ -492,7 +492,7 @@ function _lt_002(s, u) { * define prototype for f */ const _speedbinb_f = function () { - function s(t, i) { + function s(t: string, i: string) { this.Mt = null; const n = t.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/), r = i.match(/^=([0-9]+)-([0-9]+)([-+])([0-9]+)-([-_0-9A-Za-z]+)$/); @@ -515,24 +515,24 @@ const _speedbinb_f = function () { } } } - return s.prototype.vt = function () { + return s.prototype.vt = function (): boolean { return null !== this.Mt; } , - s.prototype.bt = function (t) { + s.prototype.bt = function (t: Dimensions): boolean { const i = 2 * this.C * this.jt, n = 2 * this.I * this.jt; return t.width >= 64 + i && t.height >= 64 + n && t.width * t.height >= (320 + i) * (320 + n); } , - s.prototype.dt = function (t) { + s.prototype.dt = function (t: Dimensions): Dimensions { return this.bt(t) ? { width: t.width - 2 * this.C * this.jt, height: t.height - 2 * this.I * this.jt } : t; } , - s.prototype.gt = function (t) { + s.prototype.gt = function (t: Dimensions): DrawImageCoords[] { if (!this.vt()) return null; if (!this.bt(t)) @@ -545,7 +545,7 @@ const _speedbinb_f = function () { ydest: 0 }]; - const h = []; + const h: DrawImageCoords[] = []; const i = t.width - 2 * this.C * this.jt, n = t.height - 2 * this.I * this.jt, r = Math.floor((i + this.C - 1) / this.C), @@ -576,7 +576,7 @@ const _speedbinb_f = function () { return h; } , - s.prototype.yt = function (t) { + s.prototype.yt = function (t: string) { let i; const n = [], r = [], e = []; for (i = 0; i < this.C; i++) @@ -601,7 +601,7 @@ const _speedbinb_f = function () { * define prototype for a */ const _speedbinb_a = function () { - function t(t, i) { + function t(t: string, i: string) { this.mt = null, this.wt = null; const n = this.yt(t); @@ -609,19 +609,19 @@ const _speedbinb_a = function () { n && r && n.ndx === r.ndx && n.ndy === r.ndy && (this.mt = n, this.wt = r); } - return t.prototype.vt = function () { + return t.prototype.vt = function (): boolean { return null !== this.mt && null !== this.wt; } , - t.prototype.bt = function (t) { + t.prototype.bt = function (t: Dimensions): boolean { return 64 <= t.width && 64 <= t.height && 102400 <= t.width * t.height; } , - t.prototype.dt = function (t) { + t.prototype.dt = function (t: Dimensions): Dimensions { return t; } , - t.prototype.gt = function (t) { + t.prototype.gt = function (t: Dimensions): DrawImageCoords[] { if (!this.vt()) return null; const i = []; @@ -674,7 +674,7 @@ const _speedbinb_a = function () { i; } , - t.prototype.yt = function (t) { + t.prototype.yt = function (t: string) { if (!t) return null; const i = t.split("-"); @@ -708,7 +708,7 @@ const _speedbinb_a = function () { }; } , - t.prototype.Ot = function (t) { + t.prototype.Ot = function (t: string) { let i = 0; let n = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".indexOf(t); return n < 0 ? n = "abcdefghijklmnopqrstuvwxyz".indexOf(t) : i = 1, @@ -725,19 +725,19 @@ const _speedbinb_a = function () { const _speedbinb_h = function () { // eslint-disable-next-line @typescript-eslint/no-empty-function function t() { } - return t.prototype.vt = function () { + return t.prototype.vt = function (): boolean { return !0; } , - t.prototype.bt = function () { + t.prototype.bt = function (): boolean { return !1; } , - t.prototype.dt = function (t) { + t.prototype.dt = function (t: Dimensions): Dimensions { return t; } , - t.prototype.gt = function (t) { + t.prototype.gt = function (t: Dimensions): DrawImageCoords[] { return [{ xsrc: 0, ysrc: 0, From 5bf5eedd4edd7b2aad91be4193653a52ae8524db Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 24 Jan 2024 15:24:56 +0100 Subject: [PATCH 41/88] Add BookHodai + handle ServerType 1 for BookHodai Speedbinb version --- web/src/engine/websites/BookHodai.ts | 55 ++++++++++++++++++ web/src/engine/websites/BookHodai.webp | Bin 0 -> 1394 bytes web/src/engine/websites/BookHodai_e2e.ts | 25 ++++++++ web/src/engine/websites/_index.ts | 1 + .../engine/websites/decorators/SpeedBinb.ts | 25 ++++++-- 5 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 web/src/engine/websites/BookHodai.ts create mode 100644 web/src/engine/websites/BookHodai.webp create mode 100644 web/src/engine/websites/BookHodai_e2e.ts diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts new file mode 100644 index 0000000000..862e9e61ee --- /dev/null +++ b/web/src/engine/websites/BookHodai.ts @@ -0,0 +1,55 @@ +import { Tags } from '../Tags'; +import icon from './BookHodai.webp'; +import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS } from '../platform/FetchProvider'; +function MangaLabelExtractor(element: HTMLElement): string { + return element.textContent.split('>').pop().trim() || element.textContent.trim(); +} + +@Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'section.breadcrumb div.bread-text', MangaLabelExtractor) +@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('bookhodai', `BookHodai`, 'https://bookhodai.jp', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override async FetchMangas(provider: MangaPlugin): Promise { + const paths = ['magazine', 'magazine_pop', 'manga', 'manga_pop']; + const mangaList: Manga[] = []; + for (const path of paths) { + const mangas = await Common.FetchMangasMultiPageCSS.call(this, provider, `/search/${path}?page={page}`, 'p.book-detail-pc__title a'); + mangaList.push(...mangas); + } + return mangaList.distinct(); + } + + public override async FetchChapters(manga: Manga): Promise { + const chapters: Chapter[] = []; + const [data] = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div.content'); + + //get current "chapter" (book) title + let title = data.querySelector('h2').textContent.trim(); + title = title.replace(manga.Title, '').trim() != '' ? title.replace(manga.Title, '').trim() : title; + + const chaptersNodes = [...data.querySelectorAll('.bookdetail_box div.pc a[href*="viewer"], div.matome-text-box')]; + const firstChapter = chaptersNodes.shift() as HTMLAnchorElement; + chapters.push(new Chapter(this, manga, firstChapter.pathname + firstChapter.search, title)); + + for (const chapter of chaptersNodes) { + const title = chapter.querySelector('.matome_book_nm').textContent.trim(); + const link = chapter.querySelector('a[href*="viewer"]'); + chapters.push(new Chapter(this, manga, link.pathname + link.search, title.replace(manga.Title, ''))); + } + return chapters.distinct(); + } +} + + diff --git a/web/src/engine/websites/BookHodai.webp b/web/src/engine/websites/BookHodai.webp new file mode 100644 index 0000000000000000000000000000000000000000..8ee8ef8694f8e5d0fca50158f7349ed2e76944d1 GIT binary patch literal 1394 zcmV-&1&#VrNk&F$1pok7MM6+kP&go71pokW7XY0BDnI~006v96p-`nGqav;r*~p*} zfC9Ny1xt7(_|G&7uUP1=cCn8?P#>AMg!zE}CH|xJyWKPV->Tp5o^9P^|J40JJhXk0 z|9AZ|ZsmUg(e4p*jz!NT2TZ1ae2$<>zD94MZhRFC=^(U_V(rV^Wl-8I`qr<^b!g4_ z>4=7@z5_ad|9c`!so8o8MYurh^w~i8O(4Edp6NuIcZ}ulJm7SCNSHK|z~WG<)e6wi zmtgWLs2BJ;9wlnU#RvcZ{lGWr)78&so)D#t` z@5MkN7ZAbOq^TKs*?7X)F zCK$?%gY^;^Ez2W{c}sFHtQzl)G1%HFCQ`$(buJLs?qb>{R+-RUKE0njcMA+yaN84P zBhb3hv++Q!+%!!9lk&Ut$PL%$Qy=+FXT+kOrOh+0m%MD=q|4|n!-3Oh31Ur1tDgFG z&IMdd9EjH6<&xizzveXZ`eamrT8^~>M9S~Y7QyqZ^`e~mUnM&Di5bWDbjv(jFP$6$ zb8q?4dgU8+Peg&p?tPgDGK+H)V%D_zXfRaM0R1b8pCD}qE%3pb3Y?D zj8Oh#B<;uhvK5=sEWrt&?u%;;X(EX?i~*3sMTq(-3Xm{7q(gX(jt7(c1GYjT#?SVx zF475WYZG{#CRNI$v&2yfJ*wK&xM?c!iZ>pM$`H!`(Iw?LHXUZ&pwn@{z)TgsP$ z?faR+2E9dAN+HV!T=QRUWLzQKIV;t)5vk&WeDnBlu$sH1XwL;Yn4Ii+QeWBo@o9V* z=HJ@lD+ndN)6SRG$DPDV2lSBPVDtKQ7#Wj1xyU2RIo*5COm(tBCLlN zLnDVTeLAY}ysM9ZOOTyn1!-jGv~7$O?2Es+^*vl{a-l04g6m_oa42VyHWl8pT*o?* z%5uT%a7+h)(*?SuF`S3CFZ;M%fM42@4f4c0zn3AaVRNrq-DQP}dWWZKCXOX8^6k*> zjuIS^B!=^=Hj2&9=8ptR|5WGcfK>=DfBe(}u=oG!x8?i@%$P)iN(byOPH_P(+P^0H z;Sv61eG9Ac{ZW2%q(`E#?e|Of#&+ptJ5XrHj{`VDOWwX*WH5Se`vS;|^SU0d3EZwM z7JCSCvasOTdK9--hq&D(>-0bHLN#pTZ}lOP10FeD-fCG?iW(n z&9)&b-}Zq3$wRU5TFDn*Ul?C5(FQXAQS9I6pK0bT{=c&GCq3L8l640}fKYEQ%toKh z4eqHA`GyR|lTa|iO)Rox#pO2a;sb!fYQ_zt<4qnhCX;6tGrdNlcwg#DMxH$IdlEXyur^a{bEex8+%oY_>Tm=9C06R*; AqW}N^ literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts new file mode 100644 index 0000000000..84c69e19b0 --- /dev/null +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'bookhodai', + title: 'BookHodai' + }, + container: { + url: 'https://bookhodai.jp/manga/backnumber/49775', + id: '/manga/backnumber/49775', + title: '色欲の春~秘めた色香は筆先に宿る~' + }, + child: { + id: '/viewer?book_id=3000071024&branch_no=01&book_type=4', + title: '(1)' + }, + entry: { + index: 0, + size: 1_950_670, + 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/_index.ts b/web/src/engine/websites/_index.ts index c0c6a4296c..8c2b535173 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -39,6 +39,7 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookHodai } from './BookHodai'; export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index a86c6c7fd8..21af3d68dd 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -170,11 +170,11 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap case SpeedBinbVersion.v016201: { const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); - //Doing it like that because of cookies needed + //Doing it like that because of cookies needed for YoungJump const data = await FetchWindowScript(new Request(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } - //Cmoa + //Cmoa, BookHodai case SpeedBinbVersion.v016452: { const u0 = viewerUrl.searchParams.get('u0'); const u1 = viewerUrl.searchParams.get('u1'); @@ -214,7 +214,7 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config } catch (error) { // } - if (configuration.ServerType === 0) { + if (configuration.ServerType === 0) {//CMOA const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); uri.searchParams.set('cid', params.cid); uri.searchParams.set('p', configuration.p); @@ -224,6 +224,23 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config uri.searchParams.set('u0', params.u0); uri.searchParams.set('u1', params.u1); return await fetchSBC(scraper, uri, configuration, chapter); + + } else if (configuration.ServerType === 1) {//BookHodai + const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); + uri.searchParams.set('dmytime', String(Date.now())); + uri.searchParams.set('u0', params.u0); + uri.searchParams.set('u1', params.u1); + const response = await Fetch(new Request(uri.href)); + const data = await response.text(); + const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); + const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); + const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { + let src = img.getAttribute('src'); + uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); + if (!src.startsWith('/')) src = '/' + src; + return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); + }); + return pageLinks; } return Promise.reject(new Error('Content server type not supported!')); } @@ -254,7 +271,7 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey, chapter: Chapter): Promise { +async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); From 3e0523ff68ef15b8797c5b8c5d7c17815af26c6c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 24 Jan 2024 15:26:57 +0100 Subject: [PATCH 42/88] Update BookHodai.ts --- web/src/engine/websites/BookHodai.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index 862e9e61ee..a96346cac1 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -50,6 +50,4 @@ export default class extends DecoratableMangaScraper { } return chapters.distinct(); } -} - - +} \ No newline at end of file From 2272353d42b2bc46d714809755a89b068f3f5b14 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 25 Jan 2024 12:18:16 +0100 Subject: [PATCH 43/88] SpeedBinb : tweak decorator * Add the possibility to gather initial div#pages and location using a script. * Add the possibility to override the detected Speedbind version, just in case --- .../engine/websites/decorators/SpeedBinb.ts | 159 +++++++++++++----- 1 file changed, 114 insertions(+), 45 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 21af3d68dd..288a200fe0 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -79,7 +79,7 @@ const JsonFetchScript = ` .then(json => resolve(json)) }); `; -enum SpeedBinbVersion { v016113, v016201, v016452, v016130, _default_v016061, vUnknown } +export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); @@ -88,21 +88,84 @@ function getSanitizedURL(base: string, append: string): URL { } function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion { + //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon : _default_v016061 + //(el.querySelectorAll('div[data-ptimg$="ptimg.json"]') + + /*CMOA :v016452 + ptbinb : "/bib/sws/bibGetCntntInfo.php?u0=1&u1=0" U0 U1 + ptbinbCid : "0000151961_jp_0001" + 'https://www.cmoa.jp/bib/speedreader/?cid=0000151961_jp_0001&u0=1&u1=0' U0 U1 CID + + BOOKHODAI :v016113 / v016130 + ptbinb "https://viewer.bookhodai.jp/sws/apis/bibGetCntntInfo.php?s=1&u0=8bec5433d58929b4ab4b5a07398fff33&u1=4554f324862d187e7c9d27c85e1d8d84" UO U1 + ptbinbCid "300010065401" + 'https://viewer.bookhodai.jp/speedreader/main.php?cid=300010065401&u0=8bec5433d58929b4ab4b5a07398fff33&u1=4554f324862d187e7c9d27c85e1d8d84&rurl=https%3A%2F%2Fbookhodai.jp%2F&member_id=0' U0 U1 CID + + BOOKLIVE :v016113 / v016130 + ptbinb : "/bib-api/bibGetCntntInfo" NOTHING + ptbinbCid: "60114561_001" + 'https://booklive.jp/bviewer/s/?cid=60114561_001' CID + + FUTBANET :v016113 / v016130 + ptbinb: "/sws/bibGetCntntInfo?hash=60ebb4277765619176000000&display_order=1" NOTHING + ptbinbCid: "60ebb4277765619176000000_001-001_1" + https://gaugau.futabanet.jp/list/work/60ebb4277765619176000000/episodes/1 NOTHING + + GETSUAKU :v016113 / v016130 + ptbinb: "../sws/bibGetCntntInfo" NOTHING + ptbinbCid: "001_gaw_makinasan" + https://getsuaku.com/episode/001_gaw_makinasan' NOTHING + + ManpaPlanet :v016113 / v016130 + ptbinb : "https://mangaplanet.com/sws/apis/bibGetCntntInfo.php NOTHING + 'https://mangaplanet.com/reader?cid=64c77843994e3' CID + + ManpaPlaza :v016113 / v016130 + ptbinb: "/sws/apis/bibGetCntntInfo.php?u0=0&u1=https%3A%2F%2Fmangaplaza.com%2Ftitle%2F0303001706%2F%3Forder%3Ddown%26content_id%3D103030017060001" U0 U1 + ptbinbCid: "103030017060001" + 'https://reader.mangaplaza.com/speedreader/?cid=103030017060001&u0=0&u1=https%3A%2F%2Fmangaplaza.com%2Ftitle%2F0303001706%2F%3Forder%3Ddown%26content_id%3D103030017060001' U0 U1 + + OHTABOOK :v016113 / v016130 + ptbinb: "https://console.binb.bricks.pub/bibGetCntntInfo?u0=83605b7e01f64a70baeec6bfe102f043" U0 + ptbinbCid: "cbb2ef02-0210-4050-804d-406713f40f61_1677753204" + 'https://binb.bricks.pub/contents/cbb2ef02-0210-4050-804d-406713f40f61_1677753204/speed_reader' NOTHING + + S-MANGA: :v016113 / v016130 + ptbinb: "./sws/apis/bibGetCntntInfo.php" NOTHING + ptbinbCid: "4088725093" + https://www.s-manga.net/reader/main.php?cid=4088725093' CID + + YANMAGA : v016113 / v016130 + ptbinb: "/viewer/bibGetCntntInfo?type=comics" NOTHING + ptbinbCid: "06A0000000000731237F" + 'https://yanmaga.jp/viewer/comics/%E5%A4%A2%E3%81%86%E3%81%A4%E3%81%A4%E3%81%AE%E8%8A%B1%E3%81%AE%E5%9C%92/351192c0f7d1cf3b88175f3d9dfae594?cid=06A0000000000731237F' CID + + YOUNGJUMP :v016201 + ptbinb :"/sws/apis/bibGetCntntInfo.php?u1=10001" U1 + ptbinbCid: "101012340" + https://www.youngjump.world/reader/reader.html?cid=101012340&u1=10001': CID U1 +*/ + if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { return SpeedBinbVersion.v016113; } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u0') && viewerUrl.searchParams.get('u1')) { return SpeedBinbVersion.v016452; } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u1')) { return SpeedBinbVersion.v016201; } + if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { return SpeedBinbVersion.v016130; } + if (el.querySelectorAll('div[data-ptimg$="ptimg.json"]').length > 0) { return SpeedBinbVersion._default_v016061; } + return SpeedBinbVersion.vUnknown; } @@ -110,34 +173,56 @@ function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion ******** Page List Extraction Methods ******** **********************************************/ +const pageScript = ` + new Promise(resolve => { + resolve ( { location : window.location.href, pages : document.querySelector("div#content.pages")}); + }); +`; + +type pageScriptResult = { + location: string, + pages: HTMLElement +} + /** * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages - * @param baseUrl - Override base chapter url + * @param useScript - use FetchWindowScript and not Fetch for first request + * @param SBVersionOverride - Override SpeedBinb version detection */ -export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, baseUrl = ''): Promise { - const websiteUrl = baseUrl ? new URL(baseUrl).href : new URL(this.URI).href; - let viewerUrl = new URL(chapter.Identifier, websiteUrl); +export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, useScript = false, SBVersionOverride: SpeedBinbVersion = undefined): Promise { + let viewerUrl = new URL(chapter.Identifier, this.URI); const request = new Request(viewerUrl.href, { headers: { - Referer: this.URI.href + Referer: this.URI.origin } });//referer needed for ManpaPlanet - const response = await Fetch(request); - const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); - const data = [...dom.querySelectorAll('div#content.pages')]; - if (data.length == 0) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully - - //handle redirection. Sometimes chapter is redirected - if (response.redirected) { - viewerUrl = new URL(response.url); + let el: HTMLElement = undefined; + + // Raw fetching Gives the most accurate version detection and it handle automatic redirection. + // We dont use FetchCSS because we must know if request is redirected (302, 303) to get real url + // Also, FetchWindowScript doesnt works with Referer, and sometimes Referer is mandatory (MangaPlanet) + if (!useScript) { + const response = await Fetch(request); + const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); + const data = dom.querySelector('div#content.pages'); + //handle redirection. Sometimes chapter is redirected + if (response.redirected) { + viewerUrl = new URL(response.url); + } + el = data[0]; + } else { + //Use this if chapter is redirected using javascript, or if it must be opened in a window to gather access Cookies (MangaPlaza) + const data = await FetchWindowScript(request, pageScript, 2500); + if (!data.pages) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully + viewerUrl = new URL(data.location); + el = data.pages; } - const el = data[0]; - const SBVersion = getSpeedBinbVersion(el, viewerUrl); + const SBVersion = SBVersionOverride || getSpeedBinbVersion(el, viewerUrl); if (SBVersion == SpeedBinbVersion.v016113) { viewerUrl.searchParams.set('cid', el.dataset['ptbinbCid']); @@ -160,21 +245,21 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap uri.searchParams.set('k', sharingKey); switch (SBVersion) { - case SpeedBinbVersion.v016113: //Futabanet, Getsuaku (v016700), Ohtabooks - case SpeedBinbVersion.v016130: { //Booklive, MangaPlanet, S-Manga, Yanmaga - //Doing it like that because of cookies needed for Mangaplanet - const data = await FetchWindowScript(new Request(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + case SpeedBinbVersion.v016113: //BookHodai, Futabanet, Getsuaku (v016700), MangaPlaza, Ohtabooks + case SpeedBinbVersion.v016130: { // Booklive, MangaPlanet, S-Manga, Yanmaga + //Doing it like that because of cookies needed for Mangaplanet using viewerUrl on purpose because of CORS issues + const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); } //YoungJump case SpeedBinbVersion.v016201: { const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); - //Doing it like that because of cookies needed for YoungJump - const data = await FetchWindowScript(new Request(this.URI.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + //Doing it like that because of cookies needed for YoungJump using viewerUrl on purpose because of CORS issues + const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } - //Cmoa, BookHodai + //Cmoa case SpeedBinbVersion.v016452: { const u0 = viewerUrl.searchParams.get('u0'); const u1 = viewerUrl.searchParams.get('u1'); @@ -192,15 +277,16 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap /** * A class decorator that adds the ability to extract all pages for a given chapter using the given CSS {@link query}. * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. - * @param baseUrl - base url to use. Used to create full url when partial endpoint are found + * @param useScript - use FetchWindowScript and not Fetch for first request + * @param SBVersionOverride - Override SpeedBinb version detection */ -export function PagesSinglePageAjax(baseUrl = '') { +export function PagesSinglePageAjax(useScript = false, SBVersionOverride: SpeedBinbVersion = undefined) { 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, baseUrl); + return FetchPagesSinglePageAjax.call(this, chapter, useScript, SBVersionOverride); } }; }; @@ -224,23 +310,6 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config uri.searchParams.set('u0', params.u0); uri.searchParams.set('u1', params.u1); return await fetchSBC(scraper, uri, configuration, chapter); - - } else if (configuration.ServerType === 1) {//BookHodai - const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); - uri.searchParams.set('dmytime', String(Date.now())); - uri.searchParams.set('u0', params.u0); - uri.searchParams.set('u1', params.u1); - const response = await Fetch(new Request(uri.href)); - const data = await response.text(); - const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); - const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - let src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - if (!src.startsWith('/')) src = '/' + src; - return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); - }); - return pageLinks; } return Promise.reject(new Error('Content server type not supported!')); } @@ -290,7 +359,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config uri.searchParams.set('vm', String(configuration.ViewMode)); return await fetchSBC(scraper, uri, configuration, chapter); } - case 1: {//Futabanet, Getsuaku + case 1: {//Futabanet, Getsuaku, BookHodai const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); const response = await Fetch(new Request(uri.href)); @@ -305,7 +374,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config }); return pageLinks; } - case 2: {//MangaPlanet + case 2: {//MangaPlanet, MangaPlaza const uri = getSanitizedURL(configuration.ContentsServer, 'content'); uri.searchParams.set('dmytime', configuration.ContentDate); const data = await FetchJSON(new Request(uri.href, { headers: { Referer: scraper.URI.href } })); From a2dce3e471fba5d0f604b1adbcb3d7a4435ff60f Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 25 Jan 2024 12:19:00 +0100 Subject: [PATCH 44/88] BookHodai : use script and fix test --- web/src/engine/websites/BookHodai.ts | 2 +- web/src/engine/websites/BookHodai_e2e.ts | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index a96346cac1..8f63828283 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -9,7 +9,7 @@ function MangaLabelExtractor(element: HTMLElement): string { } @Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'section.breadcrumb div.bread-text', MangaLabelExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjax(true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts index 84c69e19b0..1396f3c241 100644 --- a/web/src/engine/websites/BookHodai_e2e.ts +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -12,11 +12,12 @@ const config = { }, child: { id: '/viewer?book_id=3000071024&branch_no=01&book_type=4', - title: '(1)' + title: '(1)', + timeout: 15000 }, entry: { index: 0, - size: 1_950_670, + size: 2_198_026, type: 'image/png' } }; From c702f69fe74c5e2c89cfab695bda426e51430eb9 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 25 Jan 2024 12:19:32 +0100 Subject: [PATCH 45/88] Add MangaPlaza --- web/src/engine/websites/MangaPlaza.ts | 53 ++++++++++++++++++++++ web/src/engine/websites/MangaPlaza.webp | Bin 0 -> 1484 bytes web/src/engine/websites/MangaPlaza_e2e.ts | 26 +++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 80 insertions(+) create mode 100644 web/src/engine/websites/MangaPlaza.ts create mode 100644 web/src/engine/websites/MangaPlaza.webp create mode 100644 web/src/engine/websites/MangaPlaza_e2e.ts diff --git a/web/src/engine/websites/MangaPlaza.ts b/web/src/engine/websites/MangaPlaza.ts new file mode 100644 index 0000000000..181705e3ae --- /dev/null +++ b/web/src/engine/websites/MangaPlaza.ts @@ -0,0 +1,53 @@ +import { Tags } from '../Tags'; +import icon from './MangaPlaza.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchJSON } from '../platform/FetchProvider'; + +type APIChapterResult = { + data: { + html_content: string, + html_page: string + } +} + +@Common.MangaCSS(/^{origin}\/title\/\d+\/$/, 'div.mainTitle h1.titleTxt') +@Common.MangasNotSupported() +@SpeedBinb.PagesSinglePageAjax(true) +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('mangaplaza', `MangaPlaza`, ' https://mangaplaza.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override async FetchChapters(manga: Manga): Promise { + const chapters: Chapter[] = []; + const mangaid = manga.Identifier.match(/title\/(\d+)/)[1]; + let page = 1; + let pageMax = 1; + + while (page <= pageMax) { + const request = new Request(new URL(`/api/title/content_list/?title_id=${mangaid}&content_id=0&page=${page}&order=down&_=${Date.now().toString()}`, this.URI)); + const { data } = await FetchJSON(request); + const chaptersNodes = [...new DOMParser().parseFromString(data.html_content, 'text/html').querySelectorAll('ul.detailBox div.inner_table')]; + for (const chapterNode of chaptersNodes) { + const title = chapterNode.querySelector('p.titleName').textContent.trim(); + const linkNode = chapterNode.querySelector('div.btnBlock a.prevBtn'); + if (linkNode) chapters.push(new Chapter(this, manga, linkNode.pathname + linkNode.search, title)); + } + + if (page == 1 && data.html_page != '') { + pageMax = parseInt(new DOMParser().parseFromString(data.html_page, 'text/html').querySelector('ul#_pages li:nth-last-of-type(2) a').dataset.page); + } + page++; + } + + return chapters.distinct(); + } +} \ No newline at end of file diff --git a/web/src/engine/websites/MangaPlaza.webp b/web/src/engine/websites/MangaPlaza.webp new file mode 100644 index 0000000000000000000000000000000000000000..9b3efda50864d7241e580ba07e51bb6367e2f087 GIT binary patch literal 1484 zcmV;-1vC0mNk&G*1pok7MM6+kP&il$0000G0000#002J#06|PpNW}pF00odE+qP;e zbDi_PYlOSIMh@R%BJTk8Tl9+#ctrdakKEloa)0Nn;3*nX5itS$BMPaEjem-e%GkI< zRJN%$NOrD6knBvgQgEVdp))P&Dhf9|dmi5!P*8Feip~bqou<$DAzXNOC%!KNguG+R z(n$+bXMxf$UyFBMUAcMX;dclj8Boj_8t1NBx@yXzLURkH#rN^)kF}Sq@l0%^O6vun(2ROSxX;DGc^``;O!a>ygSNPfg zkyH%E6@;X^*~S%wa-qyfUy9V2?I6`)XDLu)ilhCJG`{`a^EZ$0HX6|Pg|jEkY7Ibg zR0StRAb)=H=JDM|1Ny#j_N3`u6Fo7}(imTR1{l2pOAfjGIpZ(u6U1o3isbmVmcB&mXJQ#O)K^$H>xI=1caYvIf2ffFA< z5oc4q0*U%7I>DSlh8{swGQXjMGZ2)`ZySU&|F!^DP&gpi0{{RJ6#$(9DnI~006v96 zp-`nGqavyt$}pf1fC1gF&HlhW!7C5fad!E<#m|Th5FScDupZ^SfI7v!06%R#GQF06 z(fP(*)Baw)FA_V|mi3OffYVzuulb&1KA!dp{b}@O_37wJumW=QN3JYgEAGYUPXZS& zzLlS+cy%m$`6gXxbxUhE#^F;mQPI~Qu9wNBpd{gpY}borYke)f09qj(H%fo}-^qR3 z_@^Cl#Xgxp0QpIiVKJOO%VJ<12MykfTKg2+FO$xQQBH=+&-N+YspQ5hugh~UzyyNN ztut{yERmp5n=rH;D4c9tJslS1K@G<{n6aE+$IfD}bqWPP6;8#!T0}Q}s0K+r{{HI- z@e|N6B1CzAjW(%Jw!o+I_6vJ*0K#_#@K(3QsRW5-x?hh#>c%b8@;KH>xRMgl5D@;a zIU7q#)wQpvsUGlw&vvu&R9xeSPXsOFa(~Rf;{e>_vJzVYCFkk_SKHoTJ1wJ5Fk?(6 z2c@>u-FS~)4Gl0afMb|ss}YqL)BoJwXGBO6sLA+v2(zT0@~R7tiHB3ALkV+dN8isf zeQA?~9Aiv+el4E}NLQ^QqA<45KrNrG+?C8jDNMgz)BNKnO`ivRnB{?q1rHzMFK>~Z ze5x>4gj_)@t`Y8lp*7p_`5^Z%S8LW1Ml1g=wY?G?sk53u5iu~G8806w$P6m!p#W}u zHN*jqep2f7!3H)pi z2fDKgz;#FS5*?OI!Smeh!$$*ulT#G)x~Wa^eAZ!y#?2v#D}++kU!MBwAw{iO2-k^* zG`At^)mzy$?H@$uJnheR--kUlq|Q5Oz^8uNu8!}mGMHmqAA2ih@^v=C_S>RaF8ew) z4#_`b3%1RzEZ^MA+eM7Wh~a6ZG6V-kQIIuj1Fbg%%$1~#Lfsf9)-%IVx451Z^o6ZJ zR#QNqRZki|V?PbhN{89b*S=JzJgjKmcbOXJz?=Pm9_PFAiMVon_!^+89Pjv2GUXL} z?~4Yy%{TRwd@`ZyFo|CQ!pb*6x`MyWRi(PSvd$2HC`220{RvE;e+$$S{>QRNx{_$; zc5L?6bJE+VLq~Brzx9QLt+oSbCr3b1M|5aF& mpC8sYsmR9mK)jA_GZp;s-c2lqs5baOd*@37-Zkx@2mk=?;@BPl literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/MangaPlaza_e2e.ts b/web/src/engine/websites/MangaPlaza_e2e.ts new file mode 100644 index 0000000000..9bbb91b303 --- /dev/null +++ b/web/src/engine/websites/MangaPlaza_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'mangaplaza', + title: 'MangaPlaza' + }, + container: { + url: 'https://mangaplaza.com/title/0303001706/', + id: '/title/0303001706/', + title: 'Defying Kurosaki-kun' + }, + child: { + id: '/reader/103030017060001/?return_url=https%3A%2F%2Fmangaplaza.com%2Ftitle%2F0303001706%2F%3Forder%3Ddown%26content_id%3D103030017060001', + title: '#1', + timeout: 10000 + }, + entry: { + index: 0, + size: 79_997, + 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/_index.ts b/web/src/engine/websites/_index.ts index 8c2b535173..7fcdca8901 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -322,6 +322,7 @@ export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; From 21425e12ac74b501e89801da454eec2062e195a2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 2 Feb 2024 15:05:10 +0100 Subject: [PATCH 46/88] fix el = undefined --- web/src/engine/websites/decorators/SpeedBinb.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 288a200fe0..6ada9ea8f2 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -200,7 +200,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap } });//referer needed for ManpaPlanet - let el: HTMLElement = undefined; + let SBpagesElement: HTMLElement = undefined; // Raw fetching Gives the most accurate version detection and it handle automatic redirection. // We dont use FetchCSS because we must know if request is redirected (302, 303) to get real url @@ -213,25 +213,25 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap if (response.redirected) { viewerUrl = new URL(response.url); } - el = data[0]; + SBpagesElement = data; } else { //Use this if chapter is redirected using javascript, or if it must be opened in a window to gather access Cookies (MangaPlaza) const data = await FetchWindowScript(request, pageScript, 2500); if (!data.pages) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully viewerUrl = new URL(data.location); - el = data.pages; + SBpagesElement = data.pages; } - const SBVersion = SBVersionOverride || getSpeedBinbVersion(el, viewerUrl); + const SBVersion = SBVersionOverride || getSpeedBinbVersion(SBpagesElement, viewerUrl); if (SBVersion == SpeedBinbVersion.v016113) { - viewerUrl.searchParams.set('cid', el.dataset['ptbinbCid']); + viewerUrl.searchParams.set('cid', SBpagesElement.dataset['ptbinbCid']); } //Handle _default_v016061 : there is no parameter at all - //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon + //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon, TKSuperheroComics if (SBVersion == SpeedBinbVersion._default_v016061) { - const [...imageConfigurations] = el.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + const [...imageConfigurations] = SBpagesElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); return imageConfigurations.map(element => { return new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg)); }); @@ -239,7 +239,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const cid = viewerUrl.searchParams.get('cid'); const sharingKey = _tt(cid); - const uri = getSanitizedURL(viewerUrl.href, el.dataset.ptbinb); + const uri = getSanitizedURL(viewerUrl.href, SBpagesElement.dataset.ptbinb); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', String(Date.now())); uri.searchParams.set('k', sharingKey); From 3d5b09038a857d1ffcef651a10ea47e9459cf00d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 2 Feb 2024 15:06:58 +0100 Subject: [PATCH 47/88] Add Televi-kun Superhero Comics https://github.com/manga-download/hakuneko/issues/6459 --- web/src/engine/websites/TKSuperheroComics.ts | 34 ++++++++++++++++++ .../engine/websites/TKSuperheroComics.webp | Bin 0 -> 420 bytes .../engine/websites/TKSuperheroComics_e2e.ts | 25 +++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 60 insertions(+) create mode 100644 web/src/engine/websites/TKSuperheroComics.ts create mode 100644 web/src/engine/websites/TKSuperheroComics.webp create mode 100644 web/src/engine/websites/TKSuperheroComics_e2e.ts diff --git a/web/src/engine/websites/TKSuperheroComics.ts b/web/src/engine/websites/TKSuperheroComics.ts new file mode 100644 index 0000000000..9d6b10b542 --- /dev/null +++ b/web/src/engine/websites/TKSuperheroComics.ts @@ -0,0 +1,34 @@ +import { Tags } from '../Tags'; +import icon from './TKSuperheroComics.webp'; +import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchCSS} from '../platform/FetchProvider'; +function MangaExtractor(anchor: HTMLAnchorElement) { + return { + id: anchor.pathname, + title: anchor.querySelector('.rensai-episode-title').textContent.trim() + }; +} + +@Common.MangaCSS(/{origin}\/rensai\/[^/]+\/$/, 'div.manga-overview-top-wrapper h2.manga-heading') +@Common.MangasSinglePageCSS('/rensai', 'li.rensai-episode-list a', MangaExtractor) +@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('tksuperherocomics', `Televi-kun Superhero Comics (てれびくんスーパーヒーローコミックス)`, 'https://televikun-super-hero-comics.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } + + public override async FetchChapters(manga: Manga): Promise { + const mangaUrl = new URL(manga.Identifier, this.URI); + const chapters = await FetchCSS(new Request(mangaUrl), 'section[data-start-date].manga-all-episode-section li.manga-all-episode-list a:not([href^="http"])'); + return chapters.map(chapter => new Chapter(this, manga, `${manga.Identifier}${chapter.getAttribute('href')}`, chapter.text.trim())); + } + +} \ No newline at end of file diff --git a/web/src/engine/websites/TKSuperheroComics.webp b/web/src/engine/websites/TKSuperheroComics.webp new file mode 100644 index 0000000000000000000000000000000000000000..b4e7b647bcabb836dd43b336e9725e6d0ca21004 GIT binary patch literal 420 zcmV;V0bBl3Nk>0RRA3MM6+kP&gov0RRAS3jmz~DnI~006v96p-`nGqa&soso0

*ux@w2c(=BLGOp)-s7%_r1d5FDXFJ!s$HGPSpstb4mDJ z`}xrX@C3zNcKU&XX1#d7HCBW0Lks`_{_i#i^S@K>7ez1fZ$jwn@%PaVCWS;CHwAIb z%klr?$Bc2Pz_Q)j#daRrVw^89P#u7z#nsId zuT5ZT#lvIZ2%DsHSoXB`*s9Whfs?V}(OZ>WEoc9b3Xk+#a$4_VdoCsM`HqUW+KT`5 zqY_$Tu>Zzr7L*k#(qHt+%?HU0JOyJ|iqY(yzjLhaKyTE<<~hRbhv7Gs!XfMqOZr&KjQ&S_I)R)Du^^D4}3Bg;(EW|kVy`8=DfFbjtu6lEkHWJ>_$w1 zi>cOkA_$j*c|uPsKx%DIZE!5#`k&?ZpwryhoQd75*{kNgVHh5e(pB-6B~to+a|Gx) O!W%$OAHtp{NB{sR57F`f literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/TKSuperheroComics_e2e.ts b/web/src/engine/websites/TKSuperheroComics_e2e.ts new file mode 100644 index 0000000000..29a65a70bb --- /dev/null +++ b/web/src/engine/websites/TKSuperheroComics_e2e.ts @@ -0,0 +1,25 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'tksuperherocomics', + title: 'Televi-kun Superhero Comics (てれびくんスーパーヒーローコミックス)' + }, + container: { + url: 'https://televikun-super-hero-comics.com/rensai/theheroisinside/', + id: '/rensai/theheroisinside/', + title: 'ヒーローは中にいる!' + }, + child: { + id: '/rensai/theheroisinside/episode-017/', + title: '17話 合宿スタート!!', + }, + entry: { + index: 0, + size: 1_867_196, + 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/_index.ts b/web/src/engine/websites/_index.ts index 7fcdca8901..fa25c3ef92 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -555,6 +555,7 @@ export { default as TempestScans } from './TempestScans'; export { default as TenshiID } from './TenshiID'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; From e202388204691b605994d27aca4d48f8d8a964ab Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 3 Feb 2024 16:37:54 +0100 Subject: [PATCH 48/88] Update _index.ts --- web/src/engine/websites/_index.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 65aea1c057..915280fd53 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -38,6 +38,8 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CarToonMad } from './CarToonMad'; @@ -45,12 +47,14 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -59,10 +63,13 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicWalker } from './ComicWalker'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -85,6 +92,7 @@ export { default as DemoneCeleste } from './DemoneCeleste'; export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -122,6 +130,7 @@ export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FRScan } from './FRScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -130,6 +139,7 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GekkouScans } from './GekkouScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; export { default as Gntai } from './Gntai'; @@ -320,6 +330,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -431,7 +443,9 @@ export { default as NiveraFansub } from './NiveraFansub'; export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -533,6 +547,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as Siyahmelek } from './Siyahmelek'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -555,6 +570,7 @@ export { default as TempestScans } from './TempestScans'; export { default as TenshiID } from './TenshiID'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; @@ -605,6 +621,7 @@ export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -612,6 +629,7 @@ export { default as YaoiScan } from './YaoiScan'; export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasES } from './YugenMangasES'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; @@ -633,16 +651,11 @@ export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -652,7 +665,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -744,9 +756,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RawMangatop } from './legacy/RawMangatop'; @@ -797,6 +807,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 1b2a46b989f7e8d206ea86c5d35ad001c5287678 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 5 Feb 2024 18:29:21 +0100 Subject: [PATCH 49/88] Update _index.ts --- web/src/engine/websites/_index.ts | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 47198eb561..57788582fd 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -42,6 +42,8 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -50,12 +52,14 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as ChibiManga } from './ChibiManga'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -64,11 +68,14 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicWalker } from './ComicWalker'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -94,6 +101,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -134,6 +142,7 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -142,6 +151,7 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GekkouScans } from './GekkouScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; export { default as Gntai } from './Gntai'; @@ -348,6 +358,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -470,7 +482,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -577,6 +591,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as Siyahmelek } from './Siyahmelek'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -602,6 +617,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; @@ -660,6 +676,7 @@ export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -667,6 +684,7 @@ export { default as YaoiScan } from './YaoiScan'; export { default as YaoiToshokan } from './YaoiToshokan'; export { default as YawarakaSpirits } from './YawarakaSpirits'; export { default as Ynjn } from './Ynjn'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as Yurineko } from './Yurineko'; @@ -687,16 +705,11 @@ export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -706,7 +719,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -798,9 +810,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RawMangatop } from './legacy/RawMangatop'; @@ -851,6 +861,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From e680a5f433a35f10d7b717239ee0d0f3f8f6ca54 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 8 Feb 2024 15:32:51 +0100 Subject: [PATCH 50/88] Add ComicPorta https://github.com/manga-download/hakuneko/issues/6761 --- web/src/engine/websites/ComicPorta.ts | 28 ++++++++++++++++++ web/src/engine/websites/ComicPorta.webp | Bin 0 -> 1706 bytes web/src/engine/websites/ComicPorta_e2e.ts | 25 ++++++++++++++++ web/src/engine/websites/_index.ts | 1 + .../engine/websites/decorators/SpeedBinb.ts | 3 +- 5 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 web/src/engine/websites/ComicPorta.ts create mode 100644 web/src/engine/websites/ComicPorta.webp create mode 100644 web/src/engine/websites/ComicPorta_e2e.ts diff --git a/web/src/engine/websites/ComicPorta.ts b/web/src/engine/websites/ComicPorta.ts new file mode 100644 index 0000000000..b5667dc22e --- /dev/null +++ b/web/src/engine/websites/ComicPorta.ts @@ -0,0 +1,28 @@ +import { Tags } from '../Tags'; +import icon from './BookHodai.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; + +function ChapterExtractor(element: HTMLElement) { + return { + id: element.querySelector('a').pathname, + title: element.parentNode.querySelector('p.title').textContent.trim() + }; +} + +@Common.MangaCSS(/^{origin}\/series\/\d+\/$/, 'div#breadcrumb li:last-of-type') +@Common.MangasSinglePageCSS('/series/', 'div.series-list ul li h3.title a') +@Common.ChaptersSinglePageCSS('ul.episode-list li.episode div.inner div.wrap p.episode-btn', ChapterExtractor) +@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('comicporta', `COMICポルタ (Comic Porta)`, 'https://comic-porta.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); + } + + public override get Icon() { + return icon; + } +} diff --git a/web/src/engine/websites/ComicPorta.webp b/web/src/engine/websites/ComicPorta.webp new file mode 100644 index 0000000000000000000000000000000000000000..93de513dd008ca06dca988ff28a72c1ac300c618 GIT binary patch literal 1706 zcmV;b237e|Nk&GZ1^@t8MM6+kP&il$0000G0000#002J#06|PpNNWQC01cpoZQB{i zdcOZpy5`unZQHhO+uGT-ZQHi()9#t6u0eBDo#g-DMZ0@Bn~0bIW`;J6GLvbP)l>l& zM~e?9pSXM32&U0t#iA=6x6gMjtTJ}0$q6*VTwMR{4^p4)w^!Ze5DhWHBR}qa<~fdi z54d?EI_Zo5OVcn7mw8a=OO(&AA*T60H{x``@8?|ltuFwQ7zdXq^zxwqoI?`ArWvm1 z{+(YZZ1m@a|G!MwXVJTS%o)Oh-Y%bSx7CUdKaTYFCL)oq-!&grJu+@jO}67xh%^5B z*u_D(BeG|}75iU`((Q^LTk6W=y9?3VB~}#nILrS|Hs^c~5Rb0R_Rdt(KzulG*Y3+F zC)o)*^50);thn6#_w;wnCCs~!Jv zOFxEsN<^k~Eq>thp;&u&9D_E@41^@i&%W5g%P#r)FJR6H5vI=?=UQgjA2@BZ*Vo?w z4MD$#nE{gU8JL1#*2R{Xm3iJR0XlS7B*(Cu8MtV1?sZpQWsSuFN^=sNSrCaaVzu~t z2txBOrCkIG;EfS&En|QA=by4?@1vq;G>$!h-kw<)r3Oj9;PLPL65U7=7|0^XDE!0B zb~YnWNC?b4C^%0|2J+!5@|$o&C4>YxXP99Cn%=cY%A`-11CpMDm*xrxejow~fjNg^ zM(@14t+TDQGI{*OuC8Ss{Nkm50DRBdC-CYYHCc)f5}0`~!vNy+_Kx-mt&=L{j;VP{ z|I_vZe3TV)-^xEX5!eCDFauDvv!ioTd1706QfG!SQ0G91YSmjP03M|KEYj+A$U56P z+biYva;0NN;Tfni10kUp>DvkcXvaA?iKNQ9Jbzi9GEg%ILWm$Sc+vNF?s<}`amc?0 z;LJcmL`6nq*RIZTMB7+rf*>)%Eq9`~D;S-!NNS~q z^Z@e4_Bs8|^o(e&G_LVX0Mbn|zZqXedjtNp^`7!GV?{BM)(yLqusx2y z2o|1GH7>g|-LYUb&fPe%=`!tw~zRPSbmo+JLffC5)e%9 z{>@{J8W1)Bxcg^N*<(?he(#PL#QfF7WxG}rN9@Xc^FwbTCHu1gA{c-2Teqh8$xSTv z<|b*RxcneJLBdASZ?>w5VRxXh83JTmV21AP7{qyBlL z;Z7rC9kSA_!7Vy!`yt|xwbi{nu0tV4RQ*1pyguiO%>B|L#F1{iI-8Y@?S~xQuY-W2 z!_#k(nc6|BQ){QNH2Y$u2UIGEU@)54F`tW#y`gw%i-ZzN;Bc5C`0CpUkWn}-`1bJ{ z|5YmL*#-7nMSH&M5Xw9yu76t#COj;yOYn;m=WgOeZ0N(a)?P$~%fT#*|<)lZiC zJ2OgP$ZW&F{e>Ao=`*b>9AfB3q(33IKmXO+X$~U 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 57788582fd..aa0d36894e 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -72,6 +72,7 @@ export { default as ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 6ada9ea8f2..d0f6c82b99 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -275,8 +275,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap } /** - * A class decorator that adds the ability to extract all pages for a given chapter using the given CSS {@link query}. - * The pages are extracted from the composed url based on the `Identifier` of the chapter and the `URI` of the website. + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. * @param useScript - use FetchWindowScript and not Fetch for first request * @param SBVersionOverride - Override SpeedBinb version detection */ From 60b65fb94cd6e0714788a3ba16b8210ff16b6544 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 26 Feb 2024 16:17:13 +0100 Subject: [PATCH 51/88] Update _index.ts --- web/src/engine/websites/_index.ts | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index a13256c2ed..d2df84d1ea 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -42,6 +42,8 @@ export { default as BestManhua } from './BestManhua'; export { default as BibiManga } from './BibiManga'; export { default as BlogTruyen } from './BlogTruyen'; export { default as Bokugents } from './Bokugents'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -49,12 +51,14 @@ export { default as CarToonMad } from './CarToonMad'; export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -63,11 +67,15 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -94,6 +102,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -133,6 +142,7 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -141,6 +151,7 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GekkouScans } from './GekkouScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GloryManga } from './GloryManga'; export { default as Gntai } from './Gntai'; @@ -350,6 +361,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -477,7 +490,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -584,6 +599,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as Siyahmelek } from './Siyahmelek'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -610,6 +626,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; @@ -668,6 +685,7 @@ export { default as xianman123 } from './xianman123'; export { default as XlecX } from './XlecX'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -676,6 +694,7 @@ 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 YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as Yurineko } from './Yurineko'; @@ -696,16 +715,11 @@ export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliComics } from './legacy/BilibiliComics'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -715,7 +729,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -805,9 +818,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RawMangatop } from './legacy/RawMangatop'; @@ -858,6 +869,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 164b251b7ae2b850eb6866e59f59d82bc18958ca Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 7 Mar 2024 21:13:55 +0100 Subject: [PATCH 52/88] Add YoManga https://github.com/manga-download/hakuneko/issues/6861 --- web/src/engine/websites/YoMonga.ts | 36 +++++++++++++++++++++++++ web/src/engine/websites/YoMonga.webp | Bin 0 -> 1358 bytes web/src/engine/websites/YoMonga_e2e.ts | 26 ++++++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 63 insertions(+) create mode 100644 web/src/engine/websites/YoMonga.ts create mode 100644 web/src/engine/websites/YoMonga.webp create mode 100644 web/src/engine/websites/YoMonga_e2e.ts diff --git a/web/src/engine/websites/YoMonga.ts b/web/src/engine/websites/YoMonga.ts new file mode 100644 index 0000000000..1e29d6b6cc --- /dev/null +++ b/web/src/engine/websites/YoMonga.ts @@ -0,0 +1,36 @@ +import { Tags } from '../Tags'; +import icon from './YoMonga.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; + +function MangaExtractor(element: HTMLElement) { + return { + id: element.querySelector('a').pathname, + title: element.querySelector('div.book-box4-title').textContent.trim() + }; +} + +function ChapterExtractor(element: HTMLElement) { + const anchor = element.querySelector('a'); + return { + id: anchor.pathname + anchor.search, + title: element.querySelector('span').textContent.trim() + }; +} + +@Common.MangaCSS(/^{origin}\/titles\/\d+\//, 'div.intr-title') +@Common.MangasMultiPageCSS('/titles/?page_num={page}', 'div.book-box4', 1, 1, 0, MangaExtractor) +@Common.ChaptersSinglePageCSS('div.episode-list', ChapterExtractor) +@SpeedBinb.PagesSinglePageAjax(true) +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + public constructor() { + super('yomonga', `YoMonga`, 'https://www.yomonga.com', 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/YoMonga.webp b/web/src/engine/websites/YoMonga.webp new file mode 100644 index 0000000000000000000000000000000000000000..58a636f82acffafb829cfcb8c6691b03b8da528c GIT binary patch literal 1358 zcmV-U1+n^4Nk&FS1pok7MM6+kP&il$0000G0000#002J#06|PpNO=GN00D3tNw%CU zH)Ny?D7>49C@e_gix4PGL>TfhZ(M2r+WlXc7=4|@}y{Uo^S04cKS7u5x z%tOX^Z+X@X8r*ZUw@)RWV{|&94hbr3Fae0j=?SXyV4bRs70T>6PQyJu)}0x`nGIE9 z1ag*X;M?wL66Q-&W@Nrh<0!eRCMhH0SMff)j%8q_6*A|AUzrmMj_~Y6PrD2y%3Gy5OkVh@PP^_C6&Gwz))4s;r9vK1hE|0{$SV3{s9&;`&K`$EL*-R$j^As zg5+R%xwDic@9pG#qGZQRZ6+UL_lcOnOCX`>9TTA0H|$0}WUIAd&pQxcQ8`KRJRVt5 zG8O!*{60URTLq8xgmfQ+NJaXTVO6H-=`|Gz|a7o)V4sje^flboWy(lJhs)OQ`6kh1i*s9XXz96v`w+ ze(3rQ>M5b?l0WnrpB6%A{l&Xar>zgNfdp_h5jo4x{}5z%#xMTfwbOGuu4dhH$jd?g zHCDj%Kdq7%%UgMzTOV2CbD75;?Nxurr&>kr{p9*aQWG{awVjL{z28twe0g7&fl(6!<3SkXdzXb16D`mTa`%HIfm#^T+uAoey6cUY~F7 zj~?(CMLz()u?@BQpPu%|MHeE$AB|2(LAGHhD!=FiT>>f=>&^Ts^fSXo2LRUf;il^6W(Cb QU_ke$C1b5NVp$tN0JR^N_5c6? literal 0 HcmV?d00001 diff --git a/web/src/engine/websites/YoMonga_e2e.ts b/web/src/engine/websites/YoMonga_e2e.ts new file mode 100644 index 0000000000..e8e13fb0ff --- /dev/null +++ b/web/src/engine/websites/YoMonga_e2e.ts @@ -0,0 +1,26 @@ +import { TestFixture } from '../../../test/WebsitesFixture'; + +const config = { + plugin: { + id: 'yomonga', + title: 'YoMonga' + }, + container: { + url: 'https://www.yomonga.com/titles/306/?episode=113', + id: '/titles/306/', + title: '部長と社畜の恋はもどかしい' + }, + child: { + id: '/titles/306/?episode=1', + title: 'Chapter.1', + timeout: 20000 + }, + entry: { + index: 0, + size: 4_190_733, + 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/_index.ts b/web/src/engine/websites/_index.ts index d2df84d1ea..d23ee5decc 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -694,6 +694,7 @@ 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 YoMonga } from './YoMonga'; export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; From 6f450dec1840d80e0c39977569c0990724682949 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 9 Mar 2024 13:33:07 +0100 Subject: [PATCH 53/88] code refactoring --- web/src/engine/websites/Cmoa.ts | 5 ++- web/src/engine/websites/ComicBrise.ts | 6 ++-- web/src/engine/websites/ComicMeteor.ts | 13 +++---- web/src/engine/websites/ComicPolaris.ts | 26 +++++++------- web/src/engine/websites/ComicValkyrie.ts | 15 ++++---- web/src/engine/websites/DigitalMargaret.ts | 14 ++++---- web/src/engine/websites/Getsuaku.ts | 5 ++- web/src/engine/websites/MangaPlanet.ts | 7 ++-- web/src/engine/websites/Ohtabooks.ts | 37 +++++++------------- web/src/engine/websites/OneTwoThreeHon.ts | 17 ++++----- web/src/engine/websites/SManga.ts | 2 +- web/src/engine/websites/TKSuperheroComics.ts | 3 +- web/src/engine/websites/Yanmaga.ts | 7 ++-- web/src/engine/websites/YoungJump.ts | 3 +- 14 files changed, 72 insertions(+), 88 deletions(-) diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index e45c65c49a..49c9b83b9b 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -26,14 +26,13 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new Request(new URL(manga.Identifier, this.URI).href); - const pages = await FetchCSS(request, '#comic_list > .pagination:nth-child(1) li:nth-last-child(2) a'); + const pages = await FetchCSS(new Request(new URL(manga.Identifier, this.URI).href), '#comic_list > .pagination:nth-child(1) li:nth-last-child(2) a'); const chapters = []; const totalPage = pages.length == 0 ? 1 : parseInt(new URL(pages[0].href).searchParams.get('page')); for (let i = 0; i < totalPage; i++) { const uri = new URL(manga.Identifier, this.URI); uri.searchParams.set('page', String(i + 1)); - const pageRequest = new Request(uri.href); + const pageRequest = new Request(uri); const data = await FetchCSS(pageRequest, '.title_vol_vox_vols .title_vol_vox_vols_i'); for (const element of data) { const chapterLink = element.querySelector('a[href^="/reader/"]'); diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index e1931a4724..2e7ce42708 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -19,10 +19,8 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const uri = new URL(manga.Identifier, this.URI); - const request = new Request(uri.href); - const data = await FetchCSS(request, '.modal.modal-chapter .modal-body'); - return data.reverse() + return (await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), '.modal.modal-chapter .modal-body')) + .reverse() //.filter(e => e.querySelector(".banner-trial img").getAttribute("alt") == "FREE") //dont filter for free chapter .map(element => new Chapter(this, manga, element.querySelector('.banner-trial a').pathname, element.querySelector('.primary-title').textContent.trim())); } diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index 40149e6217..e85c04eb04 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -6,9 +6,10 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('img').getAttribute('alt').trim(); - return { id, title }; + return { + id: anchor.pathname, + title: anchor.querySelector('img').getAttribute('alt').trim() + }; } @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @@ -24,11 +25,11 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new Request(new URL(manga.Identifier, this.URI).href); - const contents = await FetchCSS(request, 'div#contents'); - const data = contents[0]; + const [ data ] = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div#contents'); + let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn.work_episode_link_orange a')] .map(element => new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim())); + if (chapterList.length == 0) { chapterList = [...data.querySelectorAll('div.latest_info_box div.latest_info_link_btn01 a')] .map(element => new Chapter(this, manga, element.pathname, element.text.replace('読む', '').trim())); diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index a9769e987c..30cee190c5 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -6,9 +6,10 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('img').getAttribute('alt').trim(); - return { id, title }; + return { + id: anchor.pathname, + title: anchor.querySelector('img').getAttribute('alt').trim() + }; } @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @@ -16,25 +17,22 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { - public constructor() { - super('comicpolaris', `COMICポラリス (COMIC Polaris)`, 'https://comic-polaris.jp', Tags.Media.Manga, Tags.Language.Japanese); + super('comicpolaris', `COMICポラリス (COMIC Polaris)`, 'https://comic-polaris.jp', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); } public override get Icon() { return icon; } + public override async FetchChapters(manga: Manga): Promise { - const request = new Request(new URL(manga.Identifier, this.URI).href); - const data = (await FetchCSS(request, 'div#contents'))[0]; + const [ data ] = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div#contents'); + let chapterList = [...data.querySelectorAll('div.work_episode div.work_episode_box div.work_episode_table div.work_episode_link_btn a')] - .map(element => { - return new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim()); - }); - if (chapterList.length === 0) { + .map(element => new Chapter(this, manga, element.pathname, element.closest('div.work_episode_table').querySelector('div.work_episode_txt').innerText.replace(manga.Title, '').trim())); + + if (chapterList.length == 0) { chapterList = [...data.querySelectorAll('div.latest_info_box div.latest_info_link_btn01 a')] - .map(element => { - return new Chapter(this, manga, element.pathname, element.text.replace('読む', '').trim()); - }); + .map(element => new Chapter(this, manga, element.pathname, element.text.replace('読む', '').trim())); } return chapterList; } diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 170dca903c..7cd6408066 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -6,15 +6,16 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(element: HTMLElement) { - const id = new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'); - const title = element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim(); - return { id, title }; + return { + id: new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'), + title: element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim() + }; } function ChapterExtractor(element: HTMLElement) { - const a = element.parentElement.querySelector('a.read_bt'); - const id = a.pathname; - const title = element.textContent.trim(); - return { id, title }; + return { + id: element.parentElement.querySelector('a.read_bt').pathname, + title: element.textContent.trim() + }; } @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 3f8cc1b3dc..81c0a00151 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -5,14 +5,16 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('img').getAttribute('alt').trim(); - return {id, title}; + return { + id: anchor.pathname, + title: anchor.querySelector('img').getAttribute('alt').trim() + }; } function ChapterExtractor(element: HTMLElement) { - const id = element.querySelector('a').pathname; - const title = element.querySelector('p').textContent.trim(); - return { id, title }; + return { + id: element.querySelector('a').pathname, + title: element.querySelector('p').textContent.trim() + }; } @Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts index eee8eba1f2..9e3d6f2218 100644 --- a/web/src/engine/websites/Getsuaku.ts +++ b/web/src/engine/websites/Getsuaku.ts @@ -36,9 +36,8 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const bookid = await FetchWindowScript(new Request(new URL(manga.Identifier, this.URI).href), 'book_id', 1500); - const url = new URL(`/api/sort_episodes?book_id=${bookid}&order=asc&mode=all`, this.URI); - const chapters = await FetchJSON(new Request(url.href)); + const bookid = await FetchWindowScript(new Request(new URL(manga.Identifier, this.URI)), 'book_id', 1500); + const chapters = await FetchJSON(new Request(new URL(`/api/sort_episodes?book_id=${bookid}&order=asc&mode=all`, this.URI))); return chapters.objects.map(chapter => new Chapter(this, manga, `/episode/${chapter.cid}`, chapter.episode_number.trim())); } } \ No newline at end of file diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 484b0bcfec..adcd6be6bb 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -25,14 +25,11 @@ export default class extends DecoratableMangaScraper { } public override async Initialize(): Promise { - const request = new Request(this.URI.href); - return FetchWindowScript(request, `window.cookieStore.set('mpaconf', '18')`); + return FetchWindowScript(new Request(this.URI), `window.cookieStore.set('mpaconf', '18')`); } public override async FetchChapters(manga: Manga): Promise { - const uri = new URL(manga.Identifier, this.URI); - const request = new Request(uri.href); - const data = await FetchCSS(request, '#accordion div[id*="vol_"]'); + const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), '#accordion div[id*="vol_"]'); const chapters : Chapter[] = []; for (const volume of data) { const title = volume.querySelector('h3').textContent.trim() + " - "; diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 08713216dd..75df597812 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -6,9 +6,10 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('.title').textContent.trim(); - return { id, title }; + return { + id: anchor.pathname, + title: anchor.querySelector('.title').textContent.trim() + }; } @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'h2.contentTitle') @@ -26,30 +27,18 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { //find real reader url to send to SpeedBinb, since redirection is done by Javascript - const data = await FetchCSS(new Request(chapter.Identifier), 'body'); - const reallink = data[0].innerHTML.match(/location.href='(.*)'/)[1]; - return await SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); + const [ data ] = await FetchCSS(new Request(chapter.Identifier), 'body'); + const reallink = data.innerHTML.match(/location.href='(.*)'/)[1]; + return SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } public override async FetchChapters(manga: Manga): Promise { - const uri = new URL(manga.Identifier, this.URI); - const data = await FetchCSS(new Request(uri.href), 'a[onClick^="return !openBook("]'); - let chapterList = data.map(element => { - let partId = element.getAttribute('onclick'); - partId = partId.match(/\d+/)[0]; - - let title = element.querySelector('.title') ? element.querySelector('.title').textContent : element.querySelector('btnMini') ? element.querySelector('btnMini').textContent : 'マンガをよむ'; - title = title.trim(); - return { - id: 'https://yondemill.jp/contents/' + partId + '?view=1&u0=1', - title: title - }; - }); - // Remove duplicates - chapterList = chapterList.reverse().filter((chapter, index) => { - return index === chapterList.findIndex(c => c.id === chapter.id); + const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'a[onClick^="return !openBook("]'); + const chapterList = data.map(element => { + const partId = element.getAttribute('onclick').match(/\d+/)[0]; + const title = element.querySelector('.title') ? element.querySelector('.title').textContent : element.querySelector('btnMini') ? element.querySelector('btnMini').textContent : 'マンガをよむ'; + return new Chapter(this, manga, `https://yondemill.jp/contents/${partId}?view=1&u0=1`, title.trim()); }); - - return chapterList.map(chapter => new Chapter(this, manga, chapter.id, chapter.title)); + return chapterList.reverse().distinct(); } } \ No newline at end of file diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index 9dc1a515fc..0cd2ef5622 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -6,9 +6,10 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.pathname.match(/[^/]+\/web-comic\/([^/]+)\//)[1]; - return { id, title }; + return { + id: anchor.pathname, + title: anchor.pathname.match(/[^/]+\/web-comic\/([^/]+)\//)[1] + }; } @Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') @@ -17,7 +18,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { export default class extends DecoratableMangaScraper { public constructor() { - super('onetwothreehon', `123hon`, 'https://www.123hon.com', Tags.Media.Manga, Tags.Language.Japanese ); + super('onetwothreehon', `123hon`, 'https://www.123hon.com', Tags.Media.Manga, Tags.Language.Japanese, Tags.Source.Official); } public override get Icon() { @@ -35,12 +36,12 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const request = new Request(new URL(manga.Identifier, this.URI).href); - const data = await FetchCSS(request, 'div.read-episode li'); - return data.map(element => { + const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div.read-episode li'); + const chapterlist : Chapter[] = data.map(element => { if (element.querySelector('a')) { // otherwise chapter not available return new Chapter(this, manga, new URL(element.querySelector('a').pathname.replace(/index.html$/, ''), this.URI).pathname, element.innerText.match(/\s*(.*?)\s+/)[1]); } - }).filter(element => element !== undefined).filter(element => element.Identifier != '/'); + }); + return chapterlist.distinct(); } } \ No newline at end of file diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index 1affd7fa1e..7cbf78957e 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -43,7 +43,7 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const url = new URL(`/search/search.html?seriesid=${manga.Identifier}&order=1`, this.URI); - const { data } = await FetchWindowScript(new Request(url.href), 'window.ssd', 2000); + const { data } = await FetchWindowScript(new Request(url), 'window.ssd', 2000); return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.isbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); } diff --git a/web/src/engine/websites/TKSuperheroComics.ts b/web/src/engine/websites/TKSuperheroComics.ts index 9d6b10b542..a32950eeda 100644 --- a/web/src/engine/websites/TKSuperheroComics.ts +++ b/web/src/engine/websites/TKSuperheroComics.ts @@ -26,8 +26,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchChapters(manga: Manga): Promise { - const mangaUrl = new URL(manga.Identifier, this.URI); - const chapters = await FetchCSS(new Request(mangaUrl), 'section[data-start-date].manga-all-episode-section li.manga-all-episode-list a:not([href^="http"])'); + const chapters = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'section[data-start-date].manga-all-episode-section li.manga-all-episode-list a:not([href^="http"])'); return chapters.map(chapter => new Chapter(this, manga, `${manga.Identifier}${chapter.getAttribute('href')}`, chapter.text.trim())); } diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index 2cc7a255a6..ab7397aedb 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -5,9 +5,10 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { - const id = anchor.pathname; - const title = anchor.querySelector('.mod-book-title').textContent.trim(); - return { id, title }; + return { + id: anchor.pathname, + title: anchor.querySelector('.mod-book-title').textContent.trim() + }; } const chapterScript = ` diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index 845ad556cf..c1facb8c24 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -36,8 +36,7 @@ export default class extends DecoratableMangaScraper { } public override async FetchMangas(provider: MangaPlugin): Promise { - const request = new Request(new URL('/yj-rest-apis/getBookInfo.php', this.URI).href); - const data = await FetchJSON(request); + const data = await FetchJSON(new Request(new URL('/yj-rest-apis/getBookInfo.php', this.URI))); return data.map(magazine => new Manga(this, provider, magazine.url, `${magazine.issue} - ${magazine.number}`.trim())); } From 2651630f1a54d34bfcf9224afb36ff7757239cba Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 17 Apr 2024 11:29:16 +0200 Subject: [PATCH 54/88] fix cmoa test --- web/src/engine/websites/Cmoa_e2e.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/engine/websites/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts index 6241f6d6df..2b3f73bd9a 100644 --- a/web/src/engine/websites/Cmoa_e2e.ts +++ b/web/src/engine/websites/Cmoa_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 2_879_995, + size: 2_880_733, type: 'image/png' } }; From 38f2b910a6a9c0da61daaac7b162ed6ea1d2b096 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Apr 2024 14:34:37 +0200 Subject: [PATCH 55/88] use correct cases --- web/src/engine/websites/SManga.ts | 6 +-- .../engine/websites/decorators/SpeedBinb.ts | 53 +++++++++---------- 2 files changed, 29 insertions(+), 30 deletions(-) diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index 7cbf78957e..69f22fb994 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -44,10 +44,10 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const url = new URL(`/search/search.html?seriesid=${manga.Identifier}&order=1`, this.URI); const { data } = await FetchWindowScript(new Request(url), 'window.ssd', 2000); - return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.isbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); + return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.IsbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); } - isbnToCid(ISBN: string): string { - return ISBN.replaceAll('-', ''); + IsbnToCid(isbn: string): string { + return isbn.replaceAll('-', ''); } } \ No newline at end of file diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index d0f6c82b99..8fa901312b 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -4,11 +4,11 @@ import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; import DeScramble from '../../transformers/ImageDescrambler'; -type JSONPageData_v016452 = { - items: Configuration_v016452[] +type JSONPageDatav016452 = { + items: Configurationv016452[] } -type Configuration_v016452 = { +type Configurationv016452 = { ContentID: string, ctbl: string | string[], ptbl: string | string[], @@ -19,28 +19,28 @@ type Configuration_v016452 = { ContentDate: string } -type Params_v016452 = { +type Paramsv016452 = { cid: string, u0: string, u1: string, sharingKey: string } -type JSONImageData_v016061 = { +type JSONImageDatav016061 = { resources: { i: { src: string } } - views: PageView_v016061[] + views: PageViewv016061[] } -type PageView_v016061 = { +type PageViewv016061 = { coords: string[], width: number, height: number } -type PageView_v016130 = { +type PageViewv016130 = { transfers: { index: number, coords: DrawImageCoords[] @@ -179,7 +179,7 @@ const pageScript = ` }); `; -type pageScriptResult = { +type PageScriptResult = { location: string, pages: HTMLElement } @@ -190,9 +190,9 @@ type pageScriptResult = { * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages * @param useScript - use FetchWindowScript and not Fetch for first request - * @param SBVersionOverride - Override SpeedBinb version detection + * @param sbVersionOverride - Override SpeedBinb version detection */ -export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, useScript = false, SBVersionOverride: SpeedBinbVersion = undefined): Promise { +export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, useScript = false, sbVersionOverride: SpeedBinbVersion = undefined): Promise { let viewerUrl = new URL(chapter.Identifier, this.URI); const request = new Request(viewerUrl.href, { headers: { @@ -216,13 +216,13 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap SBpagesElement = data; } else { //Use this if chapter is redirected using javascript, or if it must be opened in a window to gather access Cookies (MangaPlaza) - const data = await FetchWindowScript(request, pageScript, 2500); + const data = await FetchWindowScript(request, pageScript, 2500); if (!data.pages) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully viewerUrl = new URL(data.location); SBpagesElement = data.pages; } - const SBVersion = SBVersionOverride || getSpeedBinbVersion(SBpagesElement, viewerUrl); + const SBVersion = sbVersionOverride || getSpeedBinbVersion(SBpagesElement, viewerUrl); if (SBVersion == SpeedBinbVersion.v016113) { viewerUrl.searchParams.set('cid', SBpagesElement.dataset['ptbinbCid']); @@ -248,7 +248,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap case SpeedBinbVersion.v016113: //BookHodai, Futabanet, Getsuaku (v016700), MangaPlaza, Ohtabooks case SpeedBinbVersion.v016130: { // Booklive, MangaPlanet, S-Manga, Yanmaga //Doing it like that because of cookies needed for Mangaplanet using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); } //YoungJump @@ -256,7 +256,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); //Doing it like that because of cookies needed for YoungJump using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } //Cmoa @@ -265,8 +265,8 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u1 = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u0', u0); uri.searchParams.set('u1', u1); - const data = await FetchJSON(new Request(uri.href)); - const params: Params_v016452 = { cid, sharingKey, u0, u1 }; + const data = await FetchJSON(new Request(uri.href)); + const params: Paramsv016452 = { cid, sharingKey, u0, u1 }; return await getPageLinks_v016452(this, data.items[0], params, chapter); } } @@ -277,21 +277,21 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap /** * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. * @param useScript - use FetchWindowScript and not Fetch for first request - * @param SBVersionOverride - Override SpeedBinb version detection + * @param sbVersionOverride - Override SpeedBinb version detection */ -export function PagesSinglePageAjax(useScript = false, SBVersionOverride: SpeedBinbVersion = undefined) { +export function PagesSinglePageAjax(useScript = false, sbVersionOverride: SpeedBinbVersion = undefined) { 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, useScript, SBVersionOverride); + return FetchPagesSinglePageAjax.call(this, chapter, useScript, sbVersionOverride); } }; }; } -async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configuration_v016452, params: Params_v016452, chapter: Chapter): Promise { +async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configurationv016452, params: Paramsv016452, chapter: Chapter): Promise { configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); try { @@ -313,7 +313,7 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinks_v016201(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey: string, u: string, chapter: Chapter): Promise { +async function getPageLinks_v016201(scraper: MangaScraper, configuration: Configurationv016452, sharingKey: string, u: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); @@ -339,7 +339,7 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configuration_v016452, sharingKey: string, chapter: Chapter): Promise { +async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configurationv016452, sharingKey: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); @@ -389,7 +389,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config return Promise.reject(new Error('Content server type not supported!')); } -async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configuration_v016452, chapter: Chapter) { +async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configurationv016452, chapter: Chapter) { const data = await FetchJSON(new Request(uri.href)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { @@ -427,7 +427,7 @@ async function FetchImage(this: MangaScraper, page: Page, priority: Priority, si } async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { - const data = await FetchJSON(new Request(page.Link.href)); + const data = await FetchJSON(new Request(page.Link.href)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); @@ -544,7 +544,7 @@ function lt_001(t: string, ctbl: string[], ptbl: string[]): DescrambleKP { * i width of descrambled image * n height of descrambled image */ -function getImageDescrambleCoords(/*t*/s: string, u: string, i: number, n: number): PageView_v016130 { +function getImageDescrambleCoords(/*t*/s: string, u: string, i: number, n: number): PageViewv016130 { const r = _lt_002(s, u); // var r = this.lt(t.src); if (!r || !r.vt()) return null; @@ -808,7 +808,6 @@ const _speedbinb_a = function () { * define prototype for h */ const _speedbinb_h = function () { - // eslint-disable-next-line @typescript-eslint/no-empty-function function t() { } return t.prototype.vt = function (): boolean { return !0; From 63a1c94da5231757ad1790408ce6512f1adc19ea Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 7 May 2024 12:17:45 +0200 Subject: [PATCH 56/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 43d8d4800b..fb6b7f931c 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -44,6 +44,8 @@ export { default as BestManhua } from './BestManhua'; export { default as BlogTruyen } from './BlogTruyen'; export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -52,11 +54,13 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -66,12 +70,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -97,6 +105,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -136,6 +145,7 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyAction } from './GalaxyAction'; export { default as GalaxyManga } from './GalaxyManga'; @@ -143,6 +153,7 @@ export { default as GanGanOnline } from './GanGanOnline'; export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GhostScan } from './GhostScan'; export { default as GloryManga } from './GloryManga'; @@ -358,6 +369,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -493,7 +506,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -603,6 +618,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -632,6 +648,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; export { default as TonizuToon } from './TonizuToon'; @@ -696,6 +713,7 @@ export { default as XlecX } from './XlecX'; export { default as XManga } from './XManga'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -704,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -725,16 +745,11 @@ export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -744,7 +759,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -833,9 +847,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; @@ -883,6 +895,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From c6f9d893f6ff5e2da04f768b3825be6ea7a454e0 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 7 May 2024 12:19:25 +0200 Subject: [PATCH 57/88] update e2e tests to use vitest --- web/src/engine/websites/BookHodai_e2e.ts | 5 +++-- web/src/engine/websites/BookLive_e2e.ts | 5 +++-- web/src/engine/websites/Cmoa_e2e.ts | 5 +++-- web/src/engine/websites/ComicBrise_e2e.ts | 5 +++-- web/src/engine/websites/ComicMeteor_e2e.ts | 5 +++-- web/src/engine/websites/ComicPolaris_e2e.ts | 5 +++-- web/src/engine/websites/ComicPorta_e2e.ts | 5 +++-- web/src/engine/websites/ComicValkyrie_e2e.ts | 5 +++-- web/src/engine/websites/DigitalMargaret_e2e.ts | 5 +++-- web/src/engine/websites/Futabanet_e2e.ts | 5 +++-- web/src/engine/websites/Getsuaku_e2e.ts | 5 +++-- web/src/engine/websites/MangaPlanet_e2e.ts | 5 +++-- web/src/engine/websites/MangaPlaza_e2e.ts | 5 +++-- web/src/engine/websites/Ohtabooks_e2e.ts | 5 +++-- web/src/engine/websites/OneTwoThreeHon_e2e.ts | 5 +++-- web/src/engine/websites/SManga_e2e.ts | 5 +++-- web/src/engine/websites/TKSuperheroComics_e2e.ts | 5 +++-- web/src/engine/websites/Yanmaga_e2e.ts | 5 +++-- web/src/engine/websites/YoMonga_e2e.ts | 5 +++-- web/src/engine/websites/YoungJump_e2e.ts | 5 +++-- 20 files changed, 60 insertions(+), 40 deletions(-) diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts index 1396f3c241..b7ee3651e8 100644 --- a/web/src/engine/websites/BookHodai_e2e.ts +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts index 081189421e..4977953c01 100644 --- a/web/src/engine/websites/BookLive_e2e.ts +++ b/web/src/engine/websites/BookLive_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/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts index 2b3f73bd9a..ff39303196 100644 --- a/web/src/engine/websites/Cmoa_e2e.ts +++ b/web/src/engine/websites/Cmoa_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/ComicBrise_e2e.ts b/web/src/engine/websites/ComicBrise_e2e.ts index 9f02fb595e..63a1f1a5bd 100644 --- a/web/src/engine/websites/ComicBrise_e2e.ts +++ b/web/src/engine/websites/ComicBrise_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/ComicMeteor_e2e.ts b/web/src/engine/websites/ComicMeteor_e2e.ts index ada4d566cd..9426d5066c 100644 --- a/web/src/engine/websites/ComicMeteor_e2e.ts +++ b/web/src/engine/websites/ComicMeteor_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/ComicPolaris_e2e.ts b/web/src/engine/websites/ComicPolaris_e2e.ts index 00248baa89..fd52919746 100644 --- a/web/src/engine/websites/ComicPolaris_e2e.ts +++ b/web/src/engine/websites/ComicPolaris_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/ComicPorta_e2e.ts b/web/src/engine/websites/ComicPorta_e2e.ts index fcce05e897..11a81f062f 100644 --- a/web/src/engine/websites/ComicPorta_e2e.ts +++ b/web/src/engine/websites/ComicPorta_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/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts index 1315d4c3f0..8048feba24 100644 --- a/web/src/engine/websites/ComicValkyrie_e2e.ts +++ b/web/src/engine/websites/ComicValkyrie_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/DigitalMargaret_e2e.ts b/web/src/engine/websites/DigitalMargaret_e2e.ts index 2eacbb3352..48965fdff5 100644 --- a/web/src/engine/websites/DigitalMargaret_e2e.ts +++ b/web/src/engine/websites/DigitalMargaret_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/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index 13eed60746..c183a46895 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_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/Getsuaku_e2e.ts b/web/src/engine/websites/Getsuaku_e2e.ts index c3ede35b9b..87a0f94589 100644 --- a/web/src/engine/websites/Getsuaku_e2e.ts +++ b/web/src/engine/websites/Getsuaku_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: { @@ -23,4 +24,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/MangaPlanet_e2e.ts b/web/src/engine/websites/MangaPlanet_e2e.ts index 807b567f6d..6340969891 100644 --- a/web/src/engine/websites/MangaPlanet_e2e.ts +++ b/web/src/engine/websites/MangaPlanet_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/MangaPlaza_e2e.ts b/web/src/engine/websites/MangaPlaza_e2e.ts index 9bbb91b303..fac42609ab 100644 --- a/web/src/engine/websites/MangaPlaza_e2e.ts +++ b/web/src/engine/websites/MangaPlaza_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/Ohtabooks_e2e.ts b/web/src/engine/websites/Ohtabooks_e2e.ts index c5d7bac39a..4536e7944b 100644 --- a/web/src/engine/websites/Ohtabooks_e2e.ts +++ b/web/src/engine/websites/Ohtabooks_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: { @@ -24,4 +25,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/OneTwoThreeHon_e2e.ts b/web/src/engine/websites/OneTwoThreeHon_e2e.ts index 0dac77d6e0..4a70ebc2a0 100644 --- a/web/src/engine/websites/OneTwoThreeHon_e2e.ts +++ b/web/src/engine/websites/OneTwoThreeHon_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/SManga_e2e.ts b/web/src/engine/websites/SManga_e2e.ts index 6eca2d50d3..7721a2007b 100644 --- a/web/src/engine/websites/SManga_e2e.ts +++ b/web/src/engine/websites/SManga_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/TKSuperheroComics_e2e.ts b/web/src/engine/websites/TKSuperheroComics_e2e.ts index 29a65a70bb..7da2deb842 100644 --- a/web/src/engine/websites/TKSuperheroComics_e2e.ts +++ b/web/src/engine/websites/TKSuperheroComics_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/Yanmaga_e2e.ts b/web/src/engine/websites/Yanmaga_e2e.ts index 2740edcf4d..28d98190e4 100644 --- a/web/src/engine/websites/Yanmaga_e2e.ts +++ b/web/src/engine/websites/Yanmaga_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/YoMonga_e2e.ts b/web/src/engine/websites/YoMonga_e2e.ts index e8e13fb0ff..a5ae49d7a1 100644 --- a/web/src/engine/websites/YoMonga_e2e.ts +++ b/web/src/engine/websites/YoMonga_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file diff --git a/web/src/engine/websites/YoungJump_e2e.ts b/web/src/engine/websites/YoungJump_e2e.ts index e538b03eed..9db5d934a9 100644 --- a/web/src/engine/websites/YoungJump_e2e.ts +++ b/web/src/engine/websites/YoungJump_e2e.ts @@ -1,4 +1,5 @@ -import { TestFixture } from '../../../test/WebsitesFixture'; +import { describe } from 'vitest'; +import { TestFixture } from '../../../test/WebsitesFixture'; const config = { plugin: { @@ -23,4 +24,4 @@ const config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, () => fixture.AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file From ad29f55836216334e9b3dbf29d07dea9acded9d1 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 7 May 2024 12:25:55 +0200 Subject: [PATCH 58/88] fix yanmaga icon --- web/src/engine/websites/Yanmaga.webp | Bin 5116 -> 952 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/web/src/engine/websites/Yanmaga.webp b/web/src/engine/websites/Yanmaga.webp index caae45605638fa5883b1cede6fa9afc11c7fa224..a4115f158d9719f231964e3af116b2a205b8286e 100644 GIT binary patch literal 952 zcmV;p14sN)Nk&Gn0{{S5MM6+kP&go@0{{SU5&)e6DnI~006v96p-`nGqavykJrJM} zfCE5~Q7gnh0nv@=bMHS%iv9gc)ZZWiuD zPc!}%yArZ3XD7f@bg!NCCJG`{#3^mnx-$D7t49z|d(@rXsft3cvK?&ccT;%I2_FN4 z4}MnlI~iN@>UB85uj{#8d~PJLkGg&3)pF~=Haq^nk8Mx90#?Ndgl8xiT;)0s%+m$3 z+fW17+lC$3tPp$~k5;Qj*4#Q!RJSNH@*#x_Xpz;M-W4g`2Jx^3`sK-c{yf<{ zA5H$(mBg{fKOa2NbtXu{*B8~b^ms#V8#^&L`LYUcYqRb9Wc9K|;i|DHLh}AY$-TG1 z;Pj<+>A(rTal6QZ^(eQ#|K`IDP|zBl;^L`ne#E)^iZldbw>E8JR<}aZRiFTH)-Je? z502t<{uL7#Lx~A6+uQ`P{6ZefzFj&&Q~4hkS@H>0n;)cqnn?)TZW96M)eEQ^cn|sP zztU+UB5a92Mtep>Yx{ekI>ao4v>mKCi4E+nR5q*C2}o^pR^*aha|H?nu${REO6-%c582fB zJa>C{EKWlmbeF82G4f&PU&Erl=JTvSNc>vG4ap!5R2TY0l#Z-nHNl}T`AA-tn{-2L z6ETGm>8}P$*J{R>owCBMaY_N+z){5|8@4CrI$5NSWm_!~fT57l;%u(uvrmC3#m;c` zTq6^6MZBv4?HgQyeIl49DS98)*PyhfUp3|xT literal 5116 zcmbW52{@G9`^V2SGiL1DpzLGp%gmU;Fk?4}O4hQZGG+#YSsG)FsAxeuB9%x9mC}op zQd+clE0s3Yt9pf2DiPxMOua4t|8@2L|JU!iW}fSF?(@CRxzBy>=bGnCkgvD*M=SuL zULFC90vy6*0RTqu*Y)eim%#||k%yZ=-e*3SFF+^*z~hTWL32ECVc`)t%yobOG5`(8 z05DleLcd_|5Q*B?i-AjmMH2pbeYy)EN$WPjCjf{0Y5#wb3QH&w0{{iUY8y5ui3M{m z%!#RDp~OB6vs!e5gb^qSi{JoZo-N_nZ*28d^Nrmk%;xdgutpNIkj-OD_yWx9Q<6C_ zBj>}sHigSch4~K5Mv2KhF3jUFtMNF@Bmhv7>==nTtT>phVU`z#1TkQC0zg_m_7{%+ zg~gmSI8Fc<0%5v{8yhFanX$}qWE#x@=fg=&v6Q_|s;z7XYPP0Ge<7vK|ddy~K&dLOO|*nwm=Fa#%!3LVsNUr{IV3_wdVn zM9F+Va)jOM96(0yfqS4I z`!-)@5s*B2q51>g>K0(n96p&%$6ih^Px zK9me)LTjJ`XdAQ>s)TBxV^Aw}4!Qz$Ll2;*&=B+S#`t5H7%^rorVMik(~h}?>Bo#q%Sr1?Q>4A6Bc%D# ztEEe%>!i;}-;y4Xo|I9RF_xjr_{*?m(q%TwRLh){xgpapGbyVgYbxt38zLJoyGpiH z_K567*+;S;Ij&reT&dhqxyy1-YizdmY`58*+4-{@X7|jV(8OtaX(niH)ojsx ztcB9D&i?O5^suM zh+mCwz&|#WHFPkHF)T9dFdR10H}W&eG^#gxXe?vwU>s+>!?@FU%*50r)MTAWi^-tr zY*Sy;4AXkkM`j9Uu4c>4s?6?~qs<-66U=v;-?Ttj*jdC`lv~`eL|9TSxt6;vyRD?G zXjXiyDyw@0d4fA3g-}m;O4K0EC$1*85Z{uFND-v1q)yVbwVidMb+vUbS(QAOyqbKH z{GMV#VNuE{cWe}Fylt{=PS}jtTH11K_t@UI!`k`Tt+VT}`$Dy+il|4ZL-t1YQTDs+ z?>VSB1UM8rT&79UJZRapHri)8l`f_?(%(4}91|St90#3Doj6X_PS2h3&P?Y@=ROyl zOO(rAmp)emSEg%~>oYe)H@4dWw*hx^_jvb1?r%M;JwzT&9%BqTBa3m?6X`j}GvD*N zm#Wu7ubo~`yz$<#-u2$YbL{4R-b#my1p#mTHoQh_H(o5UYI98FL>V0 zdC%rs%ooi+>4)%}>$lzS(E{TI`~@xkz~9$@yZ_?=(}3jxrvlM|0fFU#FM`NHnL(Yw z*x+Tsb-|xPJVG{y^e!}8n7puKkX#!%swDA{Ip) zh!|b$wYYe3f23XH+Q_?0OqZlBxw2GiY2wn;%aoQemmQCiiVBUYi<)BkGpm@R(Z12U zqK8=w)(+Mywi~;MJ;ZV5Y~u{XILB;@8H{y~-5xs>=NeZM_nOP#?&OZd`@~nok0tmg z)FjL#h9)-fqUgz)4I|v(l?|JWO!%nUx8Y|TG5edkhv=JX_k9dbmvd zHkEA|+n#Ut+umG+E6OkWSiG$GN{MYr#SYmW$vgT==a-%+Gb-CsHnlTuXHU6DdBZN9 zT^n|d?Pl-3wa0DGkqX_4f{KZ~+`acJ=TtUVnN*eRL+?x3_o8}Hb?1JE{j~?Q4ip^t zQp2z5I~a8ELalvmZJkct=6XbZa{bVu$U`>|dmcVs9{s;14Lt^Bn5>CI`dsX}=N-#Bde4WQzjGn*!u5;uE?&Omed&CsduRJ)=gVzZ=vP{= zI$UkJM!nYDW!Kg8r`?}T*QwW=Z`j{Bag%oQWVciInOm;6&fWIBed&(xoohV{db;l} zynFv%cv1{#QdEweR#(&!=6_f}iz1 zXFY%QchcWe{kbm`UX%>z57Z7)2HS?bhi<-H{IdU*@YUq&wQp43?0ReV_K$aN@4AM= zhWkfEBQx&{KWKia`DpvGV>Dp&$tT{Y$+7%#&GCbu9X@wXgiZ`hrcPm|O23$YIXOLV z`q2z;W(GcC;P~)sz?NBHH)P=k|LD8$h}*oY@s*Vp8obLn3L9A9+6tT|PW!@{1)&)g z)WNZl>cTSqn~!7fv?tGvEuO+`JN)2n;1~NZvmR8?^sSzVoOmMzGmHnz#&1mO_dC6w z8ku2CtvgG4KQlD*YWk@Q>-3uGn=8mGPt#V*G}I`@yRPxwvzs8jn24SoT<@nVJ9SP@ zVE4&<93M(rW0Bbw`NU1nmf?b+??u&2x@$@Ft6PC*xM(%&p$oiJF@=qnoYOPaadFip%xS7$gdkE@QY zD&l>pF;}y!w-0BChRU`$1}1%Kr`h((Lt0@XC$YJrVW(a4z?{*3|5uFzE7htvwIpqe z_Ro=yj$4&o_j?uIZE3nJhu>@=-SKR-5&vEGWN%~C?c(eMuJ7LV6#q4}L11|-*eK`v z{XC>%u(xei^Wf*4nz`Mv%@5Np7p9sv<}5h1K-|%OCCjha^P%bOHW|G*&@k2ZPm1i1ULf*f18YZVK`%r7<+Qy-p)-{+0J~;a! zt+8wm{zVN9zhcQG$3{FyH6~qT7=hR0W~=98>P}4D3Vb2M?XurccP~Guz^tLfP`^$) zKH>68I)B55~?MSJ%N?=b)YJI``T@Q{o4XjHF zE*@{4@W{nD9@3DmTI*mzA}j85OqTmCFvFfda3Me;V}Ug`1KKLm!nMyzPp;9XE!spRy~j^jIEpEyn4z zg;K#t&KtJeuH3!%bOMgmU4{DA9C&mvXt}ViG;iY|L+fnxlsC064j(!NbUO;2 zLc{%Y;o;dt>==5Gr}sZ|!7XR}FDK(v8=^oIOM?F?ppmR8BnpK9D+o#Hd@(bPz)v## zK7uFw2Z@L){Cbd-jL3`@B#WK#aHQXsz!Ux$mY+oYx*Q@)z$2wGg(Nc3TC$|?LO;KM zm-2W&)JbCaK>P3Nq>ywWhZMv~f=}5j4lFm6OeLf#7AAPNx(62E6LAWk3_B*h7Y zI0}VG!I}9nSzNxvV*b^|&yViQPZBfX)3dLqGaep<$mO!>-d^4`ikG#AwYwLCO!o40 zXE@k-+uA#LQ9Ni22Y2dsUrzxmnaAOazx%R(`Z9j&E2##a5T4nSBjToT*xn)m5BGJ| zbnfqCq5XEee|*`$kH!7Bz9cvpl4Ngx+3W8nxPT=1qjKTKkJ{((;er>zl@0y_a2O^8 From 387932af59f53b7833f3740ef68dc056de666b24 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 18 May 2024 13:19:19 +0200 Subject: [PATCH 59/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 0aeb6002e2..5dfdec702c 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -47,6 +47,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -55,11 +57,13 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -69,12 +73,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -103,6 +111,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -144,12 +153,14 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyManga } from './GalaxyManga'; export { default as GanGanOnline } from './GanGanOnline'; export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GhostScan } from './GhostScan'; export { default as GloryManga } from './GloryManga'; @@ -371,6 +382,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -510,7 +523,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -622,6 +637,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -652,6 +668,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -720,6 +737,7 @@ export { default as XManga } from './XManga'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -728,6 +746,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -750,16 +770,11 @@ export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; export { default as CocoManHua } from './legacy/CocoManHua'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -767,7 +782,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -856,9 +870,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; @@ -905,6 +917,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 583dec7f35a9d3f6aaaf7b2b09a473c2a67d0a08 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 23 May 2024 14:27:21 +0200 Subject: [PATCH 60/88] Update _index.ts --- web/src/engine/websites/_index.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 5348b0e9cb..46628948d6 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -47,6 +47,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -55,12 +57,14 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -70,12 +74,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -104,6 +112,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -146,12 +155,14 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyManga } from './GalaxyManga'; export { default as GanGanOnline } from './GanGanOnline'; export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostFansub } from './GhostFansub'; export { default as GhostScan } from './GhostScan'; export { default as GloryManga } from './GloryManga'; @@ -313,6 +324,7 @@ export { default as MangaCross } from './MangaCross'; export { default as MangaDemon } from './MangaDemon'; export { default as MangaDenizi } from './MangaDenizi'; export { default as MangaDex } from './MangaDex'; +export { default as MangaDig } from './MangaDig'; export { default as MangaDistrict } from './MangaDistrict'; export { default as MangaDiyari } from './MangaDiyari'; export { default as Mangadon } from './Mangadon'; @@ -374,6 +386,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRead } from './MangaRead'; @@ -513,7 +527,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -625,6 +641,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -655,6 +672,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -722,6 +740,7 @@ export { default as XManga } from './XManga'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -730,6 +749,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -752,15 +773,10 @@ export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as Baozimh } from './legacy/Baozimh'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -768,7 +784,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as GManga } from './legacy/GManga'; export { default as Guoman8 } from './legacy/Guoman8'; @@ -857,9 +872,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; @@ -906,6 +919,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 8bba2793fbb5ad721905e7fd04995a066c41f75e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 23 May 2024 14:38:50 +0200 Subject: [PATCH 61/88] Futabanet: accept futabanex & filter app chapters --- web/src/engine/websites/Futabanet.ts | 13 +++++++------ web/src/engine/websites/Futabanet_e2e.ts | 5 +++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 151c35702c..cd908bb771 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -@Common.MangaCSS(/^{origin}\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') +@Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') @SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() @@ -21,11 +21,12 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const request = new Request(`${this.URI.origin}${manga.Identifier}/episodes`); const data = await FetchCSS(request, 'div.episode__grid a'); - return data.map(chapter => { - const epnum = chapter.querySelector('.episode__num').textContent.trim(); - const title = chapter.querySelector('.episode__title').textContent.trim(); - return new Chapter(this, manga, chapter.pathname, title ? [epnum, title].join(' - ') : epnum); - }); + return data.filter(chapter => !chapter.pathname.endsWith('/app')) + .map(chapter => { + const epnum = chapter.querySelector('.episode__num').textContent.trim(); + const title = chapter.querySelector('.episode__title').textContent.trim(); + return new Chapter(this, manga, chapter.pathname, title ? [epnum, title].join(' - ') : epnum); + }); } diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index c183a46895..c57d67c44c 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -13,11 +13,12 @@ const config: Config = { }, child: { id: '/list/work/62591706776561c83f010000/episodes/1', - title: '第1話(1)' + title: '第1話', + timeout: 10000 }, entry: { index: 0, - size: 1_869_624, + size: 1_872_190, type: 'image/png' } }; From 881df6897be33fb969fe9494a7209f1add7ba4d9 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 23 May 2024 17:39:21 +0200 Subject: [PATCH 62/88] rename FetchImage into FetchImageAjax --- web/src/engine/websites/decorators/SpeedBinb.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 8fa901312b..3d330c9e59 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -413,7 +413,7 @@ async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configur * @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 { +export async function FetchImageAjax(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { switch (true) { case page.Link.href.endsWith('ptimg.json'): return await descramble_v016061(this, page, priority, signal, detectMimeType); @@ -469,7 +469,7 @@ export function ImageAjax(detectMimeType = false) { return class extends ctor { public async FetchImage(this: MangaScraper, page: Page, priority: Priority, signal: AbortSignal): Promise { - return FetchImage.call(this, page, priority, signal, detectMimeType); + return FetchImageAjax.call(this, page, priority, signal, detectMimeType); } }; }; From 6fa366c153b988b4f96a12fe64c336b36b76762d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 23 May 2024 17:41:59 +0200 Subject: [PATCH 63/88] Futabanet : handle non-SpeedBinb chapters --- web/src/engine/websites/Futabanet.ts | 14 ++++++++++--- web/src/engine/websites/Futabanet_e2e.ts | 26 +++++++++++++++++++++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index cd908bb771..fd8afac200 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -1,14 +1,14 @@ import { Tags } from '../Tags'; import icon from './Futabanet.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, Page, type Manga } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import type { Priority } from '../taskpool/DeferredTask'; @Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') -@SpeedBinb.PagesSinglePageAjax() -@SpeedBinb.ImageAjax() + export default class extends DecoratableMangaScraper { public constructor() { @@ -27,7 +27,15 @@ export default class extends DecoratableMangaScraper { const title = chapter.querySelector('.episode__title').textContent.trim(); return new Chapter(this, manga, chapter.pathname, title ? [epnum, title].join(' - ') : epnum); }); + } + public override async FetchPages(chapter: Chapter): Promise { + let pages: Page[] = await Common.FetchPagesSinglePageCSS.call(this, chapter, 'div.works_tateyomi__img img'); + pages = pages?.map(page => new Page(this, chapter, page.Link, { useCommon: true })); + return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjax.call(this, chapter); } + public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { + return page.Parameters?.useCommon ? Common.FetchImageAjax.call(this, page, priority, signal) : SpeedBinb.FetchImageAjax.call(this, page, priority, signal); + } } \ No newline at end of file diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index c57d67c44c..68d6471292 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -24,4 +24,28 @@ const config: Config = { }; const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); + +const NoSpeedBinbConfig: Config = { + plugin: { + id: 'futabanet', + title: 'がうがうモンスター (Futabanet Monster)' + }, + container: { + url: 'https://gaugau.futabanet.jp/list/work/oCMElLZtSKn7e5PVKDuV2josm', + id: '/list/work/oCMElLZtSKn7e5PVKDuV2josm', + title: 'ルーン魔術だけが取り柄の不憫令嬢、天才王子に溺愛される ~婚約者、仕事、成果もすべて姉に横取りされた地味な妹ですが、ある日突然立場が逆転しちゃいました~' + }, + child: { + id: '/list/work/oCMElLZtSKn7e5PVKDuV2josm/episodes/7', + title: '第3話(3)', + }, + entry: { + index: 0, + size: 204_914, + type: 'image/jpeg' + } +}; + +const NoSpeedBinbfixture = new TestFixture(NoSpeedBinbConfig); +describe(NoSpeedBinbfixture.Name, async () => (await NoSpeedBinbfixture.Connect()).AssertWebsite()); \ No newline at end of file From de34371ac81d0d32a3caac8948a8fcbafa2db305 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 10 Jun 2024 16:20:34 +0200 Subject: [PATCH 64/88] dont use href on new Request --- .../engine/websites/decorators/SpeedBinb.ts | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 3d330c9e59..2d5bd2f429 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -194,7 +194,7 @@ type PageScriptResult = { */ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, useScript = false, sbVersionOverride: SpeedBinbVersion = undefined): Promise { let viewerUrl = new URL(chapter.Identifier, this.URI); - const request = new Request(viewerUrl.href, { + const request = new Request(viewerUrl, { headers: { Referer: this.URI.origin } @@ -248,7 +248,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap case SpeedBinbVersion.v016113: //BookHodai, Futabanet, Getsuaku (v016700), MangaPlaza, Ohtabooks case SpeedBinbVersion.v016130: { // Booklive, MangaPlanet, S-Manga, Yanmaga //Doing it like that because of cookies needed for Mangaplanet using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); } //YoungJump @@ -256,7 +256,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u1', u); //Doing it like that because of cookies needed for YoungJump using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl.href), JsonFetchScript.replace('{URI}', uri.href), 2000); + const data = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', uri.href), 2000); return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); } //Cmoa @@ -265,7 +265,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap const u1 = viewerUrl.searchParams.get('u1'); uri.searchParams.set('u0', u0); uri.searchParams.set('u1', u1); - const data = await FetchJSON(new Request(uri.href)); + const data = await FetchJSON(new Request(uri)); const params: Paramsv016452 = { cid, sharingKey, u0, u1 }; return await getPageLinks_v016452(this, data.items[0], params, chapter); } @@ -327,7 +327,7 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config const uri = getSanitizedURL(configuration.ContentsServer, 'content'); uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('u1', u); - const data: SBCDATA = await FetchJSON(new Request(uri.href)); + const data: SBCDATA = await FetchJSON(new Request(uri)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); @@ -361,7 +361,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config case 1: {//Futabanet, Getsuaku, BookHodai const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - const response = await Fetch(new Request(uri.href)); + const response = await Fetch(new Request(uri)); const data = await response.text(); const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); @@ -376,7 +376,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config case 2: {//MangaPlanet, MangaPlaza const uri = getSanitizedURL(configuration.ContentsServer, 'content'); uri.searchParams.set('dmytime', configuration.ContentDate); - const data = await FetchJSON(new Request(uri.href, { headers: { Referer: scraper.URI.href } })); + const data = await FetchJSON(new Request(uri, { headers: { Referer: scraper.URI.href } })); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); @@ -390,7 +390,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config } async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configurationv016452, chapter: Chapter) { - const data = await FetchJSON(new Request(uri.href)); + const data = await FetchJSON(new Request(uri)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); @@ -427,7 +427,7 @@ export async function FetchImageAjax(this: MangaScraper, page: Page, priority: P } async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { - const data = await FetchJSON(new Request(page.Link.href)); + const data = await FetchJSON(new Request(page.Link)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); From 7e3254398bb72fd19ab8671b63837a3b830c737b Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 10 Jun 2024 16:27:26 +0200 Subject: [PATCH 65/88] fix bookhodai manga list and "chapters" --- web/src/engine/websites/BookHodai.ts | 20 ++++++++++---------- web/src/engine/websites/BookHodai_e2e.ts | 10 ++++++---- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index 8f63828283..e8db6dca16 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -3,7 +3,7 @@ import icon from './BookHodai.webp'; import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS } from '../platform/FetchProvider'; +import { FetchHTML } from '../platform/FetchProvider'; function MangaLabelExtractor(element: HTMLElement): string { return element.textContent.split('>').pop().trim() || element.textContent.trim(); } @@ -25,7 +25,7 @@ export default class extends DecoratableMangaScraper { const paths = ['magazine', 'magazine_pop', 'manga', 'manga_pop']; const mangaList: Manga[] = []; for (const path of paths) { - const mangas = await Common.FetchMangasMultiPageCSS.call(this, provider, `/search/${path}?page={page}`, 'p.book-detail-pc__title a'); + const mangas = await Common.FetchMangasMultiPageCSS.call(this, provider, `/search/${path}?page={page}`, '.p-bookdetail-contents__title a'); mangaList.push(...mangas); } return mangaList.distinct(); @@ -33,18 +33,18 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const chapters: Chapter[] = []; - const [data] = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div.content'); + const dom = await FetchHTML(new Request(new URL(manga.Identifier, this.URI))); - //get current "chapter" (book) title - let title = data.querySelector('h2').textContent.trim(); + //get first "chapter" (book) details + const bookdetails = dom.querySelector('section.p-book-overview'); + let title = bookdetails.querySelector('.p-book-overview__detail-volnumber').textContent.trim(); title = title.replace(manga.Title, '').trim() != '' ? title.replace(manga.Title, '').trim() : title; + const chapterlinkNode = bookdetails.querySelector('a[href*="viewer"'); + chapters.push(new Chapter(this, manga, chapterlinkNode.pathname + chapterlinkNode.search, title)); - const chaptersNodes = [...data.querySelectorAll('.bookdetail_box div.pc a[href*="viewer"], div.matome-text-box')]; - const firstChapter = chaptersNodes.shift() as HTMLAnchorElement; - chapters.push(new Chapter(this, manga, firstChapter.pathname + firstChapter.search, title)); - + const chaptersNodes = [...dom.querySelectorAll('div.p-book-backnumber-series__item')]; for (const chapter of chaptersNodes) { - const title = chapter.querySelector('.matome_book_nm').textContent.trim(); + const title = chapter.querySelector('.p-book-backnumber-series__volnumber').textContent.trim(); const link = chapter.querySelector('a[href*="viewer"]'); chapters.push(new Chapter(this, manga, link.pathname + link.search, title.replace(manga.Title, ''))); } diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts index b7ee3651e8..bd1886e92c 100644 --- a/web/src/engine/websites/BookHodai_e2e.ts +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -9,16 +9,18 @@ const config = { container: { url: 'https://bookhodai.jp/manga/backnumber/49775', id: '/manga/backnumber/49775', - title: '色欲の春~秘めた色香は筆先に宿る~' + title: '色欲の春~秘めた色香は筆先に宿る~', + timeout: 15000 + }, child: { id: '/viewer?book_id=3000071024&branch_no=01&book_type=4', - title: '(1)', - timeout: 15000 + title: '1 ~ 24', + timeout: 20000 }, entry: { index: 0, - size: 2_198_026, + size: 2_198_237, type: 'image/png' } }; From b3e0ef2cddf2132282a69656089acdbd24fa7b90 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 10 Jun 2024 16:36:03 +0200 Subject: [PATCH 66/88] Add MichiKusa https://github.com/manga-download/hakuneko/issues/7176 --- web/src/engine/websites/MichiKusa.ts | 34 +++++++++++++++++++++++ web/src/engine/websites/MichiKusa.webp | Bin 0 -> 1682 bytes web/src/engine/websites/MichiKusa_e2e.ts | 26 +++++++++++++++++ web/src/engine/websites/_index.ts | 1 + 4 files changed, 61 insertions(+) create mode 100644 web/src/engine/websites/MichiKusa.ts create mode 100644 web/src/engine/websites/MichiKusa.webp create mode 100644 web/src/engine/websites/MichiKusa_e2e.ts diff --git a/web/src/engine/websites/MichiKusa.ts b/web/src/engine/websites/MichiKusa.ts new file mode 100644 index 0000000000..cc95661441 --- /dev/null +++ b/web/src/engine/websites/MichiKusa.ts @@ -0,0 +1,34 @@ +import { Tags } from '../Tags'; +import icon from './MichiKusa.webp'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import * as Common from './decorators/Common'; +import * as SpeedBinb from './decorators/SpeedBinb'; + +function MangaInfoExtractor(element: HTMLElement) { + return { + id: element.querySelector('a').pathname, + title: element.querySelector('div.contents-info div.title').text.trim(), + }; +} +function ChapterExtractor(anchor: HTMLAnchorElement) { + return { + id: anchor.pathname.replace(/index\.html$/, ''), + title: anchor.text.trim() + }; +} + +@Common.MangaCSS(/^{origin}\/product\/[^/]+$/, 'header.entry-header h1.page-title') +@Common.MangasMultiPageCSS('/product/page/{page}', 'div.entry-content', 1, 1, 0, MangaInfoExtractor) +@Common.ChaptersSinglePageCSS('div.released_episodes div.items div.item a', ChapterExtractor) +@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.ImageAjax() +export default class extends DecoratableMangaScraper { + + public constructor() { + super('michikusa', `MichiKusa`, 'https://michikusacomics.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/MichiKusa.webp b/web/src/engine/websites/MichiKusa.webp new file mode 100644 index 0000000000000000000000000000000000000000..df2e13f1b7f6e57896831dc36b2d0fe55f39e6a9 GIT binary patch literal 1682 zcmV;D25tFLNk&GB1^@t8MM6+kP&il$0000G0000#002J#06|PpNVfq100EF&ZJX;v z-<`oj3$6#(0(9aDAyx_aOC8F{J*hH$Y}W6}&;OmHxpMQdc|*oAKwt>~M`9<9pxOY2kqEH1ONrIQ-zluz26`j6=}c z#`{J1Y|vrbRTjPB99Fjn8|5&1&JdV@A@F<@ZUCDpvt>*|Yq2~7*Vm>m*kUracro3l zWEd+)OIgZe$a-rYEp5qripMV7Ow2ZS;d}Tie`%><{JYZSW*EPYnqIEQkrmtaqbbTh ze4%arou+{CeI73AK~#+#z{6qTdsK~lUx4!{MO8_uBU29yDg-`E0c*uJRnr=98tc01 zDJCimIs{fGmg?F{eQ7MX|YHAq&d+ICtA^L^%_pSc9(LcBP z_lEwxC4X;zf%mrlyP^MX>A#!u@3uZ}kjE|hxJe$j$>T`e-Gzcj-5er1kogs^x6hQ3leh1j1Xi*2`in_oKTP`{hjz!~l`iU&?rpTt z63)SqYox%~OpOd#DZ0O}lTl}Jx>Y8COtM=qBI_tZy3s`7Fg}~`|hkM@#eT`R^`UCR({gw^{%109(| zF}?{YiDm_%3p^lG7=NyNlZMp#QJ>7!39U?<-!)i9wn?A#yaa|T&1)MQ)hiab8LH7{ z>bgK#13%VDUpe6Ub?cMJ2jh8d1LPIGT@^@j?3l9jL^T(whx!@y<1+o;N8U3ynz?+K zu(5R7heJ)e!ihd9=NPy|{R>I-vmQt7%wJ*wpM3gHl}bSAzCUgiA54L9c@3#H`dOb{mJ z8`O%(zXQ2TAPt=4jH@cNg;%cX>2aM<{5vNtzj)XSP;$9FVU4>GP>ryrWLzE#`Nq7i z6jU}18IpS)<#Tg+4@B`8?;n>Pvp!oU^DdvjEvDf10@xU^Ahf(+(4ghQ{qgr6vxkbn zu2v6#a_(6%!fGgk)k?n4x->U;pKX6D`vl_Gz@3H?yqCE$V_+lhU_M80{( z-?B2E)el^WBR1-nuz0okQyWbo;>5RCc@nOWruGaqHcT9=*-9o{r9zqPQ3CM&;#Z(2@iolXG+;} zH1>^%Ggak51Vh;tXIAK@Kj`gv)Dy9SJ|T)U=Ldh9ij}|LZ)H79bakYh(vZ)kgTuLt zzkrX$M_)`Y{wVBx3%usOcm>J(zjw+SySJlK6Qji$xoaI)bjN7$XhLl zrKlGz&_F?@3`+homr%8MK=3d{9TH!_9+em{WNRdP#M-nEr*)2DeCRX=>iZmW~ zbV`m?aPQXFP8KIfESXVtdZv08X_K9pHikES6dgIM8uGMJlH4%~UYZBs#U+#8F$e|y zwf~#FiF4mo#U};A1v_N0W);_R$j-9*&Q}_}=9z cljLdrmL-|&J-@6t*46z_^ (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 3016e70441..a1501b4606 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -488,6 +488,7 @@ export { default as Mexat } from './Mexat'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as MilfToon } from './MilfToon'; export { default as MindaFanSub } from './MindaFanSub'; From 5b5cf2d41b6efd56bafac0f541a74ae85fb866ab Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 11 Jul 2024 15:44:10 +0200 Subject: [PATCH 67/88] Update _index.ts --- web/src/engine/websites/_index.ts | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index bd9f0e29c5..d9bef9b162 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -47,6 +47,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -56,12 +58,14 @@ export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -71,12 +75,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -106,6 +114,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -148,6 +157,7 @@ export { default as FRScan } from './FRScan'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyManga } from './GalaxyManga'; export { default as GanGanOnline } from './GanGanOnline'; @@ -155,6 +165,7 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GenzToon } from './GenzToon'; +export { default as Getsuaku } from './Getsuaku'; export { default as GhostScan } from './GhostScan'; export { default as GloryManga } from './GloryManga'; export { default as GManga } from './GManga'; @@ -384,6 +395,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRaw1001 } from './MangaRaw1001'; @@ -484,6 +497,7 @@ export { default as Mexat } from './Mexat'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as MilfToon } from './MilfToon'; export { default as MindaFanSub } from './MindaFanSub'; @@ -526,7 +540,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -643,6 +659,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SMangaVF } from './SMangaVF'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; @@ -672,6 +689,7 @@ export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as ThreeHentai } from './ThreeHentai'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -741,6 +759,7 @@ export { default as XManga } from './XManga'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -749,6 +768,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -771,15 +792,10 @@ export { default as AnimExtremist } from './legacy/AnimExtremist'; export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -export { default as BookLive } from './legacy/BookLive'; 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'; export { default as CopyToon } from './legacy/CopyToon'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; @@ -787,7 +803,6 @@ export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; export { default as Funbe } from './legacy/Funbe'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -870,9 +885,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as RoseliaScanlations } from './legacy/RoseliaScanlations'; @@ -918,6 +931,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From fcc09953152c75389c4393ce6225a24c2935f8d0 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Jul 2024 18:37:39 +0200 Subject: [PATCH 68/88] starting to introduce versioned decorators To hell with SB version detection. --- web/src/engine/websites/ComicBrise.ts | 2 +- web/src/engine/websites/ComicMeteor.ts | 2 +- web/src/engine/websites/ComicPolaris.ts | 2 +- web/src/engine/websites/ComicValkyrie.ts | 2 +- web/src/engine/websites/DigitalMargaret.ts | 2 +- web/src/engine/websites/OneTwoThreeHon.ts | 2 +- web/src/engine/websites/TKSuperheroComics.ts | 2 +- .../engine/websites/decorators/SpeedBinb.ts | 53 +++++++++++++++++-- 8 files changed, 56 insertions(+), 11 deletions(-) diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index 2e7ce42708..a13fdb8c1a 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -7,7 +7,7 @@ import { FetchCSS } from '../platform/FetchProvider'; @Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index e85c04eb04..cf53b47e3d 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -14,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 30cee190c5..352997f63f 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -14,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 7cd6408066..3ff7e8cabd 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -20,7 +20,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 81c0a00151..30d1ac0ea2 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -20,7 +20,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index 0cd2ef5622..8bec94d36b 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -13,7 +13,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/TKSuperheroComics.ts b/web/src/engine/websites/TKSuperheroComics.ts index a32950eeda..7f6123ac28 100644 --- a/web/src/engine/websites/TKSuperheroComics.ts +++ b/web/src/engine/websites/TKSuperheroComics.ts @@ -13,7 +13,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/{origin}\/rensai\/[^/]+\/$/, 'div.manga-overview-top-wrapper h2.manga-heading') @Common.MangasSinglePageCSS('/rensai', 'li.rensai-episode-list a', MangaExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 2d5bd2f429..d772b82489 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -169,10 +169,6 @@ function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion return SpeedBinbVersion.vUnknown; } -/********************************************** - ******** Page List Extraction Methods ******** - **********************************************/ - const pageScript = ` new Promise(resolve => { resolve ( { location : window.location.href, pages : document.querySelector("div#content.pages")}); @@ -183,6 +179,55 @@ type PageScriptResult = { location: string, pages: HTMLElement } +/********************************************** + ******** Page List Extraction Methods ******** + **********************************************/ + +/** + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. + * @param useScript - use FetchWindowScript and not Fetch for first request + * @param sbVersionOverride - Override SpeedBinb version detection + */ +export function PagesSinglePageAjaxV016061() { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); + + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageAjaxV016061.call(this, chapter); + } + }; + }; +} + +/** + * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. + * Supposed to be used when chapter JSON got div[data-ptimg$="ptimg.json"] and each one is a json to a page. + * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. + * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method + * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages + * @param useScript - use FetchWindowScript and not Fetch for first request + * @param sbVersionOverride - Override SpeedBinb version detection + */ +export async function FetchPagesSinglePageAjaxV016061(this: MangaScraper, chapter: Chapter): Promise { + let viewerUrl = new URL(chapter.Identifier, this.URI); + const request = new Request(viewerUrl, { + headers: { + Referer: this.URI.origin + } + }); + + const response = await Fetch(request); + const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); + const SBpagesElement = dom.querySelector('div#content.pages'); + //handle redirection. Sometimes chapter is redirected + if (response.redirected) { + viewerUrl = new URL(response.url); + } + + const [...imageConfigurations] = SBpagesElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); +} /** * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. From 7683ae12b510e70505b3fa75d4d1ab882363536a Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 27 Jul 2024 19:32:10 +0200 Subject: [PATCH 69/88] Remove Getsuaku redirect to comic action --- web/src/engine/websites/Getsuaku.ts | 43 ------------------------ web/src/engine/websites/Getsuaku.webp | Bin 2418 -> 0 bytes web/src/engine/websites/Getsuaku_e2e.ts | 27 --------------- web/src/engine/websites/_index.ts | 1 - 4 files changed, 71 deletions(-) delete mode 100644 web/src/engine/websites/Getsuaku.ts delete mode 100644 web/src/engine/websites/Getsuaku.webp delete mode 100644 web/src/engine/websites/Getsuaku_e2e.ts diff --git a/web/src/engine/websites/Getsuaku.ts b/web/src/engine/websites/Getsuaku.ts deleted file mode 100644 index 9e3d6f2218..0000000000 --- a/web/src/engine/websites/Getsuaku.ts +++ /dev/null @@ -1,43 +0,0 @@ -import { Tags } from '../Tags'; -import icon from './Getsuaku.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; -import * as Common from './decorators/Common'; -import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; - -type APIChapters = { - objects: { - id: number, - book_id: number, - title: string, - episode_number: string, - cid : string - }[] -} - -function MangaExtractor(element: HTMLElement) { - return { - id: element.querySelector('div.button a.button__link-dark').pathname, - title: element.querySelector('div.comics__name').textContent.trim() - }; -} - -@Common.MangaCSS(/^{origin}\/episode\/[^/]+$/, 'div.detail__main h2.detail__title') -@Common.MangasSinglePageCSS('/series', 'div.comics__grid div.comics__gridItem', MangaExtractor) -@SpeedBinb.PagesSinglePageAjax() -@SpeedBinb.ImageAjax() -export default class extends DecoratableMangaScraper { - public constructor() { - super('getsuaku', `Getsuaku`, 'https://getsuaku.com', Tags.Language.Japanese, Tags.Media.Manga, Tags.Source.Official); - } - - public override get Icon() { - return icon; - } - - public override async FetchChapters(manga: Manga): Promise { - const bookid = await FetchWindowScript(new Request(new URL(manga.Identifier, this.URI)), 'book_id', 1500); - const chapters = await FetchJSON(new Request(new URL(`/api/sort_episodes?book_id=${bookid}&order=asc&mode=all`, this.URI))); - return chapters.objects.map(chapter => new Chapter(this, manga, `/episode/${chapter.cid}`, chapter.episode_number.trim())); - } -} \ No newline at end of file diff --git a/web/src/engine/websites/Getsuaku.webp b/web/src/engine/websites/Getsuaku.webp deleted file mode 100644 index 977f97921ce684e9a27bc59ec5110e0f03ba650b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 2418 zcmaJ>dpy(YAD_yh94W~qx0!2VwlSA6D{Q&6+%G3Fvwdxo?Yp*Vi#p5E&8aBzqodJ5 z7nS_zB1Nc3Dff;=%Mm|XMTLkBzj2Pv?~nRDujhHap6Bzt-=EL>^L^g0Z;%gx5Wf-v z3CDW`gatT9tb#xwD-?^gI292n;s*%iqX9&uWE}&Efw(grG6`m;CcoS8@-`n(PoqOR z=zRYhqEXzi(~YO-Tf+9F^j@VQ%Zc7eS4m!b#+MADQQ`b%4Y)tG_EYVr8pJgjZta(6 z?P;4XJI|YsNk+{7d{y83Tu&(fpx;A`OCAK@l4kno#$?>p8v3kZTMKu?3zg|-!$C$F zsp2v+;_#@t$(pA34{$eGNzbeON)7r$9=j2&rQVf8Hg``}j>C79^~X#E&+yWRQ-Uwe zxt-T<<8HgBmp<*^OgWF0J0*KA%b&`!_bQcROb!!5cH@q<5B|8|4A58Vga0Pgm2+o@LNHs!0<0 zsEKR)&nbi5H$<`H<$u}WIdWwj5&GnC%Ld&0YQZtRBZ$CN6`O_D>b(i;lhi~;`2{s{3sG8RF73j~&vPar zTdspejXmdQTBp?O>t^hQTes`BK2?#eUn{*{yrShjWjX0`LBemiOqq*Z9Uw)6ad)HiKcrSP{WT~nMmE^)L|F{S3qSW>D`OHgT(ui2qAPk$x(`6Q z`^5OlQL<&VQ&C5&BL=x_#a^!kM(H z>BOwvx;p4G0au`U2}6&>*obo+ero9(*?!m^R@r#sO}EsbdO06wXmdRzOF6iP?8lrN z>tR2!)EzOB&bbYcE39`b{lcVG@HBAJ__;-%wQyEjR$uEM!=4EQ2e1;Q5_4mFN3s9tmKxXA2IRTHvnAXSjY+>!j2XEhTv_QW4$)4V70gGgqNiAIdMPv_kGF-$zJ z)-R5ldemTO+TVn!^KNZ2_Upcg#Sgi_uN4<2F*M~yswqd?!t@Q&g|`QHTZ$(LQ9OO< zaj4a=D$5=hm&{weR9ml+S6Z;~m>RK)xi@3~$Eq2Ncp-je$-N)U-}yLhYyYjgxjT%e zldf7*n4Vd5u90=qEUPi=r!HSjXJxQpnn&yMqY+kqe1I#vM>2iD+%ZNqj)p#57dn+u zxAFLp#pzj(Lq$Z(H@Ay^uJVY9NTIo=o~nz?h{}*Y#E9mbinnzhP%gKrhhI7DV67@y zr{vL{NHNcQkd?bp1{m&A7iJ}-XkL;^GIIMgC-cwHCS@3{6V;EG#c|B~yZ(%4*HRu2 zf@t3h;EiOJ;M{RZg0|8zprNj=sugh3>$%ZmNN^4|d|-Vj%ininTpSv=^AD0_WW$6^ z6gu5?Ym=$YnZ$={YTw-r48ZSV21Mt$-)YMZH3}x|?nda)#*ev6Db_`!Wv4$)+NTQr ztX;?0Duef(T8m4kNj>&JOgKGi!|rq?vyLmpNg`-Qr9R$FKY3pz&hI>}PVw(lj0j=? zRBJf|;)WBj$&_6H4;l;57%VL8!`)gKltIP9!qG$ok?jf48Qw`8AUJ7z2qkG3#f1vP zxkKFq7y*;b1bAeqfSJJJVgy(inF_`N7{z`eYzKobLU_Bduq_K0(1n7YAP0cDz!A0- z1Of?la)DD2D1<{SiVDQpKv4*ky&VFjn6^k12I+u7IY9p&FhxZUH4YQxMfkg(;)I3K zc|118&W_LL!}<1bkVCUWy12M3wZUY6P0QlK7h8f;K&G95%(g?q5escC0g1%_4`njHqPe^v;2*u;Ow0}0 z%LeR%04|uwp#TcF=|U+s#*+h(c_1eQ1QV9NWB?uHfm}MshN2wcXs8vDOkuDVA{!Se zL?XtA#pRJ%6u`#|3sWS4GZ<71($mug<$?Aj;J4tBNW7Pamy;s_>1@9Rjl?@RIwP03 zULYlr39xueTKOa9W8%x sso&DF$aO}1musgGW4G|O|MS*MA%%e!wqM<=IDGX#z*3l=qi{Fmzo{P|VgLXD diff --git a/web/src/engine/websites/Getsuaku_e2e.ts b/web/src/engine/websites/Getsuaku_e2e.ts deleted file mode 100644 index 87a0f94589..0000000000 --- a/web/src/engine/websites/Getsuaku_e2e.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { describe } from 'vitest'; -import { TestFixture, type Config } from '../../../test/WebsitesFixture'; - -const config: Config = { - plugin: { - id: 'getsuaku', - title: 'Getsuaku' - }, - container: { - url: 'https://getsuaku.com/episode/001_gaw_maidragon', - id: '/episode/001_gaw_maidragon', - title: '小林さんちのメイドラゴン', - timeout: 15000 - }, - child: { - id: '/episode/001_gaw_maidragon', - title: '第1話' - }, - entry: { - index: 0, - size: 1_441_630, - 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 d9bef9b162..3610ccd207 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -165,7 +165,6 @@ export { default as Ganma } from './Ganma'; export { default as GateManga } from './GateManga'; export { default as GDScans } from './GDScans'; export { default as GenzToon } from './GenzToon'; -export { default as Getsuaku } from './Getsuaku'; export { default as GhostScan } from './GhostScan'; export { default as GloryManga } from './GloryManga'; export { default as GManga } from './GManga'; From 5ff8bdf2a8c86dc102a909441fb23458355a324e Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 28 Jul 2024 15:57:32 +0200 Subject: [PATCH 70/88] massive rework (again) --- web/src/engine/websites/BookHodai.ts | 2 +- web/src/engine/websites/BookLive.ts | 11 +- web/src/engine/websites/Cmoa.ts | 2 +- web/src/engine/websites/ComicPorta.ts | 2 +- web/src/engine/websites/Futabanet.ts | 2 +- web/src/engine/websites/MangaPlanet.ts | 8 +- web/src/engine/websites/MangaPlaza.ts | 27 +- web/src/engine/websites/MichiKusa.ts | 4 +- web/src/engine/websites/Ohtabooks.ts | 2 +- web/src/engine/websites/SManga.ts | 6 +- web/src/engine/websites/Yanmaga.ts | 10 +- web/src/engine/websites/YoMonga.ts | 3 +- web/src/engine/websites/YoungJump.ts | 8 +- .../engine/websites/decorators/SpeedBinb.ts | 369 ++++++++---------- 14 files changed, 229 insertions(+), 227 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index e8db6dca16..bff30fa00c 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -9,7 +9,7 @@ function MangaLabelExtractor(element: HTMLElement): string { } @Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'section.breadcrumb div.bread-text', MangaLabelExtractor) -@SpeedBinb.PagesSinglePageAjax(true) +@SpeedBinb.PagesSinglePageAjaxv016130() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index e84bbcdeea..fa90f91f96 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -3,17 +3,16 @@ import icon from './BookLive.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -function ChapterExtractor(element: HTMLElement) { - const linkElement = element.querySelector('a.bl-bviewer'); - const id = '/bviewer/s/?cid=' + linkElement.dataset.title + '_' + linkElement.dataset.vol; - const title = element.querySelector('a.cart_action').dataset.vol.trim(); +function ChapterExtractor(anchor: HTMLAnchorElement) { + const id = '/bviewer/s/?cid=' + anchor.dataset.title + '_' + anchor.dataset.vol; + const title = anchor.closest('.series_list_detail').querySelector('a[class*=sl-title]').text.trim(); return { id, title }; } @Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'li.contents span.book_title') @Common.MangasNotSupported() -@Common.ChaptersSinglePageCSS('div#slide_up_top li.item div.buttons', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() +@Common.ChaptersSinglePageCSS('div#slide_up_top li.item div.buttons a.bl-bviewer[data-title][data-vol]', ChapterExtractor) +@SpeedBinb.PagesSinglePageAjaxv016130() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 49c9b83b9b..24e48a7d2f 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -6,7 +6,7 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxv016452() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPorta.ts b/web/src/engine/websites/ComicPorta.ts index b5667dc22e..f1ebbbb17d 100644 --- a/web/src/engine/websites/ComicPorta.ts +++ b/web/src/engine/websites/ComicPorta.ts @@ -14,7 +14,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/series\/\d+\/$/, 'div#breadcrumb li:last-of-type') @Common.MangasSinglePageCSS('/series/', 'div.series-list ul li h3.title a') @Common.ChaptersSinglePageCSS('ul.episode-list li.episode div.inner div.wrap p.episode-btn', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index fd8afac200..9f4b77900a 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -32,7 +32,7 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { let pages: Page[] = await Common.FetchPagesSinglePageCSS.call(this, chapter, 'div.works_tateyomi__img img'); pages = pages?.map(page => new Page(this, chapter, page.Link, { useCommon: true })); - return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjax.call(this, chapter); + return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); } public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index adcd6be6bb..6561749534 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -43,7 +43,7 @@ export default class extends DecoratableMangaScraper { } let url = ""; if (origurl.includes("/reader")) { - url = "/reader?cid=" + chapid + "&sk=1"; + url = "/reader?cid=" + chapid; } else if (origurl.includes("/viewer")) { url = "https://image.mangaplanet.com/viewer/" + chapid; } @@ -52,4 +52,10 @@ export default class extends DecoratableMangaScraper { } return chapters; } + /* + public override async FetchPages(chapter: Chapter): Promise { + await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 10000);//set necessary cookies + return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); + }*/ + } \ No newline at end of file diff --git a/web/src/engine/websites/MangaPlaza.ts b/web/src/engine/websites/MangaPlaza.ts index 181705e3ae..c39b624376 100644 --- a/web/src/engine/websites/MangaPlaza.ts +++ b/web/src/engine/websites/MangaPlaza.ts @@ -1,9 +1,9 @@ import { Tags } from '../Tags'; import icon from './MangaPlaza.webp'; -import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Page, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchJSON } from '../platform/FetchProvider'; +import { FetchCSS, FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; type APIChapterResult = { data: { @@ -13,8 +13,6 @@ type APIChapterResult = { } @Common.MangaCSS(/^{origin}\/title\/\d+\/$/, 'div.mainTitle h1.titleTxt') -@Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjax(true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -26,6 +24,21 @@ export default class extends DecoratableMangaScraper { return icon; } + public override async Initialize(): Promise { + return FetchWindowScript(new Request(this.URI), `window.cookieStore.set('mp_over18_agreement', 'ON')`); + } + + public override async FetchMangas(provider: MangaPlugin): Promise { + //fetch genre list + let genres = (await FetchCSS(new Request(new URL('/genre/', this.URI)), 'a[href*="/genre/"]')).filter(link => link.pathname.match(/genre\/\d+\/$/)).map(link => link.pathname.match(/\d+/)[0]); + genres = Array.from(new Set(genres)); + const mangaList: Manga[] = []; + for (const genre of genres) { + mangaList.push(... await Common.FetchMangasMultiPageCSS.call(this, provider, `/genre/${genre}/?page={page}`, 'ul.listBox li div.titleName a')); + } + return mangaList.distinct(); + } + public override async FetchChapters(manga: Manga): Promise { const chapters: Chapter[] = []; const mangaid = manga.Identifier.match(/title\/(\d+)/)[1]; @@ -50,4 +63,10 @@ export default class extends DecoratableMangaScraper { return chapters.distinct(); } + + public override async FetchPages(chapter: Chapter): Promise { + await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 3000);//set necessary cookies + return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); + } + } \ No newline at end of file diff --git a/web/src/engine/websites/MichiKusa.ts b/web/src/engine/websites/MichiKusa.ts index cc95661441..3f7f7cf134 100644 --- a/web/src/engine/websites/MichiKusa.ts +++ b/web/src/engine/websites/MichiKusa.ts @@ -7,7 +7,7 @@ import * as SpeedBinb from './decorators/SpeedBinb'; function MangaInfoExtractor(element: HTMLElement) { return { id: element.querySelector('a').pathname, - title: element.querySelector('div.contents-info div.title').text.trim(), + title: element.querySelector('div.contents-info div.title').textContent.trim(), }; } function ChapterExtractor(anchor: HTMLAnchorElement) { @@ -20,7 +20,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/product\/[^/]+$/, 'header.entry-header h1.page-title') @Common.MangasMultiPageCSS('/product/page/{page}', 'div.entry-content', 1, 1, 0, MangaInfoExtractor) @Common.ChaptersSinglePageCSS('div.released_episodes div.items div.item a', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxV016061() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 75df597812..39e0ac2938 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -29,7 +29,7 @@ export default class extends DecoratableMangaScraper { //find real reader url to send to SpeedBinb, since redirection is done by Javascript const [ data ] = await FetchCSS(new Request(chapter.Identifier), 'body'); const reallink = data.innerHTML.match(/location.href='(.*)'/)[1]; - return SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); + return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index 69f22fb994..9bd7bd917d 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -22,7 +22,7 @@ type SSD = { } @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjaxv016130() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -43,8 +43,8 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const url = new URL(`/search/search.html?seriesid=${manga.Identifier}&order=1`, this.URI); - const { data } = await FetchWindowScript(new Request(url), 'window.ssd', 2000); - return data.item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.IsbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); + const { data: { item_datas } } = await FetchWindowScript(new Request(url), 'window.ssd', 2000); + return item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.IsbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); } IsbnToCid(isbn: string): string { diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index ab7397aedb..d188620b2d 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -1,8 +1,9 @@ import { Tags } from '../Tags'; import icon from './Yanmaga.webp'; -import { DecoratableMangaScraper } from '../providers/MangaPlugin'; +import { type Chapter, DecoratableMangaScraper, type Page } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { FetchWindowScript } from '../platform/FetchProvider'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -33,7 +34,6 @@ const chapterScript = ` @Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') @Common.MangasSinglePageCSS('/comics', 'a.ga-comics-book-item', MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 200) -@SpeedBinb.PagesSinglePageAjax() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -43,4 +43,10 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } + + public override async FetchPages(chapter: Chapter): Promise { + await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 3000);//set necessary cookies + return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); + } + } \ No newline at end of file diff --git a/web/src/engine/websites/YoMonga.ts b/web/src/engine/websites/YoMonga.ts index 1e29d6b6cc..0eeb8d3ac8 100644 --- a/web/src/engine/websites/YoMonga.ts +++ b/web/src/engine/websites/YoMonga.ts @@ -22,7 +22,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/titles\/\d+\//, 'div.intr-title') @Common.MangasMultiPageCSS('/titles/?page_num={page}', 'div.book-box4', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('div.episode-list', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(true) +@SpeedBinb.PagesSinglePageAjaxv016130() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -32,5 +32,4 @@ export default class extends DecoratableMangaScraper { public override get Icon() { return icon; } - } \ No newline at end of file diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index c1facb8c24..11c38abf56 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -1,6 +1,6 @@ import { Tags } from '../Tags'; import icon from './YoungJump.webp'; -import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper, Manga, type Page, type MangaPlugin, type Chapter } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; @@ -12,7 +12,7 @@ type APIMagazine = { } @Common.ChaptersUniqueFromManga() -@SpeedBinb.PagesSinglePageAjax() +//@SpeedBinb.PagesSinglePageAjaxv016201() @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -38,7 +38,11 @@ export default class extends DecoratableMangaScraper { public override async FetchMangas(provider: MangaPlugin): Promise { const data = await FetchJSON(new Request(new URL('/yj-rest-apis/getBookInfo.php', this.URI))); return data.map(magazine => new Manga(this, provider, magazine.url, `${magazine.issue} - ${magazine.number}`.trim())); + } + public override async FetchPages(chapter: Chapter): Promise { + await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI)), 'true', 2000); //set cookies + return SpeedBinb.FetchPagesSinglePageAjaxv016201.call(this, chapter); } } \ No newline at end of file diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index d772b82489..e114562f68 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -4,11 +4,25 @@ import type { Priority } from '../../taskpool/TaskPool'; import * as Common from './Common'; import DeScramble from '../../transformers/ImageDescrambler'; -type JSONPageDatav016452 = { - items: Configurationv016452[] +type ViewerData = { + viewerUrl: URL; + SBHtmlElement: HTMLElement } -type Configurationv016452 = { +type RequestData = { + cid: string, + sharingKey :string, + dmytime, + u0: string, + u1: string, + request: Request +} + +type JSONPageData = { + items: ContentConfiguration[] +} + +type ContentConfiguration = { ContentID: string, ctbl: string | string[], ptbl: string | string[], @@ -26,7 +40,7 @@ type Paramsv016452 = { sharingKey: string } -type JSONImageDatav016061 = { +type JSONImageData = { resources: { i: { src: string @@ -80,113 +94,76 @@ const JsonFetchScript = ` }); `; export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } + function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); return baseURI; - } -function getSpeedBinbVersion(el: HTMLElement, viewerUrl: URL): SpeedBinbVersion { - //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon : _default_v016061 - //(el.querySelectorAll('div[data-ptimg$="ptimg.json"]') - - /*CMOA :v016452 - ptbinb : "/bib/sws/bibGetCntntInfo.php?u0=1&u1=0" U0 U1 - ptbinbCid : "0000151961_jp_0001" - 'https://www.cmoa.jp/bib/speedreader/?cid=0000151961_jp_0001&u0=1&u1=0' U0 U1 CID - - BOOKHODAI :v016113 / v016130 - ptbinb "https://viewer.bookhodai.jp/sws/apis/bibGetCntntInfo.php?s=1&u0=8bec5433d58929b4ab4b5a07398fff33&u1=4554f324862d187e7c9d27c85e1d8d84" UO U1 - ptbinbCid "300010065401" - 'https://viewer.bookhodai.jp/speedreader/main.php?cid=300010065401&u0=8bec5433d58929b4ab4b5a07398fff33&u1=4554f324862d187e7c9d27c85e1d8d84&rurl=https%3A%2F%2Fbookhodai.jp%2F&member_id=0' U0 U1 CID - - BOOKLIVE :v016113 / v016130 - ptbinb : "/bib-api/bibGetCntntInfo" NOTHING - ptbinbCid: "60114561_001" - 'https://booklive.jp/bviewer/s/?cid=60114561_001' CID - - FUTBANET :v016113 / v016130 - ptbinb: "/sws/bibGetCntntInfo?hash=60ebb4277765619176000000&display_order=1" NOTHING - ptbinbCid: "60ebb4277765619176000000_001-001_1" - https://gaugau.futabanet.jp/list/work/60ebb4277765619176000000/episodes/1 NOTHING - - GETSUAKU :v016113 / v016130 - ptbinb: "../sws/bibGetCntntInfo" NOTHING - ptbinbCid: "001_gaw_makinasan" - https://getsuaku.com/episode/001_gaw_makinasan' NOTHING - - ManpaPlanet :v016113 / v016130 - ptbinb : "https://mangaplanet.com/sws/apis/bibGetCntntInfo.php NOTHING - 'https://mangaplanet.com/reader?cid=64c77843994e3' CID - - ManpaPlaza :v016113 / v016130 - ptbinb: "/sws/apis/bibGetCntntInfo.php?u0=0&u1=https%3A%2F%2Fmangaplaza.com%2Ftitle%2F0303001706%2F%3Forder%3Ddown%26content_id%3D103030017060001" U0 U1 - ptbinbCid: "103030017060001" - 'https://reader.mangaplaza.com/speedreader/?cid=103030017060001&u0=0&u1=https%3A%2F%2Fmangaplaza.com%2Ftitle%2F0303001706%2F%3Forder%3Ddown%26content_id%3D103030017060001' U0 U1 - - OHTABOOK :v016113 / v016130 - ptbinb: "https://console.binb.bricks.pub/bibGetCntntInfo?u0=83605b7e01f64a70baeec6bfe102f043" U0 - ptbinbCid: "cbb2ef02-0210-4050-804d-406713f40f61_1677753204" - 'https://binb.bricks.pub/contents/cbb2ef02-0210-4050-804d-406713f40f61_1677753204/speed_reader' NOTHING - - S-MANGA: :v016113 / v016130 - ptbinb: "./sws/apis/bibGetCntntInfo.php" NOTHING - ptbinbCid: "4088725093" - https://www.s-manga.net/reader/main.php?cid=4088725093' CID - - YANMAGA : v016113 / v016130 - ptbinb: "/viewer/bibGetCntntInfo?type=comics" NOTHING - ptbinbCid: "06A0000000000731237F" - 'https://yanmaga.jp/viewer/comics/%E5%A4%A2%E3%81%86%E3%81%A4%E3%81%A4%E3%81%AE%E8%8A%B1%E3%81%AE%E5%9C%92/351192c0f7d1cf3b88175f3d9dfae594?cid=06A0000000000731237F' CID - - YOUNGJUMP :v016201 - ptbinb :"/sws/apis/bibGetCntntInfo.php?u1=10001" U1 - ptbinbCid: "101012340" - https://www.youngjump.world/reader/reader.html?cid=101012340&u1=10001': CID U1 -*/ - - if (el.dataset['ptbinb'] && el.dataset['ptbinbCid']) { - return SpeedBinbVersion.v016113; - } - - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u0') && viewerUrl.searchParams.get('u1')) { - return SpeedBinbVersion.v016452; - } +/** + * Return real chapter url & SpeedBinb "pages" element from said page, so we can work + * @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 + */ +async function GetViewerData(this: MangaScraper, chapter: Chapter): Promise { + let viewerUrl = new URL(chapter.Identifier, this.URI); + const request = new Request(viewerUrl, { + headers: { + Referer: this.URI.origin + } + }); - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo') && viewerUrl.searchParams.get('u1')) { - return SpeedBinbVersion.v016201; + const response = await Fetch(request); + const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); + const SBHtmlElement = dom.querySelector('div#content.pages'); + //handle redirection. Sometimes chapter is redirected + if (response.redirected) { + viewerUrl = new URL(response.url); } + return { viewerUrl, SBHtmlElement }; +} +/** + * Create first SpeedBinb AJAX request to perform, using viewerUrl GET parameters, and endpoint from SpeedBinb HTML node + * @param viewerUrl - Read Url of the SpeedBinb Viewer + * @param sbHtmlElement - HTMLElement extracted from said page + */ +async function CreatePtBinbRequestData(viewerUrl: URL, sbHtmlElement: HTMLElement): Promise{ + let cid = viewerUrl.searchParams.get('cid') || sbHtmlElement.dataset['ptbinbCid']; - if (el.dataset['ptbinb'] && el.dataset.ptbinb.includes('bibGetCntntInfo')) { - return SpeedBinbVersion.v016130; + //in case cid is not in url and not in html, try to get it from page redirected by Javascript/ Meta element + if (!cid) { + cid = await FetchWindowScript(new Request(viewerUrl), 'new URL(window.location).searchParams.get("cid");', 5000); } + if (!cid) throw new Error('Unable to find CID (content ID) !'); - if (el.querySelectorAll('div[data-ptimg$="ptimg.json"]').length > 0) { - return SpeedBinbVersion._default_v016061; - } + const sharingKey = _tt(cid); + const uri = getSanitizedURL(viewerUrl.href, sbHtmlElement.dataset.ptbinb); + const dmytime = String(Date.now()); + uri.searchParams.set('cid', cid); + uri.searchParams.set('dmytime', dmytime); + uri.searchParams.set('k', sharingKey); - return SpeedBinbVersion.vUnknown; -} + const u0 = viewerUrl.searchParams.get('u0'); + const u1 = viewerUrl.searchParams.get('u1'); + if (u0) uri.searchParams.set('u0', u0); + if (u1) uri.searchParams.set('u1', u1); -const pageScript = ` - new Promise(resolve => { - resolve ( { location : window.location.href, pages : document.querySelector("div#content.pages")}); + const request = new Request(uri, { + headers: { + Referer: viewerUrl.href + } }); -`; -type PageScriptResult = { - location: string, - pages: HTMLElement + return { cid, sharingKey, dmytime, u0, u1, request }; } + /********************************************** ******** Page List Extraction Methods ******** **********************************************/ /** - * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. - * @param useScript - use FetchWindowScript and not Fetch for first request - * @param sbVersionOverride - Override SpeedBinb version detection + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer when chapter JSON got div[data-ptimg$="ptimg.json"] */ export function PagesSinglePageAjaxV016061() { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { @@ -206,27 +183,26 @@ export function PagesSinglePageAjaxV016061() { * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages - * @param useScript - use FetchWindowScript and not Fetch for first request - * @param sbVersionOverride - Override SpeedBinb version detection */ export async function FetchPagesSinglePageAjaxV016061(this: MangaScraper, chapter: Chapter): Promise { - let viewerUrl = new URL(chapter.Identifier, this.URI); - const request = new Request(viewerUrl, { - headers: { - Referer: this.URI.origin - } - }); + const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); + const [...imageConfigurations] = SBHtmlElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); +} - const response = await Fetch(request); - const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); - const SBpagesElement = dom.querySelector('div#content.pages'); - //handle redirection. Sometimes chapter is redirected - if (response.redirected) { - viewerUrl = new URL(response.url); - } +/** + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. For version v016130 + */ +export function PagesSinglePageAjaxv016130() { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); - const [...imageConfigurations] = SBpagesElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); - return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageAjaxv016130.call(this, chapter); + } + }; + }; } /** @@ -234,109 +210,102 @@ export async function FetchPagesSinglePageAjaxV016061(this: MangaScraper, chapte * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages - * @param useScript - use FetchWindowScript and not Fetch for first request - * @param sbVersionOverride - Override SpeedBinb version detection */ -export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, useScript = false, sbVersionOverride: SpeedBinbVersion = undefined): Promise { - let viewerUrl = new URL(chapter.Identifier, this.URI); - const request = new Request(viewerUrl, { - headers: { - Referer: this.URI.origin - } - });//referer needed for ManpaPlanet - - let SBpagesElement: HTMLElement = undefined; - - // Raw fetching Gives the most accurate version detection and it handle automatic redirection. - // We dont use FetchCSS because we must know if request is redirected (302, 303) to get real url - // Also, FetchWindowScript doesnt works with Referer, and sometimes Referer is mandatory (MangaPlanet) - if (!useScript) { - const response = await Fetch(request); - const dom = new DOMParser().parseFromString(await response.text(), 'text/html'); - const data = dom.querySelector('div#content.pages'); - //handle redirection. Sometimes chapter is redirected - if (response.redirected) { - viewerUrl = new URL(response.url); - } - SBpagesElement = data; - } else { - //Use this if chapter is redirected using javascript, or if it must be opened in a window to gather access Cookies (MangaPlaza) - const data = await FetchWindowScript(request, pageScript, 2500); - if (!data.pages) return []; //chapter may be paywalled, no need to throw an error, so quit gracefully - viewerUrl = new URL(data.location); - SBpagesElement = data.pages; - } +export async function FetchPagesSinglePageAjaxv016130(this: MangaScraper, chapter: Chapter): Promise { + const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); + const { request, sharingKey } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); + const config = await FetchJSON(request); + return await getPageLinks_v016130.call(this, config.items[0], sharingKey, chapter); - const SBVersion = sbVersionOverride || getSpeedBinbVersion(SBpagesElement, viewerUrl); +} - if (SBVersion == SpeedBinbVersion.v016113) { - viewerUrl.searchParams.set('cid', SBpagesElement.dataset['ptbinbCid']); - } +/** + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. + */ +export function PagesSinglePageAjaxv016452() { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); - //Handle _default_v016061 : there is no parameter at all - //Comic Brise, Comic Meteor, Comic Polaris, Comic Valkyrie, Digital MargaRet, OneTwoThreeHon, TKSuperheroComics - if (SBVersion == SpeedBinbVersion._default_v016061) { - const [...imageConfigurations] = SBpagesElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); - return imageConfigurations.map(element => { - return new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg)); - }); - } + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageAjaxv016452.call(this, chapter); + } + }; + }; +} - const cid = viewerUrl.searchParams.get('cid'); - const sharingKey = _tt(cid); - const uri = getSanitizedURL(viewerUrl.href, SBpagesElement.dataset.ptbinb); - uri.searchParams.set('cid', cid); - uri.searchParams.set('dmytime', String(Date.now())); - uri.searchParams.set('k', sharingKey); +/** + * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. + * 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 FetchPagesSinglePageAjaxv016452(this: MangaScraper, chapter: Chapter): Promise { + const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); + const { request, sharingKey, cid, u0, u1 } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); + const config = await FetchJSON(request); + const params: Paramsv016452 = { cid, sharingKey, u0, u1 }; + return await getPageLinks_v016452.call(this, config.items[0], params, chapter); - switch (SBVersion) { - case SpeedBinbVersion.v016113: //BookHodai, Futabanet, Getsuaku (v016700), MangaPlaza, Ohtabooks - case SpeedBinbVersion.v016130: { // Booklive, MangaPlanet, S-Manga, Yanmaga - //Doing it like that because of cookies needed for Mangaplanet using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', uri.href), 2000); - return await getPageLinks_v016130(this, data.items[0], sharingKey, chapter); - } - //YoungJump - case SpeedBinbVersion.v016201: { - const u = viewerUrl.searchParams.get('u1'); - uri.searchParams.set('u1', u); - //Doing it like that because of cookies needed for YoungJump using viewerUrl on purpose because of CORS issues - const data = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', uri.href), 2000); - return await getPageLinks_v016201(this, data.items[0], sharingKey, u, chapter); - } - //Cmoa - case SpeedBinbVersion.v016452: { - const u0 = viewerUrl.searchParams.get('u0'); - const u1 = viewerUrl.searchParams.get('u1'); - uri.searchParams.set('u0', u0); - uri.searchParams.set('u1', u1); - const data = await FetchJSON(new Request(uri)); - const params: Paramsv016452 = { cid, sharingKey, u0, u1 }; - return await getPageLinks_v016452(this, data.items[0], params, chapter); - } - } +} - throw new Error('Unsupported version of SpeedBinb reader!'); +/** + * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. + */ +export function PagesSinglePageAjaxv016201() { + return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { + Common.ThrowOnUnsupportedDecoratorContext(context); + + return class extends ctor { + public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { + return FetchPagesSinglePageAjaxv016201.call(this, chapter); + } + }; + }; +} + +/** + * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. + * 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 FetchPagesSinglePageAjaxv016201(this: MangaScraper, chapter: Chapter): Promise { + const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); + const { request, sharingKey, u1 } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); + const config = await FetchJSON(request); + return await getPageLinks_v016201.call(this, config.items[0], sharingKey, u1, chapter); +} + +/** + * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. + * 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 { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); + const { request, sharingKey } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); + const config = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', request.url), 2000); + return await getPageLinks_v016130.call(this, config.items[0], sharingKey, chapter); } /** * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. - * @param useScript - use FetchWindowScript and not Fetch for first request - * @param sbVersionOverride - Override SpeedBinb version detection */ -export function PagesSinglePageAjax(useScript = false, sbVersionOverride: SpeedBinbVersion = undefined) { +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, useScript, sbVersionOverride); + return FetchPagesSinglePageAjax.call(this, chapter); } }; }; } -async function getPageLinks_v016452(scraper: MangaScraper, configuration: Configurationv016452, params: Paramsv016452, chapter: Chapter): Promise { +async function getPageLinks_v016452(this: MangaScraper, configuration: ContentConfiguration, params: Paramsv016452, chapter: Chapter): Promise { configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); try { @@ -353,12 +322,12 @@ async function getPageLinks_v016452(scraper: MangaScraper, configuration: Config uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('u0', params.u0); uri.searchParams.set('u1', params.u1); - return await fetchSBC(scraper, uri, configuration, chapter); + return await fetchSBC.call(this, uri, configuration, chapter); } return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinks_v016201(scraper: MangaScraper, configuration: Configurationv016452, sharingKey: string, u: string, chapter: Chapter): Promise { +async function getPageLinks_v016201(this: MangaScraper, configuration: ContentConfiguration, sharingKey: string, u: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); @@ -377,14 +346,14 @@ async function getPageLinks_v016201(scraper: MangaScraper, configuration: Config const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); }); return pageLinks; } return Promise.reject(new Error('Content server type not supported!')); } -async function getPageLinks_v016130(scraper: MangaScraper, configuration: Configurationv016452, sharingKey: string, chapter: Chapter): Promise { +async function getPageLinks_v016130(this: MangaScraper, configuration: ContentConfiguration, sharingKey: string, chapter: Chapter): Promise { const cid = configuration.ContentID; configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); @@ -401,7 +370,7 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('p', configuration.p); uri.searchParams.set('vm', String(configuration.ViewMode)); - return await fetchSBC(scraper, uri, configuration, chapter); + return await fetchSBC.call(this, uri, configuration, chapter); } case 1: {//Futabanet, Getsuaku, BookHodai const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); @@ -414,19 +383,19 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config let src = img.getAttribute('src'); uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); if (!src.startsWith('/')) src = '/' + src; - return new Page(scraper, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); + return new Page(this, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); }); return pageLinks; } case 2: {//MangaPlanet, MangaPlaza const uri = getSanitizedURL(configuration.ContentsServer, 'content'); - uri.searchParams.set('dmytime', configuration.ContentDate); - const data = await FetchJSON(new Request(uri, { headers: { Referer: scraper.URI.href } })); + if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); + const data = await FetchJSON(new Request(uri, { headers: { Referer: this.URI.href }})); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(scraper, chapter, new URL(uri.href.replace('/content', '/img/' + src))); + return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); }); return pageLinks; } @@ -434,14 +403,14 @@ async function getPageLinks_v016130(scraper: MangaScraper, configuration: Config return Promise.reject(new Error('Content server type not supported!')); } -async function fetchSBC(scraper: MangaScraper, uri: URL, configuration: Configurationv016452, chapter: Chapter) { +async function fetchSBC(this: MangaScraper, uri: URL, configuration: ContentConfiguration, chapter: Chapter) { const data = await FetchJSON(new Request(uri)); const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { const src = img.getAttribute('src'); uri.searchParams.set('src', src); uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(scraper, chapter, new URL(uri.href.replace('/sbcGetCntnt.php', '/sbcGetImg.php'))); + return new Page(this, chapter, new URL(uri.href.replace('/sbcGetCntnt.php', '/sbcGetImg.php'))); }); return pageLinks; } @@ -472,7 +441,7 @@ export async function FetchImageAjax(this: MangaScraper, page: Page, priority: P } async function descramble_v016061(scraper: MangaScraper, page: Page, priority: Priority, signal: AbortSignal, detectMimeType = false): Promise { - const data = await FetchJSON(new Request(page.Link)); + const data = await FetchJSON(new Request(page.Link)); const fakepage = new Page(scraper, page.Parent as Chapter, new URL(data.resources.i.src, page.Link.href)); const imagedata: Blob = await Common.FetchImageAjax.call(scraper, fakepage, priority, signal, detectMimeType); From b69e2af55b04e5c1850f65ce60af6548897d0b6d Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 28 Jul 2024 15:58:06 +0200 Subject: [PATCH 71/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index fa795067d1..7651fa506e 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -47,6 +47,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as BoysLove } from './BoysLove'; export { default as CartelDeManhwas } from './CartelDeManhwas'; @@ -56,6 +58,7 @@ export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -63,6 +66,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -71,12 +75,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -107,6 +115,7 @@ export { default as DessertScan } from './DessertScan'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -147,6 +156,7 @@ export { default as FreeWebtoonCoins } from './FreeWebtoonCoins'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyManga } from './GalaxyManga'; export { default as GanGanOnline } from './GanGanOnline'; @@ -382,6 +392,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaPure } from './MangaPure'; export { default as MangaRaw1001 } from './MangaRaw1001'; @@ -484,6 +496,7 @@ export { default as Mexat } from './Mexat'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as MilfToon } from './MilfToon'; export { default as MindaFanSub } from './MindaFanSub'; @@ -528,7 +541,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -646,6 +661,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpoilerPlus } from './SpoilerPlus'; @@ -674,6 +690,7 @@ export { default as TheBlank } from './TheBlank'; export { default as TheGuildScans } from './TheGuildScans'; export { default as ThreeHentai } from './ThreeHentai'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -745,6 +762,7 @@ export { default as XManga } from './XManga'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -753,6 +771,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YugenMangasPT } from './YugenMangasPT'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; @@ -774,20 +794,14 @@ export { default as AnimExtremist } from './legacy/AnimExtremist'; export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -861,9 +875,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as SakuraManga } from './legacy/SakuraManga'; @@ -906,6 +918,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 89674d7df274d9e609e6d45d2e9c863ea7f34051 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 29 Jul 2024 14:21:57 +0200 Subject: [PATCH 72/88] Update SpeedBinb.ts --- web/src/engine/websites/decorators/SpeedBinb.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index e114562f68..d80383713b 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -87,11 +87,15 @@ type Dimensions = { } const JsonFetchScript = ` - new Promise(resolve => { + new Promise(resolve, reject) => { + try { fetch('{URI}') .then(response => response.json()) .then(json => resolve(json)) - }); + } catch {error} { + reject(error); + } + }); `; export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } From db95ad4d35775ecc9932e757f98695b4ab8cdb27 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 14 Aug 2024 13:09:18 +0200 Subject: [PATCH 73/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d2870126a8..5135611540 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -45,6 +45,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boosei } from './Boosei'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -53,6 +55,7 @@ export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; export { default as CloverManga } from './CloverManga'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -60,6 +63,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -68,12 +72,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -103,6 +111,7 @@ export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -141,6 +150,7 @@ export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; export { default as FunManga } from './FunManga'; export { default as FuryoSquad } from './FuryoSquad'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GalaxyManga } from './GalaxyManga'; export { default as GanGanOnline } from './GanGanOnline'; @@ -362,6 +372,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -458,6 +470,7 @@ export { default as Mexat } from './Mexat'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilfToon } from './MilfToon'; @@ -501,7 +514,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -613,6 +628,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpoilerPlus } from './SpoilerPlus'; @@ -638,6 +654,7 @@ export { default as TenshiID } from './TenshiID'; export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -709,6 +726,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -717,6 +735,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -736,20 +756,14 @@ export { default as AnimExtremist } from './legacy/AnimExtremist'; export { default as Aniwave } from './legacy/Aniwave'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -817,9 +831,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as Qiman5 } from './legacy/Qiman5'; export { default as SakuraManga } from './legacy/SakuraManga'; @@ -861,6 +873,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From b76a024ebcb869cc24919d4df1c1fcf619ec1ad8 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Wed, 14 Aug 2024 13:18:29 +0200 Subject: [PATCH 74/88] fix lint errors --- web/src/engine/websites/decorators/SpeedBinb.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index d80383713b..004c6cad1a 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -314,6 +314,7 @@ async function getPageLinks_v016452(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ } catch (error) { // } @@ -337,6 +338,7 @@ async function getPageLinks_v016201(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ } catch (error) { // } @@ -363,6 +365,7 @@ async function getPageLinks_v016130(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ } catch (error) { // } @@ -533,6 +536,7 @@ function _pt(t: string, i: string, n: string): string[] { } try { return JSON.parse(u); + /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ } catch (t) { return null; } From 89d3ad8a7d286fe273b984932c2ba25428233c13 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 9 Sep 2024 21:13:04 +0200 Subject: [PATCH 75/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 080fb4ac3d..dd01971bb8 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -46,12 +46,15 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; 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 Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -59,6 +62,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -67,12 +71,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -101,6 +109,7 @@ export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DisasterScans } from './DisasterScans'; export { default as DiskusScan } from './DiskusScan'; @@ -136,6 +145,7 @@ export { default as FranxxMangas } from './FranxxMangas'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -354,6 +364,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -448,6 +460,7 @@ export { default as MerlinScans } from './MerlinScans'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -493,7 +506,9 @@ export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as NvManga } from './NvManga'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -609,6 +624,7 @@ export { default as SirenKomik } from './SirenKomik'; export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpoilerPlus } from './SpoilerPlus'; @@ -637,6 +653,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -709,6 +726,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -717,6 +735,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -733,20 +753,14 @@ export { default as AllHentai } from './legacy/AllHentai'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -811,9 +825,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as SakuraManga } from './legacy/SakuraManga'; export { default as SelfManga } from './legacy/SelfManga'; @@ -853,6 +865,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 3488c99876561f97d2034794f83af80fe015cf78 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Mon, 23 Sep 2024 12:51:33 +0200 Subject: [PATCH 76/88] remove useless errors from catches --- .../engine/websites/decorators/SpeedBinb.ts | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 004c6cad1a..6cb775a64c 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -314,10 +314,7 @@ async function getPageLinks_v016452(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - } catch (error) { - // - } + } catch { } if (configuration.ServerType === 0) {//CMOA const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); uri.searchParams.set('cid', params.cid); @@ -338,10 +335,7 @@ async function getPageLinks_v016201(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - } catch (error) { - // - } + } catch { } if (configuration.ServerType === 2) { const uri = getSanitizedURL(configuration.ContentsServer, 'content'); @@ -365,10 +359,7 @@ async function getPageLinks_v016130(this: MangaScraper, configuration: ContentCo configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - } catch (error) { - // - } + } catch { } switch (configuration.ServerType as number) { case 0: { //Booklive @@ -536,8 +527,7 @@ function _pt(t: string, i: string, n: string): string[] { } try { return JSON.parse(u); - /* eslint-disable-next-line @typescript-eslint/no-unused-vars */ - } catch (t) { + } catch { return null; } } From 4ca1624b58cb6d989f3fc72e9e71c55b66b280fd Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 28 Sep 2024 11:55:26 +0200 Subject: [PATCH 77/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index cb531ef22b..2965f9edb3 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -44,6 +44,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -51,6 +53,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -58,6 +61,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -66,12 +70,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; export { default as Comikey } from './Comikey'; @@ -103,6 +111,7 @@ export { default as DemonSect } from './DemonSect'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -137,6 +146,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -355,6 +365,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -450,6 +462,7 @@ export { default as MerlinScans } from './MerlinScans'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -495,7 +508,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -610,6 +625,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -639,6 +655,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -712,6 +729,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -720,6 +738,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -736,20 +756,14 @@ export { default as AllHentai } from './legacy/AllHentai'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -814,9 +828,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as SelfManga } from './legacy/SelfManga'; export { default as ShinobiScans } from './legacy/ShinobiScans'; @@ -855,6 +867,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 438484e39d8b2b30cfa4ba2b99d4cf0374f16adf Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Thu, 17 Oct 2024 10:10:34 +0200 Subject: [PATCH 78/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index d00f54b587..c123a47427 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -43,6 +43,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -50,6 +52,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -57,6 +60,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -65,12 +69,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -104,6 +112,7 @@ export { default as DennoMavo } from './DennoMavo'; export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -139,6 +148,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -353,6 +363,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -446,6 +458,7 @@ export { default as MerlinScans } from './MerlinScans'; export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -489,7 +502,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -601,6 +616,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -632,6 +648,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -706,6 +723,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -714,6 +732,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -730,20 +750,14 @@ export { default as AllHentai } from './legacy/AllHentai'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -807,9 +821,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as SelfManga } from './legacy/SelfManga'; export { default as ShinobiScans } from './legacy/ShinobiScans'; @@ -848,6 +860,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From 0e913f6c12be163f4f1d6371d46d3b0a21afe5c6 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 27 Oct 2024 10:31:34 +0100 Subject: [PATCH 79/88] update tests --- web/src/engine/websites/BookHodai_e2e.ts | 4 +-- web/src/engine/websites/BookLive_e2e.ts | 4 +-- web/src/engine/websites/Cmoa_e2e.ts | 4 +-- web/src/engine/websites/ComicBrise_e2e.ts | 4 +-- web/src/engine/websites/ComicMeteor_e2e.ts | 4 +-- web/src/engine/websites/ComicPolaris_e2e.ts | 4 +-- web/src/engine/websites/ComicPorta_e2e.ts | 4 +-- web/src/engine/websites/ComicValkyrie_e2e.ts | 4 +-- .../engine/websites/DigitalMargaret_e2e.ts | 4 +-- web/src/engine/websites/Futabanet_e2e.ts | 4 +-- web/src/engine/websites/MangaPlanet_e2e.ts | 4 +-- web/src/engine/websites/MangaPlaza_e2e.ts | 4 +-- web/src/engine/websites/MichiKusa_e2e.ts | 4 +-- web/src/engine/websites/Ohtabooks_e2e.ts | 4 +-- web/src/engine/websites/OneTwoThreeHon_e2e.ts | 4 +-- web/src/engine/websites/SManga_e2e.ts | 4 +-- .../engine/websites/TKSuperheroComics_e2e.ts | 4 +-- web/src/engine/websites/Yanmaga_e2e.ts | 4 +-- web/src/engine/websites/YoMonga_e2e.ts | 4 +-- web/src/engine/websites/YoungJump_e2e.ts | 4 +-- web/src/engine/websites/_index.ts | 29 +++++++++++++------ 21 files changed, 40 insertions(+), 69 deletions(-) diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts index bd1886e92c..2e3ca1802f 100644 --- a/web/src/engine/websites/BookHodai_e2e.ts +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -25,5 +24,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/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts index 4977953c01..6ea8cc1afc 100644 --- a/web/src/engine/websites/BookLive_e2e.ts +++ b/web/src/engine/websites/BookLive_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/Cmoa_e2e.ts b/web/src/engine/websites/Cmoa_e2e.ts index ff39303196..a5db576f54 100644 --- a/web/src/engine/websites/Cmoa_e2e.ts +++ b/web/src/engine/websites/Cmoa_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/ComicBrise_e2e.ts b/web/src/engine/websites/ComicBrise_e2e.ts index 63a1f1a5bd..a7f48ef5ed 100644 --- a/web/src/engine/websites/ComicBrise_e2e.ts +++ b/web/src/engine/websites/ComicBrise_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/ComicMeteor_e2e.ts b/web/src/engine/websites/ComicMeteor_e2e.ts index 9426d5066c..a85fa49985 100644 --- a/web/src/engine/websites/ComicMeteor_e2e.ts +++ b/web/src/engine/websites/ComicMeteor_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/ComicPolaris_e2e.ts b/web/src/engine/websites/ComicPolaris_e2e.ts index fd52919746..0a9dd1ec12 100644 --- a/web/src/engine/websites/ComicPolaris_e2e.ts +++ b/web/src/engine/websites/ComicPolaris_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/ComicPorta_e2e.ts b/web/src/engine/websites/ComicPorta_e2e.ts index 11a81f062f..54f941c380 100644 --- a/web/src/engine/websites/ComicPorta_e2e.ts +++ b/web/src/engine/websites/ComicPorta_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/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts index 8048feba24..188e0faa91 100644 --- a/web/src/engine/websites/ComicValkyrie_e2e.ts +++ b/web/src/engine/websites/ComicValkyrie_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/DigitalMargaret_e2e.ts b/web/src/engine/websites/DigitalMargaret_e2e.ts index 48965fdff5..f4d8e57c68 100644 --- a/web/src/engine/websites/DigitalMargaret_e2e.ts +++ b/web/src/engine/websites/DigitalMargaret_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/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index 68d6471292..880e5edb52 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -23,8 +22,7 @@ const config: Config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); +new TestFixture(config).AssertWebsite(); const NoSpeedBinbConfig: Config = { plugin: { diff --git a/web/src/engine/websites/MangaPlanet_e2e.ts b/web/src/engine/websites/MangaPlanet_e2e.ts index 6340969891..64849177b2 100644 --- a/web/src/engine/websites/MangaPlanet_e2e.ts +++ b/web/src/engine/websites/MangaPlanet_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/MangaPlaza_e2e.ts b/web/src/engine/websites/MangaPlaza_e2e.ts index fac42609ab..c052010361 100644 --- a/web/src/engine/websites/MangaPlaza_e2e.ts +++ b/web/src/engine/websites/MangaPlaza_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/MichiKusa_e2e.ts b/web/src/engine/websites/MichiKusa_e2e.ts index 1b1d6d3b7b..fd0d6937c7 100644 --- a/web/src/engine/websites/MichiKusa_e2e.ts +++ b/web/src/engine/websites/MichiKusa_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/Ohtabooks_e2e.ts b/web/src/engine/websites/Ohtabooks_e2e.ts index 4536e7944b..c6a5a03ff4 100644 --- a/web/src/engine/websites/Ohtabooks_e2e.ts +++ b/web/src/engine/websites/Ohtabooks_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture, type Config } from '../../../test/WebsitesFixture'; const config: Config = { @@ -24,5 +23,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/OneTwoThreeHon_e2e.ts b/web/src/engine/websites/OneTwoThreeHon_e2e.ts index 4a70ebc2a0..62d57ae4e5 100644 --- a/web/src/engine/websites/OneTwoThreeHon_e2e.ts +++ b/web/src/engine/websites/OneTwoThreeHon_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/SManga_e2e.ts b/web/src/engine/websites/SManga_e2e.ts index 7721a2007b..7b228599b3 100644 --- a/web/src/engine/websites/SManga_e2e.ts +++ b/web/src/engine/websites/SManga_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/TKSuperheroComics_e2e.ts b/web/src/engine/websites/TKSuperheroComics_e2e.ts index 7da2deb842..29fe09eb30 100644 --- a/web/src/engine/websites/TKSuperheroComics_e2e.ts +++ b/web/src/engine/websites/TKSuperheroComics_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/Yanmaga_e2e.ts b/web/src/engine/websites/Yanmaga_e2e.ts index 28d98190e4..d19c23d2ba 100644 --- a/web/src/engine/websites/Yanmaga_e2e.ts +++ b/web/src/engine/websites/Yanmaga_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/YoMonga_e2e.ts b/web/src/engine/websites/YoMonga_e2e.ts index a5ae49d7a1..1f5db6e0b3 100644 --- a/web/src/engine/websites/YoMonga_e2e.ts +++ b/web/src/engine/websites/YoMonga_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { } }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/YoungJump_e2e.ts b/web/src/engine/websites/YoungJump_e2e.ts index 9db5d934a9..9c6b2945c0 100644 --- a/web/src/engine/websites/YoungJump_e2e.ts +++ b/web/src/engine/websites/YoungJump_e2e.ts @@ -1,4 +1,3 @@ -import { describe } from 'vitest'; import { TestFixture } from '../../../test/WebsitesFixture'; const config = { @@ -23,5 +22,4 @@ const config = { }*/ }; -const fixture = new TestFixture(config); -describe(fixture.Name, async () => (await fixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(config).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index b07b22eada..da9c596f92 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -43,6 +43,8 @@ export { default as BlogTruyenMoi } from './BlogTruyenMoi'; export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -50,6 +52,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -57,6 +60,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -65,12 +69,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -105,6 +113,7 @@ export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; export { default as Digimon } from './Digimon'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -141,6 +150,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -353,6 +363,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -446,6 +458,7 @@ export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; export { default as MiauScan } from './MiauScan'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -488,8 +501,10 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OkToon } from './OkToon'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -601,6 +616,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -632,6 +648,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -707,6 +724,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -715,6 +733,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -731,20 +751,14 @@ export { default as AllHentai } from './legacy/AllHentai'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as DongManManhua } from './legacy/DongManManhua'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -807,9 +821,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as SelfManga } from './legacy/SelfManga'; export { default as ShinobiScans } from './legacy/ShinobiScans'; @@ -848,6 +860,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From dc20bc37117eb3c24ddb2aa7814fdce970a1851c Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 27 Oct 2024 10:38:23 +0100 Subject: [PATCH 80/88] Update Futabanet_e2e.ts --- web/src/engine/websites/Futabanet_e2e.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index 880e5edb52..8d150933af 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -45,5 +45,4 @@ const NoSpeedBinbConfig: Config = { } }; -const NoSpeedBinbfixture = new TestFixture(NoSpeedBinbConfig); -describe(NoSpeedBinbfixture.Name, async () => (await NoSpeedBinbfixture.Connect()).AssertWebsite()); \ No newline at end of file +new TestFixture(NoSpeedBinbConfig).AssertWebsite(); From 26462eb045587a58fae2fd247a0bf22b1df48187 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 16 Nov 2024 12:50:12 +0100 Subject: [PATCH 81/88] update --- web/src/engine/websites/_index.ts | 29 +++++++++++++------ .../engine/websites/decorators/SpeedBinb.ts | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index c28499fd32..c5e6e51e89 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -44,6 +44,8 @@ export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as BomtoonCN } from './BomtoonCN'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -51,6 +53,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -58,6 +61,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -66,12 +70,16 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; export { default as ComicOnlineFree } from './ComicOnlineFree'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -106,6 +114,7 @@ export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; export { default as Digimon } from './Digimon'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -143,6 +152,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -354,6 +364,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -447,6 +459,7 @@ export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; export { default as MiauScan } from './MiauScan'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -487,7 +500,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -599,6 +614,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -633,6 +649,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -708,6 +725,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -716,6 +734,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -732,19 +752,13 @@ export { default as AllHentai } from './legacy/AllHentai'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -800,9 +814,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as SelfManga } from './legacy/SelfManga'; export { default as ShinobiScans } from './legacy/ShinobiScans'; @@ -841,6 +853,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 6cb775a64c..675c7187e4 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -97,7 +97,7 @@ const JsonFetchScript = ` } }); `; -export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } +//export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); From 008b2cdbd04badace3d9e357da2520a7a54a14c0 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sat, 16 Nov 2024 14:06:46 +0100 Subject: [PATCH 82/88] fix promise --- web/src/engine/websites/decorators/SpeedBinb.ts | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index 675c7187e4..fae81f35a9 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -87,17 +87,16 @@ type Dimensions = { } const JsonFetchScript = ` - new Promise(resolve, reject) => { + new Promise((resolve, reject) => { try { fetch('{URI}') .then(response => response.json()) .then(json => resolve(json)) - } catch {error} { + } catch (error) { reject(error); } }); `; -//export enum SpeedBinbVersion { v016113 = 1, v016201, v016452, v016130, _default_v016061, vUnknown } function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); From 226ad8e25395dfb803b73a104c599389eb5f0567 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 22 Nov 2024 11:37:49 +0100 Subject: [PATCH 83/88] fix clipboard on futaba --- web/src/engine/websites/Futabanet.ts | 6 +++--- web/src/engine/websites/Futabanet_e2e.ts | 25 +----------------------- 2 files changed, 4 insertions(+), 27 deletions(-) diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index 9f4b77900a..f2c5007842 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -6,7 +6,7 @@ import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; import type { Priority } from '../taskpool/DeferredTask'; -@Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'div.works__grid div.list__text div.mbOff h1') +@Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'ol.breadcrumb li:last-of-type') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') export default class extends DecoratableMangaScraper { @@ -29,13 +29,13 @@ export default class extends DecoratableMangaScraper { }); } - public override async FetchPages(chapter: Chapter): Promise { + public override async FetchPages(chapter: Chapter): Promise { //Not sure if needed anymore let pages: Page[] = await Common.FetchPagesSinglePageCSS.call(this, chapter, 'div.works_tateyomi__img img'); pages = pages?.map(page => new Page(this, chapter, page.Link, { useCommon: true })); return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); } - public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { + public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { //Not sure if needed anymore return page.Parameters?.useCommon ? Common.FetchImageAjax.call(this, page, priority, signal) : SpeedBinb.FetchImageAjax.call(this, page, priority, signal); } } \ No newline at end of file diff --git a/web/src/engine/websites/Futabanet_e2e.ts b/web/src/engine/websites/Futabanet_e2e.ts index 8d150933af..b717d716c5 100644 --- a/web/src/engine/websites/Futabanet_e2e.ts +++ b/web/src/engine/websites/Futabanet_e2e.ts @@ -22,27 +22,4 @@ const config: Config = { } }; -new TestFixture(config).AssertWebsite(); - -const NoSpeedBinbConfig: Config = { - plugin: { - id: 'futabanet', - title: 'がうがうモンスター (Futabanet Monster)' - }, - container: { - url: 'https://gaugau.futabanet.jp/list/work/oCMElLZtSKn7e5PVKDuV2josm', - id: '/list/work/oCMElLZtSKn7e5PVKDuV2josm', - title: 'ルーン魔術だけが取り柄の不憫令嬢、天才王子に溺愛される ~婚約者、仕事、成果もすべて姉に横取りされた地味な妹ですが、ある日突然立場が逆転しちゃいました~' - }, - child: { - id: '/list/work/oCMElLZtSKn7e5PVKDuV2josm/episodes/7', - title: '第3話(3)', - }, - entry: { - index: 0, - size: 204_914, - type: 'image/jpeg' - } -}; - -new TestFixture(NoSpeedBinbConfig).AssertWebsite(); +new TestFixture(config).AssertWebsite(); \ No newline at end of file From 4dcc88e6addf253f265debb7daebb6d61ebf7405 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 22 Nov 2024 17:57:59 +0100 Subject: [PATCH 84/88] refactor SpeedBinb * Must fix BookHodai CHAPTERS MESS --- web/src/engine/websites/BookHodai.ts | 14 +- web/src/engine/websites/BookHodai_e2e.ts | 45 ++- web/src/engine/websites/BookLive.ts | 10 +- web/src/engine/websites/BookLive_e2e.ts | 4 +- web/src/engine/websites/Cmoa.ts | 3 +- web/src/engine/websites/ComicBrise.ts | 3 +- web/src/engine/websites/ComicBrise_e2e.ts | 5 +- web/src/engine/websites/ComicMeteor.ts | 3 +- web/src/engine/websites/ComicMeteor_e2e.ts | 2 +- web/src/engine/websites/ComicPolaris.ts | 3 +- web/src/engine/websites/ComicPolaris_e2e.ts | 2 +- web/src/engine/websites/ComicPorta.ts | 5 +- web/src/engine/websites/ComicPorta_e2e.ts | 5 +- web/src/engine/websites/ComicValkyrie.ts | 3 +- web/src/engine/websites/ComicValkyrie_e2e.ts | 5 +- web/src/engine/websites/DigitalMargaret.ts | 3 +- .../engine/websites/DigitalMargaret_e2e.ts | 13 +- web/src/engine/websites/Futabanet.ts | 3 +- web/src/engine/websites/MangaPlanet.ts | 15 +- web/src/engine/websites/MangaPlanet_e2e.ts | 4 +- web/src/engine/websites/MangaPlaza.ts | 10 +- web/src/engine/websites/MichiKusa.ts | 3 +- web/src/engine/websites/MichiKusa_e2e.ts | 2 +- web/src/engine/websites/Ohtabooks.ts | 3 +- web/src/engine/websites/OneTwoThreeHon.ts | 9 +- web/src/engine/websites/OneTwoThreeHon_e2e.ts | 2 +- web/src/engine/websites/SManga.ts | 5 +- web/src/engine/websites/SManga_e2e.ts | 2 +- web/src/engine/websites/TKSuperheroComics.ts | 3 +- .../engine/websites/TKSuperheroComics_e2e.ts | 2 +- web/src/engine/websites/Yanmaga.ts | 10 +- web/src/engine/websites/Yanmaga_e2e.ts | 2 +- web/src/engine/websites/YoMonga.ts | 3 +- web/src/engine/websites/YoMonga_e2e.ts | 2 +- web/src/engine/websites/YoungJump.ts | 11 +- .../engine/websites/decorators/SpeedBinb.ts | 278 ++++-------------- 36 files changed, 187 insertions(+), 310 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index bff30fa00c..45182a7d8c 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -4,12 +4,14 @@ import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchHTML } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; + function MangaLabelExtractor(element: HTMLElement): string { return element.textContent.split('>').pop().trim() || element.textContent.trim(); } -@Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'section.breadcrumb div.bread-text', MangaLabelExtractor) -@SpeedBinb.PagesSinglePageAjaxv016130() +@Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'ol.c-breadcrumb li:last-of-type a, div.p-book-overview__detail h2.p-book-overview__detail-bookname', MangaLabelExtractor) +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -37,16 +39,16 @@ export default class extends DecoratableMangaScraper { //get first "chapter" (book) details const bookdetails = dom.querySelector('section.p-book-overview'); - let title = bookdetails.querySelector('.p-book-overview__detail-volnumber').textContent.trim(); + let title = (bookdetails.querySelector('span.p-book-overview__detail-volnumber') ?? bookdetails.querySelector('h2.p-book-overview__detail-vol')).textContent.replaceAll('\n', '').trim(); title = title.replace(manga.Title, '').trim() != '' ? title.replace(manga.Title, '').trim() : title; const chapterlinkNode = bookdetails.querySelector('a[href*="viewer"'); - chapters.push(new Chapter(this, manga, chapterlinkNode.pathname + chapterlinkNode.search, title)); + if (chapterlinkNode) chapters.push(new Chapter(this, manga, chapterlinkNode.pathname + chapterlinkNode.search, title)); const chaptersNodes = [...dom.querySelectorAll('div.p-book-backnumber-series__item')]; for (const chapter of chaptersNodes) { - const title = chapter.querySelector('.p-book-backnumber-series__volnumber').textContent.trim(); + const title = (chapter.querySelector('.p-book-backnumber-series__volnumber') ?? chapter.querySelector('.p-book-backnumber-series__book-nm')).textContent.trim(); const link = chapter.querySelector('a[href*="viewer"]'); - chapters.push(new Chapter(this, manga, link.pathname + link.search, title.replace(manga.Title, ''))); + chapters.push(new Chapter(this, manga, link.pathname + link.search, title.replace(manga.Title, '').trim())); } return chapters.distinct(); } diff --git a/web/src/engine/websites/BookHodai_e2e.ts b/web/src/engine/websites/BookHodai_e2e.ts index 2e3ca1802f..cc23a18850 100644 --- a/web/src/engine/websites/BookHodai_e2e.ts +++ b/web/src/engine/websites/BookHodai_e2e.ts @@ -1,27 +1,52 @@ import { TestFixture } from '../../../test/WebsitesFixture'; -const config = { +new TestFixture({ plugin: { id: 'bookhodai', title: 'BookHodai' }, container: { - url: 'https://bookhodai.jp/manga/backnumber/49775', - id: '/manga/backnumber/49775', - title: '色欲の春~秘めた色香は筆先に宿る~', + url: 'https://bookhodai.jp/magazine/backnumber/1029551', + id: '/magazine/backnumber/1029551', + title: 'comicグラスト', timeout: 15000 }, child: { - id: '/viewer?book_id=3000071024&branch_no=01&book_type=4', - title: '1 ~ 24', + id: '/viewer?book_id=2000035407&branch_no=01&book_type=3', + title: 'vol.85', timeout: 20000 }, entry: { index: 0, - size: 2_198_237, - type: 'image/png' + size: 3_984_399, + type: 'image/png', + timeout: 30000 + } -}; +}).AssertWebsite(); + +new TestFixture({ + plugin: { + id: 'bookhodai', + title: 'BookHodai' + }, + container: { + url: 'https://bookhodai.jp/manga/backnumber/62789', + id: '/manga/backnumber/62789', + title: '風光る', + timeout: 15000 -new TestFixture(config).AssertWebsite(); \ No newline at end of file + }, + child: { + id: '/viewer?book_id=3000099022&branch_no=01&book_type=4', + title: '1 ~ 44', + timeout: 20000 + }, + entry: { + index: 0, + size: 4_011_228, + type: 'image/png', + timeout: 30000 + } +}).AssertWebsite(); \ No newline at end of file diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index fa90f91f96..5d050feaeb 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -3,16 +3,18 @@ import icon from './BookLive.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { SBVersion } from './decorators/SpeedBinb'; function ChapterExtractor(anchor: HTMLAnchorElement) { - const id = '/bviewer/s/?cid=' + anchor.dataset.title + '_' + anchor.dataset.vol; - const title = anchor.closest('.series_list_detail').querySelector('a[class*=sl-title]').text.trim(); - return { id, title }; + return { + id: '/bviewer/s/?cid=' + anchor.dataset.title + '_' + anchor.dataset.vol, + title: anchor.closest('.series_list_detail').querySelector('a[class*=sl-title]').text.trim() + }; } @Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'li.contents span.book_title') @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#slide_up_top li.item div.buttons a.bl-bviewer[data-title][data-vol]', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxv016130() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/BookLive_e2e.ts b/web/src/engine/websites/BookLive_e2e.ts index 6ea8cc1afc..0f6e9b7305 100644 --- a/web/src/engine/websites/BookLive_e2e.ts +++ b/web/src/engine/websites/BookLive_e2e.ts @@ -12,11 +12,11 @@ const config: Config = { }, child: { id: '/bviewer/s/?cid=20063601_001', - title: '001' + title: '1' }, entry: { index: 0, - size: 2_218_525, + size: 2_219_447, type: 'image/png' } }; diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 24e48a7d2f..2cb9997c07 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -4,9 +4,10 @@ import { Chapter, DecoratableMangaScraper, type MangaPlugin, type Manga } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjaxv016452() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016452) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index a13fdb8c1a..4adc5de75d 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -4,10 +4,11 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; @Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') @Common.MangasSinglePageCSS('/titlelist', '.list-works a') -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicBrise_e2e.ts b/web/src/engine/websites/ComicBrise_e2e.ts index a7f48ef5ed..8326c107bb 100644 --- a/web/src/engine/websites/ComicBrise_e2e.ts +++ b/web/src/engine/websites/ComicBrise_e2e.ts @@ -16,8 +16,9 @@ const config: Config = { }, entry: { index: 0, - size: 4_606_656, - type: 'image/png' + size: 4_607_990, + type: 'image/png', + timeout: 10000 } }; diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index cf53b47e3d..63fa6eaf6e 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -14,7 +15,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicMeteor_e2e.ts b/web/src/engine/websites/ComicMeteor_e2e.ts index a85fa49985..1eda5d0f46 100644 --- a/web/src/engine/websites/ComicMeteor_e2e.ts +++ b/web/src/engine/websites/ComicMeteor_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 3_858_581, + size: 3_860_271, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 352997f63f..1d276ab9e0 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -14,7 +15,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPolaris_e2e.ts b/web/src/engine/websites/ComicPolaris_e2e.ts index 0a9dd1ec12..1bd425c9cc 100644 --- a/web/src/engine/websites/ComicPolaris_e2e.ts +++ b/web/src/engine/websites/ComicPolaris_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_864_432, + size: 1_869_995, type: 'image/png' } }; diff --git a/web/src/engine/websites/ComicPorta.ts b/web/src/engine/websites/ComicPorta.ts index f1ebbbb17d..236d0691c4 100644 --- a/web/src/engine/websites/ComicPorta.ts +++ b/web/src/engine/websites/ComicPorta.ts @@ -1,8 +1,9 @@ import { Tags } from '../Tags'; -import icon from './BookHodai.webp'; +import icon from './ComicPorta.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { SBVersion } from './decorators/SpeedBinb'; function ChapterExtractor(element: HTMLElement) { return { @@ -14,7 +15,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/series\/\d+\/$/, 'div#breadcrumb li:last-of-type') @Common.MangasSinglePageCSS('/series/', 'div.series-list ul li h3.title a') @Common.ChaptersSinglePageCSS('ul.episode-list li.episode div.inner div.wrap p.episode-btn', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/ComicPorta_e2e.ts b/web/src/engine/websites/ComicPorta_e2e.ts index 54f941c380..fbf2014cf3 100644 --- a/web/src/engine/websites/ComicPorta_e2e.ts +++ b/web/src/engine/websites/ComicPorta_e2e.ts @@ -12,12 +12,13 @@ const config = { }, child: { id: '/p_data/moth001/', - title: '第1話「モスとの出会い」' + title: '1話「モスとの出会い」' }, entry: { index: 0, size: 1_320_774, - type: 'image/png' + type: 'image/png', + timeout: 20000 } }; diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index 3ff7e8cabd..a619b24261 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -4,6 +4,7 @@ import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/M import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { @@ -20,7 +21,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicValkyrie_e2e.ts b/web/src/engine/websites/ComicValkyrie_e2e.ts index 188e0faa91..64da6c3a1a 100644 --- a/web/src/engine/websites/ComicValkyrie_e2e.ts +++ b/web/src/engine/websites/ComicValkyrie_e2e.ts @@ -16,8 +16,9 @@ const config: Config = { }, entry: { index: 0, - size: 1_249_371, - type: 'image/png' + size: 1_249_355, + type: 'image/png', + timeout: 20000 } }; diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index 30d1ac0ea2..ea02a0046a 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -3,6 +3,7 @@ import icon from './DigitalMargaret.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -20,7 +21,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') @Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/DigitalMargaret_e2e.ts b/web/src/engine/websites/DigitalMargaret_e2e.ts index f4d8e57c68..60f6ebe01c 100644 --- a/web/src/engine/websites/DigitalMargaret_e2e.ts +++ b/web/src/engine/websites/DigitalMargaret_e2e.ts @@ -6,18 +6,19 @@ const config: Config = { title: 'デジタルマーガレット (Digital Margaret)' }, container: { - url: 'https://digitalmargaret.jp/detail/seijyokankin/', - id: '/detail/seijyokankin/', - title: '私、聖女。いま、監禁されているの' + url: 'https://digitalmargaret.jp/detail/dansou/', + id: '/detail/dansou/', + title: '策士な女装王子は男装令嬢とのいちゃラブをご所望です' }, child: { - id: '/contents/seijyokankin/231001_1-17f812664eb968b5aab01e76f7c2a6335/', + id: '/contents/dansou/241101_1-1bd1f5e685898bb58781b42ad6094eb75/', title: '第1-1話' }, entry: { index: 0, - size: 1_317_928, - type: 'image/png' + size: 1_570_077, + type: 'image/png', + timeout: 20000 } }; diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index f2c5007842..b6400416f6 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -5,6 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; import type { Priority } from '../taskpool/DeferredTask'; +import { SBVersion } from './decorators/SpeedBinb'; @Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'ol.breadcrumb li:last-of-type') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') @@ -32,7 +33,7 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { //Not sure if needed anymore let pages: Page[] = await Common.FetchPagesSinglePageCSS.call(this, chapter, 'div.works_tateyomi__img img'); pages = pages?.map(page => new Page(this, chapter, page.Link, { useCommon: true })); - return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); + return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjax.call(this, chapter, SBVersion.v016130); } public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { //Not sure if needed anymore diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 6561749534..9f87edbd9c 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -4,16 +4,18 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchWindowScript } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { - const id = element.querySelector('a').pathname; - const title = element.querySelector('h3').innerText.trim(); - return {id, title}; + return { + id: element.querySelector('a').pathname, + title: element.querySelector('h3').innerText.trim() + }; } @Common.MangaCSS(/^{origin}\/comic\/[^/]+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -52,10 +54,5 @@ export default class extends DecoratableMangaScraper { } return chapters; } - /* - public override async FetchPages(chapter: Chapter): Promise { - await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 10000);//set necessary cookies - return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); - }*/ } \ No newline at end of file diff --git a/web/src/engine/websites/MangaPlanet_e2e.ts b/web/src/engine/websites/MangaPlanet_e2e.ts index 64849177b2..d00d08331c 100644 --- a/web/src/engine/websites/MangaPlanet_e2e.ts +++ b/web/src/engine/websites/MangaPlanet_e2e.ts @@ -11,12 +11,12 @@ const config: Config = { title: 'Concerned About My Virginity: I Wanna Give It to My Boss!', }, child: { - id: '/reader?cid=64f300af38575&sk=1', + id: '/reader?cid=64f300af38575', title: 'Volume 1 - Free Preview' }, entry: { index: 0, - size: 1_709_465, + size: 1_709_506, type: 'image/png' } }; diff --git a/web/src/engine/websites/MangaPlaza.ts b/web/src/engine/websites/MangaPlaza.ts index c39b624376..6b5f816563 100644 --- a/web/src/engine/websites/MangaPlaza.ts +++ b/web/src/engine/websites/MangaPlaza.ts @@ -1,9 +1,10 @@ import { Tags } from '../Tags'; import icon from './MangaPlaza.webp'; -import { Chapter, DecoratableMangaScraper, type Page, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; type APIChapterResult = { data: { @@ -13,6 +14,7 @@ type APIChapterResult = { } @Common.MangaCSS(/^{origin}\/title\/\d+\/$/, 'div.mainTitle h1.titleTxt') +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -63,10 +65,4 @@ export default class extends DecoratableMangaScraper { return chapters.distinct(); } - - public override async FetchPages(chapter: Chapter): Promise { - await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 3000);//set necessary cookies - return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/MichiKusa.ts b/web/src/engine/websites/MichiKusa.ts index 3f7f7cf134..4267f9a90e 100644 --- a/web/src/engine/websites/MichiKusa.ts +++ b/web/src/engine/websites/MichiKusa.ts @@ -3,6 +3,7 @@ import icon from './MichiKusa.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaInfoExtractor(element: HTMLElement) { return { @@ -20,7 +21,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/product\/[^/]+$/, 'header.entry-header h1.page-title') @Common.MangasMultiPageCSS('/product/page/{page}', 'div.entry-content', 1, 1, 0, MangaInfoExtractor) @Common.ChaptersSinglePageCSS('div.released_episodes div.items div.item a', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/MichiKusa_e2e.ts b/web/src/engine/websites/MichiKusa_e2e.ts index fd0d6937c7..c559e52410 100644 --- a/web/src/engine/websites/MichiKusa_e2e.ts +++ b/web/src/engine/websites/MichiKusa_e2e.ts @@ -16,7 +16,7 @@ const config = { }, entry: { index: 0, - size: 2_241_089, + size: 2_245_849, type: 'image/png' } }; diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index 39e0ac2938..cfbfba3524 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../prov import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -29,7 +30,7 @@ export default class extends DecoratableMangaScraper { //find real reader url to send to SpeedBinb, since redirection is done by Javascript const [ data ] = await FetchCSS(new Request(chapter.Identifier), 'body'); const reallink = data.innerHTML.match(/location.href='(.*)'/)[1]; - return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title)); + return SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title), SBVersion.v016130); } public override async FetchChapters(manga: Manga): Promise { diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index 8bec94d36b..d2e15b51db 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { return { @@ -13,7 +14,7 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -25,6 +26,10 @@ export default class extends DecoratableMangaScraper { return icon; } + public override async Initialize(): Promise { + //do nothing, as https://www.123hon.com fails to load but https://www.123hon.com/nova and https://www.123hon.com/polca works + } + public override async FetchMangas(provider: MangaPlugin): Promise { const mangalist = []; for (const path of ['/polca/web-comic/', '/nova/web-comic']) { @@ -37,7 +42,7 @@ export default class extends DecoratableMangaScraper { public override async FetchChapters(manga: Manga): Promise { const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div.read-episode li'); - const chapterlist : Chapter[] = data.map(element => { + const chapterlist: Chapter[] = data.map(element => { if (element.querySelector('a')) { // otherwise chapter not available return new Chapter(this, manga, new URL(element.querySelector('a').pathname.replace(/index.html$/, ''), this.URI).pathname, element.innerText.match(/\s*(.*?)\s+/)[1]); } diff --git a/web/src/engine/websites/OneTwoThreeHon_e2e.ts b/web/src/engine/websites/OneTwoThreeHon_e2e.ts index 62d57ae4e5..dc5f4d0c83 100644 --- a/web/src/engine/websites/OneTwoThreeHon_e2e.ts +++ b/web/src/engine/websites/OneTwoThreeHon_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 1_468_883, + size: 1_468_880, type: 'image/png' } }; diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index 9bd7bd917d..ef10269743 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type MangaPlugin, Manga } from '../pr import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchWindowScript } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; type SSD = { datas?: [{ @@ -22,7 +23,7 @@ type SSD = { } @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjaxv016130() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { @@ -47,7 +48,7 @@ export default class extends DecoratableMangaScraper { return item_datas.map(chapter => new Chapter(this, manga, `/reader/main.php?cid=${this.IsbnToCid(chapter.isbn)}`, chapter.item_name.replace(manga.Title, '').trim().replace(/^//, '').trim())); } - IsbnToCid(isbn: string): string { + private IsbnToCid(isbn: string): string { return isbn.replaceAll('-', ''); } } \ No newline at end of file diff --git a/web/src/engine/websites/SManga_e2e.ts b/web/src/engine/websites/SManga_e2e.ts index 7b228599b3..1ad5761a24 100644 --- a/web/src/engine/websites/SManga_e2e.ts +++ b/web/src/engine/websites/SManga_e2e.ts @@ -17,7 +17,7 @@ const config = { }, entry: { index: 0, - size: 2_610_174, + size: 2_613_081, type: 'image/png' } }; diff --git a/web/src/engine/websites/TKSuperheroComics.ts b/web/src/engine/websites/TKSuperheroComics.ts index 7f6123ac28..07b94fdfd6 100644 --- a/web/src/engine/websites/TKSuperheroComics.ts +++ b/web/src/engine/websites/TKSuperheroComics.ts @@ -4,6 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS} from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { id: anchor.pathname, @@ -13,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/{origin}\/rensai\/[^/]+\/$/, 'div.manga-overview-top-wrapper h2.manga-heading') @Common.MangasSinglePageCSS('/rensai', 'li.rensai-episode-list a', MangaExtractor) -@SpeedBinb.PagesSinglePageAjaxV016061() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/TKSuperheroComics_e2e.ts b/web/src/engine/websites/TKSuperheroComics_e2e.ts index 29fe09eb30..dee1e92c55 100644 --- a/web/src/engine/websites/TKSuperheroComics_e2e.ts +++ b/web/src/engine/websites/TKSuperheroComics_e2e.ts @@ -16,7 +16,7 @@ const config = { }, entry: { index: 0, - size: 1_867_196, + size: 1_867_269, type: 'image/png' } }; diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index d188620b2d..a647125a26 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -1,9 +1,9 @@ import { Tags } from '../Tags'; import icon from './Yanmaga.webp'; -import { type Chapter, DecoratableMangaScraper, type Page } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchWindowScript } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -34,6 +34,7 @@ const chapterScript = ` @Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') @Common.MangasSinglePageCSS('/comics', 'a.ga-comics-book-item', MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 200) +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -44,9 +45,4 @@ export default class extends DecoratableMangaScraper { return icon; } - public override async FetchPages(chapter: Chapter): Promise { - await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI), { headers: { Referer: this.URI.origin } }), 'true', 3000);//set necessary cookies - return SpeedBinb.FetchPagesSinglePageAjaxv016130.call(this, chapter); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/Yanmaga_e2e.ts b/web/src/engine/websites/Yanmaga_e2e.ts index d19c23d2ba..e732d1016b 100644 --- a/web/src/engine/websites/Yanmaga_e2e.ts +++ b/web/src/engine/websites/Yanmaga_e2e.ts @@ -16,7 +16,7 @@ const config: Config = { }, entry: { index: 0, - size: 2_088_299, + size: 2_088_305, type: 'image/png' } }; diff --git a/web/src/engine/websites/YoMonga.ts b/web/src/engine/websites/YoMonga.ts index 0eeb8d3ac8..6a4c70623e 100644 --- a/web/src/engine/websites/YoMonga.ts +++ b/web/src/engine/websites/YoMonga.ts @@ -3,6 +3,7 @@ import icon from './YoMonga.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; +import { SBVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { @@ -22,7 +23,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/titles\/\d+\//, 'div.intr-title') @Common.MangasMultiPageCSS('/titles/?page_num={page}', 'div.book-box4', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('div.episode-list', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjaxv016130() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/YoMonga_e2e.ts b/web/src/engine/websites/YoMonga_e2e.ts index 1f5db6e0b3..d61938dad7 100644 --- a/web/src/engine/websites/YoMonga_e2e.ts +++ b/web/src/engine/websites/YoMonga_e2e.ts @@ -12,7 +12,7 @@ const config = { }, child: { id: '/titles/306/?episode=1', - title: 'Chapter.1', + title: 'Chapter.1_1巻', timeout: 20000 }, entry: { diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index 11c38abf56..c5120e7c4d 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -1,9 +1,10 @@ import { Tags } from '../Tags'; import icon from './YoungJump.webp'; -import { DecoratableMangaScraper, Manga, type Page, type MangaPlugin, type Chapter } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; +import { SBVersion } from './decorators/SpeedBinb'; type APIMagazine = { url: string, @@ -12,7 +13,7 @@ type APIMagazine = { } @Common.ChaptersUniqueFromManga() -//@SpeedBinb.PagesSinglePageAjaxv016201() +@SpeedBinb.PagesSinglePageAjax(SBVersion.v016201, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -39,10 +40,4 @@ export default class extends DecoratableMangaScraper { const data = await FetchJSON(new Request(new URL('/yj-rest-apis/getBookInfo.php', this.URI))); return data.map(magazine => new Manga(this, provider, magazine.url, `${magazine.issue} - ${magazine.number}`.trim())); } - - public override async FetchPages(chapter: Chapter): Promise { - await FetchWindowScript(new Request(new URL(chapter.Identifier, this.URI)), 'true', 2000); //set cookies - return SpeedBinb.FetchPagesSinglePageAjaxv016201.call(this, chapter); - } - } \ No newline at end of file diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index fae81f35a9..ef7ed2be68 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -11,7 +11,7 @@ type ViewerData = { type RequestData = { cid: string, - sharingKey :string, + sharingKey: string, dmytime, u0: string, u1: string, @@ -33,25 +33,17 @@ type ContentConfiguration = { ContentDate: string } -type Paramsv016452 = { - cid: string, - u0: string, - u1: string, - sharingKey: string -} - type JSONImageData = { resources: { i: { src: string } } - views: PageViewv016061[] -} -type PageViewv016061 = { - coords: string[], - width: number, - height: number + views: { + coords: string[], + width: number, + height: number + }[] } type PageViewv016130 = { @@ -98,6 +90,8 @@ const JsonFetchScript = ` }); `; +export enum SBVersion { v016061, v016452, v016201, v016130 }; + function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); baseURI.pathname = baseURI.pathname.replaceAll(/\/\/+/g, '/'); @@ -131,8 +125,8 @@ async function GetViewerData(this: MangaScraper, chapter: Chapter): Promise{ - let cid = viewerUrl.searchParams.get('cid') || sbHtmlElement.dataset['ptbinbCid']; +async function CreatePtBinbRequestData(viewerUrl: URL, sbHtmlElement: HTMLElement): Promise { + let cid = viewerUrl.searchParams.get('cid') ?? sbHtmlElement.dataset['ptbinbCid']; //in case cid is not in url and not in html, try to get it from page redirected by Javascript/ Meta element if (!cid) { @@ -142,7 +136,7 @@ async function CreatePtBinbRequestData(viewerUrl: URL, sbHtmlElement: HTMLElemen const sharingKey = _tt(cid); const uri = getSanitizedURL(viewerUrl.href, sbHtmlElement.dataset.ptbinb); - const dmytime = String(Date.now()); + const dmytime = Date.now().toString(); uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', dmytime); uri.searchParams.set('k', sharingKey); @@ -165,249 +159,97 @@ async function CreatePtBinbRequestData(viewerUrl: URL, sbHtmlElement: HTMLElemen ******** Page List Extraction Methods ******** **********************************************/ -/** - * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer when chapter JSON got div[data-ptimg$="ptimg.json"] - */ -export function PagesSinglePageAjaxV016061() { - return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - Common.ThrowOnUnsupportedDecoratorContext(context); - - return class extends ctor { - public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageAjaxV016061.call(this, chapter); - } - }; - }; -} - -/** - * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. - * Supposed to be used when chapter JSON got div[data-ptimg$="ptimg.json"] and each one is a json to a page. - * 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 FetchPagesSinglePageAjaxV016061(this: MangaScraper, chapter: Chapter): Promise { - const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - const [...imageConfigurations] = SBHtmlElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); - return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); -} - -/** - * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. For version v016130 - */ -export function PagesSinglePageAjaxv016130() { - return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - Common.ThrowOnUnsupportedDecoratorContext(context); - - return class extends ctor { - public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageAjaxv016130.call(this, chapter); - } - }; - }; -} - -/** - * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. - * 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 FetchPagesSinglePageAjaxv016130(this: MangaScraper, chapter: Chapter): Promise { - const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - const { request, sharingKey } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); - const config = await FetchJSON(request); - return await getPageLinks_v016130.call(this, config.items[0], sharingKey, chapter); - -} - -/** - * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. - */ -export function PagesSinglePageAjaxv016452() { - return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - Common.ThrowOnUnsupportedDecoratorContext(context); - - return class extends ctor { - public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageAjaxv016452.call(this, chapter); - } - }; - }; -} - /** * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. * The pages are extracted from the composed url based on the `Identifier` of the {@link chapter} and the `URI` of the website. * @param this - A reference to the {@link MangaScraper} instance which will be used as context for this method * @param chapter - A reference to the {@link Chapter} which shall be assigned as parent for the extracted pages + * @param version - SpeedBinb version used by the website + * @param needCookies - Use browser window to perform first JSON request to get access cookies properly */ -export async function FetchPagesSinglePageAjaxv016452(this: MangaScraper, chapter: Chapter): Promise { +export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, version: SBVersion, needCookies = false): Promise { const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - const { request, sharingKey, cid, u0, u1 } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); - const config = await FetchJSON(request); - const params: Paramsv016452 = { cid, sharingKey, u0, u1 }; - return await getPageLinks_v016452.call(this, config.items[0], params, chapter); + if (version == SBVersion.v016061) { + //ComicBrise, ComicMeteor, ComicPorta, ComicValKyrie, DigitalMargaret, MichiKusa, OneTwoThreeHon, TKSuperheroComics + const [...imageConfigurations] = SBHtmlElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); + return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); + } + const params = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); + const { items } = !needCookies ? await FetchJSON(params.request) : await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', params.request.url), 2000); + return getPagesLinks.call(this, items[0], params, chapter, version); } - /** * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. + * @param version - SpeedBinb version used by the website + * @param needCookies - Use browser window to perform first JSON request to get access cookies properly */ -export function PagesSinglePageAjaxv016201() { - return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { - Common.ThrowOnUnsupportedDecoratorContext(context); - - return class extends ctor { - public async FetchPages(this: MangaScraper, chapter: Chapter): Promise { - return FetchPagesSinglePageAjaxv016201.call(this, chapter); - } - }; - }; -} - -/** - * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. - * 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 FetchPagesSinglePageAjaxv016201(this: MangaScraper, chapter: Chapter): Promise { - const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - const { request, sharingKey, u1 } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); - const config = await FetchJSON(request); - return await getPageLinks_v016201.call(this, config.items[0], sharingKey, u1, chapter); -} - -/** - * An extension method for extracting all pages for the given {@link chapter} using the given CSS {@link query}. - * 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 { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - const { request, sharingKey } = await CreatePtBinbRequestData(viewerUrl, SBHtmlElement); - const config = await FetchWindowScript(new Request(viewerUrl), JsonFetchScript.replace('{URI}', request.url), 2000); - return await getPageLinks_v016130.call(this, config.items[0], sharingKey, chapter); -} -/** - * A class decorator that adds the ability to extract all pages for a given chapter from a website using SpeedBinb Viewer. - */ -export function PagesSinglePageAjax() { +export function PagesSinglePageAjax(version: SBVersion, needCookies = false) { 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); + return FetchPagesSinglePageAjax.call(this, chapter, version, needCookies); } }; }; } - -async function getPageLinks_v016452(this: MangaScraper, configuration: ContentConfiguration, params: Paramsv016452, chapter: Chapter): Promise { - configuration.ctbl = _pt(params.cid, params.sharingKey, configuration.ctbl as string); - configuration.ptbl = _pt(params.cid, params.sharingKey, configuration.ptbl as string); - try { - configuration.ServerType = parseInt(configuration.ServerType as string); - } catch { } - if (configuration.ServerType === 0) {//CMOA - const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); - uri.searchParams.set('cid', params.cid); - uri.searchParams.set('p', configuration.p); - uri.searchParams.set('q', '1'); - uri.searchParams.set('vm', String(configuration.ViewMode)); - uri.searchParams.set('dmytime', configuration.ContentDate); - uri.searchParams.set('u0', params.u0); - uri.searchParams.set('u1', params.u1); - return await fetchSBC.call(this, uri, configuration, chapter); - } - return Promise.reject(new Error('Content server type not supported!')); -} - -async function getPageLinks_v016201(this: MangaScraper, configuration: ContentConfiguration, sharingKey: string, u: string, chapter: Chapter): Promise { - const cid = configuration.ContentID; - configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); - configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); - try { - configuration.ServerType = parseInt(configuration.ServerType as string); - } catch { } - - if (configuration.ServerType === 2) { - const uri = getSanitizedURL(configuration.ContentsServer, 'content'); - uri.searchParams.set('dmytime', configuration.ContentDate); - uri.searchParams.set('u1', u); - const data: SBCDATA = await FetchJSON(new Request(uri)); - const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); - }); - return pageLinks; - } - return Promise.reject(new Error('Content server type not supported!')); -} - -async function getPageLinks_v016130(this: MangaScraper, configuration: ContentConfiguration, sharingKey: string, chapter: Chapter): Promise { - const cid = configuration.ContentID; - configuration.ctbl = _pt(cid, sharingKey, configuration.ctbl as string); - configuration.ptbl = _pt(cid, sharingKey, configuration.ptbl as string); +async function getPagesLinks(this: MangaScraper, configuration: ContentConfiguration, params: RequestData, chapter: Chapter, version: SBVersion): Promise { + const cid = version === SBVersion.v016452 ? params.cid : configuration.ContentID; + configuration.ctbl = _pt(cid, params.sharingKey, configuration.ctbl as string); + configuration.ptbl = _pt(cid, params.sharingKey, configuration.ptbl as string); try { configuration.ServerType = parseInt(configuration.ServerType as string); } catch { } switch (configuration.ServerType as number) { - case 0: { //Booklive + case 0: { //v016130 Booklive , v016452 CMOA const uri = getSanitizedURL(configuration.ContentsServer, 'sbcGetCntnt.php'); - uri.searchParams.set('cid', configuration.ContentID); + uri.searchParams.set('cid', cid); uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('p', configuration.p); - uri.searchParams.set('vm', String(configuration.ViewMode)); - return await fetchSBC.call(this, uri, configuration, chapter); + uri.searchParams.set('vm', configuration.ViewMode.toString()); + if (version === SBVersion.v016452) { //CMOA + uri.searchParams.set('q', '1'); + uri.searchParams.set('u0', params.u0); + uri.searchParams.set('u1', params.u1); + } + return await ExtractPages.call(this, uri, '/sbcGetCntnt.php', '/sbcGetImg.php', configuration, chapter, true); } - case 1: {//Futabanet, Getsuaku, BookHodai + + case 1: {//v016130 Futabanet, BookHodai, Booklive, OhtaBooks, SManga const uri = getSanitizedURL(configuration.ContentsServer, 'content.js'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - const response = await Fetch(new Request(uri)); - const data = await response.text(); - const jsonObj: SBCDATA = JSON.parse(data.slice(16, -1)); - const dom = new DOMParser().parseFromString(jsonObj.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - let src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - if (!src.startsWith('/')) src = '/' + src; - return new Page(this, chapter, new URL(uri.href.replace('/content.js', src + '/M_H.jpg'))); - }); - return pageLinks; + return await ExtractPages.call(this, uri, '/content.js', '{src}/M_H.jpg', configuration, chapter); } - case 2: {//MangaPlanet, MangaPlaza + case 2: {//v016130 MangaPlanet, MangaPlaza, Yanmaga, Yomonga const uri = getSanitizedURL(configuration.ContentsServer, 'content'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - const data = await FetchJSON(new Request(uri, { headers: { Referer: this.URI.href }})); - const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); - const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - const src = img.getAttribute('src'); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(this, chapter, new URL(uri.href.replace('/content', '/img/' + src))); - }); - return pageLinks; + if (version === SBVersion.v016201) uri.searchParams.set('u1', params.u1); //YOUNGJUMP + return await ExtractPages.call(this, uri, '/content', '/img/{src}', configuration, chapter); } } return Promise.reject(new Error('Content server type not supported!')); } -async function fetchSBC(this: MangaScraper, uri: URL, configuration: ContentConfiguration, chapter: Chapter) { - const data = await FetchJSON(new Request(uri)); - const dom = new DOMParser().parseFromString(data.ttx, 'text/html'); +async function ExtractPages(uri: URL, replaceFrom : string, replaceto: string, configuration: ContentConfiguration, chapter: Chapter, setSrc = false): Promise { + const response = await Fetch(new Request(uri, { headers: { Referer: this.URI.href } })); + const data = await response.text(); + const { ttx }: SBCDATA = data.startsWith('DataGet_Content(') ? JSON.parse(data.slice(16, -1)) : JSON.parse(data); + const dom = new DOMParser().parseFromString(ttx, 'text/html'); const pageLinks = [...dom.querySelectorAll('t-case:first-of-type t-img')].map(img => { - const src = img.getAttribute('src'); - uri.searchParams.set('src', src); - uri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); - return new Page(this, chapter, new URL(uri.href.replace('/sbcGetCntnt.php', '/sbcGetImg.php'))); + let src = img.getAttribute('src'); + + const pageUri = new URL(uri); + pageUri.hash = window.btoa(JSON.stringify(lt_001(src, configuration.ctbl as string[], configuration.ptbl as string[]))); + if (setSrc) pageUri.searchParams.set('src', src); + + if (!src.startsWith('/')) src = '/' + src; + pageUri.href = pageUri.href.replace(replaceFrom, replaceto.replace('{src}', src)); + return new Page(this, chapter, pageUri); + }); return pageLinks; } From c979b012a765c6c7d392a3b20169f6c114cbcb73 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Tue, 26 Nov 2024 14:11:06 +0100 Subject: [PATCH 85/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 07aba17b4b..3b959a0c53 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -45,6 +45,8 @@ export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as BomtoonCN } from './BomtoonCN'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -52,6 +54,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -59,6 +62,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -67,11 +71,15 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -106,6 +114,7 @@ export { default as Desu } from './Desu'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; export { default as Digimon } from './Digimon'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -143,6 +152,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -355,6 +365,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -448,6 +460,7 @@ export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; export { default as MiauScan } from './MiauScan'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -488,7 +501,9 @@ export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; export { default as Nyrax } from './Nyrax'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as OnMangaMe } from './OnMangaMe'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; @@ -602,6 +617,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -636,6 +652,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -710,6 +727,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -718,6 +736,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -733,19 +753,13 @@ export { default as ZinMangaNet } from './ZinMangaNet'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -800,9 +814,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as ShinobiScans } from './legacy/ShinobiScans'; export { default as SixMH7 } from './legacy/SixMH7'; @@ -840,6 +852,5 @@ export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as wuqimh } from './legacy/wuqimh'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From cbd3f255726d8bb766510610657740ba94e87ba1 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Dec 2024 11:51:38 +0100 Subject: [PATCH 86/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 9f72c71025..4ac4aece07 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -45,6 +45,8 @@ export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as BomtoonCN } from './BomtoonCN'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -52,6 +54,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -59,6 +62,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -67,11 +71,15 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -108,6 +116,7 @@ export { default as DEXHentai } from './DEXHentai'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; export { default as Digimon } from './Digimon'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -146,6 +155,7 @@ export { default as FoyScan } from './FoyScan'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; export { default as FRTiretScan } from './FRTiretScan'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -359,6 +369,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -450,6 +462,7 @@ export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; export { default as MiauScan } from './MiauScan'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -490,7 +503,9 @@ export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; export { default as OrigamiOrpheans } from './OrigamiOrpheans'; @@ -603,6 +618,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -636,6 +652,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -709,6 +726,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -717,6 +735,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -732,19 +752,13 @@ export { default as ZinMangaNet } from './ZinMangaNet'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HeavenManga } from './legacy/HeavenManga'; @@ -797,9 +811,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as ShinobiScans } from './legacy/ShinobiScans'; export { default as SixMH7 } from './legacy/SixMH7'; @@ -832,6 +844,5 @@ export { default as WoopRead } from './legacy/WoopRead'; export { default as WordExcerpt } from './legacy/WordExcerpt'; export { default as WordRain } from './legacy/WordRain'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file From e4ce52dd8d9c75c6ec3a4533155dd27ddf0e3466 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Sun, 15 Dec 2024 12:09:44 +0100 Subject: [PATCH 87/88] reflect Common changes --- web/src/engine/websites/BookHodai.ts | 4 +-- web/src/engine/websites/BookLive.ts | 4 +-- web/src/engine/websites/Cmoa.ts | 4 +-- web/src/engine/websites/ComicBrise.ts | 6 ++-- web/src/engine/websites/ComicMeteor.ts | 4 +-- web/src/engine/websites/ComicPolaris.ts | 4 +-- web/src/engine/websites/ComicPorta.ts | 6 ++-- web/src/engine/websites/ComicValkyrie.ts | 8 ++--- web/src/engine/websites/DigitalMargaret.ts | 12 +++---- web/src/engine/websites/Futabanet.ts | 4 +-- web/src/engine/websites/MangaPlanet.ts | 4 +-- web/src/engine/websites/MangaPlaza.ts | 4 +-- web/src/engine/websites/MichiKusa.ts | 4 +-- web/src/engine/websites/Ohtabooks.ts | 10 +++--- web/src/engine/websites/OneTwoThreeHon.ts | 35 ++++++------------- web/src/engine/websites/SManga.ts | 4 +-- web/src/engine/websites/TKSuperheroComics.ts | 6 ++-- web/src/engine/websites/Yanmaga.ts | 6 ++-- web/src/engine/websites/YoMonga.ts | 4 +-- web/src/engine/websites/YoungJump.ts | 4 +-- .../engine/websites/decorators/SpeedBinb.ts | 16 ++++----- 21 files changed, 70 insertions(+), 83 deletions(-) diff --git a/web/src/engine/websites/BookHodai.ts b/web/src/engine/websites/BookHodai.ts index 45182a7d8c..b22a08b77f 100644 --- a/web/src/engine/websites/BookHodai.ts +++ b/web/src/engine/websites/BookHodai.ts @@ -4,14 +4,14 @@ import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchHTML } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaLabelExtractor(element: HTMLElement): string { return element.textContent.split('>').pop().trim() || element.textContent.trim(); } @Common.MangaCSS(/^{origin}\/[^/]+\/backnumber\/\d+$/, 'ol.c-breadcrumb li:last-of-type a, div.p-book-overview__detail h2.p-book-overview__detail-bookname', MangaLabelExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/BookLive.ts b/web/src/engine/websites/BookLive.ts index 5d050feaeb..9719ddd1d4 100644 --- a/web/src/engine/websites/BookLive.ts +++ b/web/src/engine/websites/BookLive.ts @@ -3,7 +3,7 @@ import icon from './BookLive.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function ChapterExtractor(anchor: HTMLAnchorElement) { return { id: '/bviewer/s/?cid=' + anchor.dataset.title + '_' + anchor.dataset.vol, @@ -14,7 +14,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/product\/index\/title_id\/\d+\/vol_no\/\d+$/, 'li.contents span.book_title') @Common.MangasNotSupported() @Common.ChaptersSinglePageCSS('div#slide_up_top li.item div.buttons a.bl-bviewer[data-title][data-vol]', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Cmoa.ts b/web/src/engine/websites/Cmoa.ts index 2cb9997c07..1bdb17715e 100644 --- a/web/src/engine/websites/Cmoa.ts +++ b/web/src/engine/websites/Cmoa.ts @@ -4,10 +4,10 @@ import { Chapter, DecoratableMangaScraper, type MangaPlugin, type Manga } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016452) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016452) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicBrise.ts b/web/src/engine/websites/ComicBrise.ts index 4adc5de75d..ecabdafd4b 100644 --- a/web/src/engine/websites/ComicBrise.ts +++ b/web/src/engine/websites/ComicBrise.ts @@ -4,11 +4,11 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; @Common.MangaCSS(/^{origin}\/contents\/[^/]+\/$/, '.post-title') -@Common.MangasSinglePageCSS('/titlelist', '.list-works a') -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@Common.MangasSinglePagesCSS(['/titlelist'], '.list-works a') +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicMeteor.ts b/web/src/engine/websites/ComicMeteor.ts index 63fa6eaf6e..06df66a412 100644 --- a/web/src/engine/websites/ComicMeteor.ts +++ b/web/src/engine/websites/ComicMeteor.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -15,7 +15,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div.h2ttl_other') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPolaris.ts b/web/src/engine/websites/ComicPolaris.ts index 1d276ab9e0..364ac8d0f5 100644 --- a/web/src/engine/websites/ComicPolaris.ts +++ b/web/src/engine/websites/ComicPolaris.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -15,7 +15,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'div#contents div.h2_area_comic h2.h2ttl_comic') @Common.MangasMultiPageCSS('/wp-admin/admin-ajax.php?action=get_flex_titles_for_toppage&get_num=64&page={page}', 'div.update_work_size div.update_work_info_img a', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/ComicPorta.ts b/web/src/engine/websites/ComicPorta.ts index 236d0691c4..c3f6b7f19b 100644 --- a/web/src/engine/websites/ComicPorta.ts +++ b/web/src/engine/websites/ComicPorta.ts @@ -3,7 +3,7 @@ import icon from './ComicPorta.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function ChapterExtractor(element: HTMLElement) { return { @@ -13,9 +13,9 @@ function ChapterExtractor(element: HTMLElement) { } @Common.MangaCSS(/^{origin}\/series\/\d+\/$/, 'div#breadcrumb li:last-of-type') -@Common.MangasSinglePageCSS('/series/', 'div.series-list ul li h3.title a') +@Common.MangasSinglePagesCSS(['/series/'], 'div.series-list ul li h3.title a') @Common.ChaptersSinglePageCSS('ul.episode-list li.episode div.inner div.wrap p.episode-btn', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/ComicValkyrie.ts b/web/src/engine/websites/ComicValkyrie.ts index a619b24261..774c3d832e 100644 --- a/web/src/engine/websites/ComicValkyrie.ts +++ b/web/src/engine/websites/ComicValkyrie.ts @@ -4,11 +4,11 @@ import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/M import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { - id: new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'), + id: new URL(element.querySelector('a').href).pathname.replace('/new.html', '/'), title: element.querySelector('.title').textContent.replace(/\s*THE COMIC\s*/i, '').trim() }; } @@ -19,9 +19,9 @@ function ChapterExtractor(element: HTMLElement) { }; } -@Common.MangasSinglePageCSS('/list', '.box_wrap .box', MangaExtractor) +@Common.MangasSinglePagesCSS(['/list'], '.box_wrap .box', MangaExtractor) @Common.ChaptersSinglePageCSS('#new_story .title, #back_number .title', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/DigitalMargaret.ts b/web/src/engine/websites/DigitalMargaret.ts index ea02a0046a..d77f1d4978 100644 --- a/web/src/engine/websites/DigitalMargaret.ts +++ b/web/src/engine/websites/DigitalMargaret.ts @@ -3,25 +3,25 @@ import icon from './DigitalMargaret.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { id: anchor.pathname, - title: anchor.querySelector('img').getAttribute('alt').trim() + title: anchor.querySelector('img').getAttribute('alt').trim() }; } function ChapterExtractor(element: HTMLElement) { return { - id: element.querySelector('a').pathname, - title: element.querySelector('p').textContent.trim() + id: element.querySelector('a').pathname, + title: element.querySelector('p').textContent.trim() }; } @Common.MangaCSS(/^{origin}\/detail\/[^/]+\/$/, 'section#product div.content h3') -@Common.MangasSinglePageCSS('/', 'section#serial ul.serial-list li a', MangaExtractor) +@Common.MangasSinglePagesCSS(['/'], 'section#serial ul.serial-list li a', MangaExtractor) @Common.ChaptersSinglePageCSS('section#product div.list div.box div.number', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Futabanet.ts b/web/src/engine/websites/Futabanet.ts index b6400416f6..c05820a695 100644 --- a/web/src/engine/websites/Futabanet.ts +++ b/web/src/engine/websites/Futabanet.ts @@ -5,7 +5,7 @@ import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; import type { Priority } from '../taskpool/DeferredTask'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; @Common.MangaCSS(/^https:\/\/gaugau\.futabane(t|x)\.jp\/list\/work\/[^/]+$/, 'ol.breadcrumb li:last-of-type') @Common.MangasMultiPageCSS('/list/works?page={page}', 'div.works__grid div.list__box h4 a') @@ -33,7 +33,7 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { //Not sure if needed anymore let pages: Page[] = await Common.FetchPagesSinglePageCSS.call(this, chapter, 'div.works_tateyomi__img img'); pages = pages?.map(page => new Page(this, chapter, page.Link, { useCommon: true })); - return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjax.call(this, chapter, SBVersion.v016130); + return pages?.length > 0 ? pages : await SpeedBinb.FetchPagesSinglePageAjax.call(this, chapter, SpeedBindVersion.v016130); } public override async FetchImage(page: Page, priority: Priority, signal: AbortSignal): Promise { //Not sure if needed anymore diff --git a/web/src/engine/websites/MangaPlanet.ts b/web/src/engine/websites/MangaPlanet.ts index 9f87edbd9c..4b7a6e3784 100644 --- a/web/src/engine/websites/MangaPlanet.ts +++ b/web/src/engine/websites/MangaPlanet.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchWindowScript } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { @@ -15,7 +15,7 @@ function MangaExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/comic\/[^/]+$/, '.card-body.book-detail h3') @Common.MangasMultiPageCSS('/browse/title?ttlpage={page}', 'div#Title .row.book-list', 1, 1, 0, MangaExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/MangaPlaza.ts b/web/src/engine/websites/MangaPlaza.ts index 6b5f816563..8ddd605074 100644 --- a/web/src/engine/websites/MangaPlaza.ts +++ b/web/src/engine/websites/MangaPlaza.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from ' import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS, FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; type APIChapterResult = { data: { @@ -14,7 +14,7 @@ type APIChapterResult = { } @Common.MangaCSS(/^{origin}\/title\/\d+\/$/, 'div.mainTitle h1.titleTxt') -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/MichiKusa.ts b/web/src/engine/websites/MichiKusa.ts index 4267f9a90e..7adcb59884 100644 --- a/web/src/engine/websites/MichiKusa.ts +++ b/web/src/engine/websites/MichiKusa.ts @@ -3,7 +3,7 @@ import icon from './MichiKusa.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaInfoExtractor(element: HTMLElement) { return { @@ -21,7 +21,7 @@ function ChapterExtractor(anchor: HTMLAnchorElement) { @Common.MangaCSS(/^{origin}\/product\/[^/]+$/, 'header.entry-header h1.page-title') @Common.MangasMultiPageCSS('/product/page/{page}', 'div.entry-content', 1, 1, 0, MangaInfoExtractor) @Common.ChaptersSinglePageCSS('div.released_episodes div.items div.item a', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Ohtabooks.ts b/web/src/engine/websites/Ohtabooks.ts index cfbfba3524..3526ee982a 100644 --- a/web/src/engine/websites/Ohtabooks.ts +++ b/web/src/engine/websites/Ohtabooks.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga, type Page } from '../prov import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -14,7 +14,7 @@ function MangaExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/^{origin}\/[^/]+\/$/, 'h2.contentTitle') -@Common.MangasSinglePageCSS('/list/', 'div.bnrList ul li a', MangaExtractor) +@Common.MangasSinglePagesCSS(['/list/'], 'div.bnrList ul li a', MangaExtractor) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -29,14 +29,14 @@ export default class extends DecoratableMangaScraper { public override async FetchPages(chapter: Chapter): Promise { //find real reader url to send to SpeedBinb, since redirection is done by Javascript const [ data ] = await FetchCSS(new Request(chapter.Identifier), 'body'); - const reallink = data.innerHTML.match(/location.href='(.*)'/)[1]; - return SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title), SBVersion.v016130); + const reallink = data.innerHTML.match(/location.href='(.*)'/).at(1); + return SpeedBinb.FetchPagesSinglePageAjax.call(this, new Chapter(this, chapter.Parent as Manga, reallink, chapter.Title), SpeedBindVersion.v016130); } public override async FetchChapters(manga: Manga): Promise { const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'a[onClick^="return !openBook("]'); const chapterList = data.map(element => { - const partId = element.getAttribute('onclick').match(/\d+/)[0]; + const partId = element.getAttribute('onclick').match(/\d+/).at(0); const title = element.querySelector('.title') ? element.querySelector('.title').textContent : element.querySelector('btnMini') ? element.querySelector('btnMini').textContent : 'マンガをよむ'; return new Chapter(this, manga, `https://yondemill.jp/contents/${partId}?view=1&u0=1`, title.trim()); }); diff --git a/web/src/engine/websites/OneTwoThreeHon.ts b/web/src/engine/websites/OneTwoThreeHon.ts index d2e15b51db..ccc699da27 100644 --- a/web/src/engine/websites/OneTwoThreeHon.ts +++ b/web/src/engine/websites/OneTwoThreeHon.ts @@ -1,10 +1,9 @@ import { Tags } from '../Tags'; import icon from './OneTwoThreeHon.webp'; -import { Chapter, DecoratableMangaScraper, type Manga, type MangaPlugin } from '../providers/MangaPlugin'; +import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { FetchCSS } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaInfoExtractor(anchor: HTMLAnchorElement) { return { @@ -12,9 +11,17 @@ function MangaInfoExtractor(anchor: HTMLAnchorElement) { title: anchor.pathname.match(/[^/]+\/web-comic\/([^/]+)\//)[1] }; } +function ChapterExtractor(element: HTMLLIElement) { + return { + id: new URL(element.querySelector('a').pathname.replace(/index.html$/, ''), this.URI).pathname, + title: element.innerText.match(/\s*(.*?)\s+/).at(1) + }; +} @Common.MangaCSS(/^{origin}\/[^/]+\/web-comic\/[^/]+\/$/, 'div.title-area h2') -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@Common.MangasSinglePagesCSS(['/polca/web-comic/', '/nova/web-comic/'], 'ul.comic__list > li > a', MangaInfoExtractor) +@Common.ChaptersSinglePageCSS('div.read-episode li:has(a)', ChapterExtractor) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { @@ -29,24 +36,4 @@ export default class extends DecoratableMangaScraper { public override async Initialize(): Promise { //do nothing, as https://www.123hon.com fails to load but https://www.123hon.com/nova and https://www.123hon.com/polca works } - - public override async FetchMangas(provider: MangaPlugin): Promise { - const mangalist = []; - for (const path of ['/polca/web-comic/', '/nova/web-comic']) { - const mangas = await Common.FetchMangasSinglePageCSS.call(this, provider, path, 'ul.comic__list > li > a', MangaInfoExtractor); - mangalist.push(...mangas); - } - return mangalist; - - } - - public override async FetchChapters(manga: Manga): Promise { - const data = await FetchCSS(new Request(new URL(manga.Identifier, this.URI)), 'div.read-episode li'); - const chapterlist: Chapter[] = data.map(element => { - if (element.querySelector('a')) { // otherwise chapter not available - return new Chapter(this, manga, new URL(element.querySelector('a').pathname.replace(/index.html$/, ''), this.URI).pathname, element.innerText.match(/\s*(.*?)\s+/)[1]); - } - }); - return chapterlist.distinct(); - } } \ No newline at end of file diff --git a/web/src/engine/websites/SManga.ts b/web/src/engine/websites/SManga.ts index ef10269743..6824e1200f 100644 --- a/web/src/engine/websites/SManga.ts +++ b/web/src/engine/websites/SManga.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type MangaPlugin, Manga } from '../pr import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchWindowScript } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; type SSD = { datas?: [{ @@ -23,7 +23,7 @@ type SSD = { } @Common.MangasNotSupported() -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/TKSuperheroComics.ts b/web/src/engine/websites/TKSuperheroComics.ts index 07b94fdfd6..9ba8470052 100644 --- a/web/src/engine/websites/TKSuperheroComics.ts +++ b/web/src/engine/websites/TKSuperheroComics.ts @@ -4,7 +4,7 @@ import { Chapter, DecoratableMangaScraper, type Manga } from '../providers/Manga import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchCSS} from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { id: anchor.pathname, @@ -13,8 +13,8 @@ function MangaExtractor(anchor: HTMLAnchorElement) { } @Common.MangaCSS(/{origin}\/rensai\/[^/]+\/$/, 'div.manga-overview-top-wrapper h2.manga-heading') -@Common.MangasSinglePageCSS('/rensai', 'li.rensai-episode-list a', MangaExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016061) +@Common.MangasSinglePagesCSS(['/rensai'], 'li.rensai-episode-list a', MangaExtractor) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016061) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/Yanmaga.ts b/web/src/engine/websites/Yanmaga.ts index a647125a26..63a4495530 100644 --- a/web/src/engine/websites/Yanmaga.ts +++ b/web/src/engine/websites/Yanmaga.ts @@ -3,7 +3,7 @@ import icon from './Yanmaga.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(anchor: HTMLAnchorElement) { return { @@ -32,9 +32,9 @@ const chapterScript = ` `; @Common.MangaCSS(/^{origin}\/comics\/[^/]+$/, 'h1.detail-header-title, h1.detailv2-outline-title') -@Common.MangasSinglePageCSS('/comics', 'a.ga-comics-book-item', MangaExtractor) +@Common.MangasSinglePagesCSS(['/comics'], 'a.ga-comics-book-item', MangaExtractor) @Common.ChaptersSinglePageJS(chapterScript, 200) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130, true) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/YoMonga.ts b/web/src/engine/websites/YoMonga.ts index 6a4c70623e..0e80d7a85f 100644 --- a/web/src/engine/websites/YoMonga.ts +++ b/web/src/engine/websites/YoMonga.ts @@ -3,7 +3,7 @@ import icon from './YoMonga.webp'; import { DecoratableMangaScraper } from '../providers/MangaPlugin'; import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; function MangaExtractor(element: HTMLElement) { return { @@ -23,7 +23,7 @@ function ChapterExtractor(element: HTMLElement) { @Common.MangaCSS(/^{origin}\/titles\/\d+\//, 'div.intr-title') @Common.MangasMultiPageCSS('/titles/?page_num={page}', 'div.book-box4', 1, 1, 0, MangaExtractor) @Common.ChaptersSinglePageCSS('div.episode-list', ChapterExtractor) -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016130) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016130) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { public constructor() { diff --git a/web/src/engine/websites/YoungJump.ts b/web/src/engine/websites/YoungJump.ts index c5120e7c4d..28fe3b675a 100644 --- a/web/src/engine/websites/YoungJump.ts +++ b/web/src/engine/websites/YoungJump.ts @@ -4,7 +4,7 @@ import { DecoratableMangaScraper, Manga, type MangaPlugin } from '../providers/M import * as Common from './decorators/Common'; import * as SpeedBinb from './decorators/SpeedBinb'; import { FetchJSON, FetchWindowScript } from '../platform/FetchProvider'; -import { SBVersion } from './decorators/SpeedBinb'; +import { SpeedBindVersion } from './decorators/SpeedBinb'; type APIMagazine = { url: string, @@ -13,7 +13,7 @@ type APIMagazine = { } @Common.ChaptersUniqueFromManga() -@SpeedBinb.PagesSinglePageAjax(SBVersion.v016201, true) +@SpeedBinb.PagesSinglePageAjax(SpeedBindVersion.v016201, true) @SpeedBinb.ImageAjax() export default class extends DecoratableMangaScraper { diff --git a/web/src/engine/websites/decorators/SpeedBinb.ts b/web/src/engine/websites/decorators/SpeedBinb.ts index ef7ed2be68..ce020c1e87 100644 --- a/web/src/engine/websites/decorators/SpeedBinb.ts +++ b/web/src/engine/websites/decorators/SpeedBinb.ts @@ -90,7 +90,7 @@ const JsonFetchScript = ` }); `; -export enum SBVersion { v016061, v016452, v016201, v016130 }; +export enum SpeedBindVersion { v016061, v016452, v016201, v016130 }; function getSanitizedURL(base: string, append: string): URL { const baseURI = new URL(append, base + '/'); @@ -167,9 +167,9 @@ async function CreatePtBinbRequestData(viewerUrl: URL, sbHtmlElement: HTMLElemen * @param version - SpeedBinb version used by the website * @param needCookies - Use browser window to perform first JSON request to get access cookies properly */ -export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, version: SBVersion, needCookies = false): Promise { +export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chapter, version: SpeedBindVersion, needCookies = false): Promise { const { viewerUrl, SBHtmlElement } = await GetViewerData.call(this, chapter); - if (version == SBVersion.v016061) { + if (version == SpeedBindVersion.v016061) { //ComicBrise, ComicMeteor, ComicPorta, ComicValKyrie, DigitalMargaret, MichiKusa, OneTwoThreeHon, TKSuperheroComics const [...imageConfigurations] = SBHtmlElement.querySelectorAll('div[data-ptimg$="ptimg.json"]'); return imageConfigurations.map(element => new Page(this, chapter, getSanitizedURL(viewerUrl.href, element.dataset.ptimg))); @@ -185,7 +185,7 @@ export async function FetchPagesSinglePageAjax(this: MangaScraper, chapter: Chap * @param needCookies - Use browser window to perform first JSON request to get access cookies properly */ -export function PagesSinglePageAjax(version: SBVersion, needCookies = false) { +export function PagesSinglePageAjax(version: SpeedBindVersion, needCookies = false) { return function DecorateClass(ctor: T, context?: ClassDecoratorContext): T { Common.ThrowOnUnsupportedDecoratorContext(context); @@ -196,8 +196,8 @@ export function PagesSinglePageAjax(version: SBVersion, needCookies = false) { }; }; } -async function getPagesLinks(this: MangaScraper, configuration: ContentConfiguration, params: RequestData, chapter: Chapter, version: SBVersion): Promise { - const cid = version === SBVersion.v016452 ? params.cid : configuration.ContentID; +async function getPagesLinks(this: MangaScraper, configuration: ContentConfiguration, params: RequestData, chapter: Chapter, version: SpeedBindVersion): Promise { + const cid = version === SpeedBindVersion.v016452 ? params.cid : configuration.ContentID; configuration.ctbl = _pt(cid, params.sharingKey, configuration.ctbl as string); configuration.ptbl = _pt(cid, params.sharingKey, configuration.ptbl as string); try { @@ -211,7 +211,7 @@ async function getPagesLinks(this: MangaScraper, configuration: ContentConfigura uri.searchParams.set('dmytime', configuration.ContentDate); uri.searchParams.set('p', configuration.p); uri.searchParams.set('vm', configuration.ViewMode.toString()); - if (version === SBVersion.v016452) { //CMOA + if (version === SpeedBindVersion.v016452) { //CMOA uri.searchParams.set('q', '1'); uri.searchParams.set('u0', params.u0); uri.searchParams.set('u1', params.u1); @@ -227,7 +227,7 @@ async function getPagesLinks(this: MangaScraper, configuration: ContentConfigura case 2: {//v016130 MangaPlanet, MangaPlaza, Yanmaga, Yomonga const uri = getSanitizedURL(configuration.ContentsServer, 'content'); if (configuration.ContentDate) uri.searchParams.set('dmytime', configuration.ContentDate); - if (version === SBVersion.v016201) uri.searchParams.set('u1', params.u1); //YOUNGJUMP + if (version === SpeedBindVersion.v016201) uri.searchParams.set('u1', params.u1); //YOUNGJUMP return await ExtractPages.call(this, uri, '/content', '/img/{src}', configuration, chapter); } } From 5227cd023dfe2111919f9a72f09992c49b77c9f2 Mon Sep 17 00:00:00 2001 From: MikeZeDev Date: Fri, 17 Jan 2025 15:19:51 +0100 Subject: [PATCH 88/88] Update _index.ts --- web/src/engine/websites/_index.ts | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/web/src/engine/websites/_index.ts b/web/src/engine/websites/_index.ts index 657491be13..ee8acc065f 100755 --- a/web/src/engine/websites/_index.ts +++ b/web/src/engine/websites/_index.ts @@ -50,6 +50,8 @@ export { default as Bokugents } from './Bokugents'; export { default as Bomtoon } from './Bomtoon'; export { default as BomtoonCN } from './BomtoonCN'; export { default as Bontoon } from './Bontoon'; +export { default as BookHodai } from './BookHodai'; +export { default as BookLive } from './BookLive'; export { default as Boomtoon } from './Boomtoon'; export { default as CartelDeManhwas } from './CartelDeManhwas'; export { default as CarToonMad } from './CarToonMad'; @@ -58,6 +60,7 @@ export { default as CatTranslator } from './CatTranslator'; export { default as CeriseScans } from './CeriseScans'; export { default as Chochox } from './Chochox'; export { default as CiaoPlus } from './CiaoPlus'; +export { default as Cmoa } from './Cmoa'; export { default as Cocorip } from './Cocorip'; export { default as CoffeeManga } from './CoffeeManga'; export { default as ColaManga } from './ColaManga'; @@ -65,6 +68,7 @@ export { default as ColoredManga } from './ColoredManga'; export { default as Comic21 } from './Comic21'; export { default as ComicAction } from './ComicAction'; export { default as ComicBorder } from './ComicBorder'; +export { default as ComicBrise } from './ComicBrise'; export { default as ComicDays } from './ComicDays'; export { default as ComicEarthStar } from './ComicEarthStar'; export { default as ComicExtra } from './ComicExtra'; @@ -73,11 +77,15 @@ 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 ComicMeteor } from './ComicMeteor'; export { default as Comico } from './Comico'; +export { default as ComicPolaris } from './ComicPolaris'; +export { default as ComicPorta } from './ComicPorta'; export { default as ComicRyu } from './ComicRyu'; export { default as ComicsValley } from './ComicsValley'; export { default as ComicTop } from './ComicTop'; export { default as ComicTrail } from './ComicTrail'; +export { default as ComicValkyrie } from './ComicValkyrie'; export { default as ComicVn } from './ComicVn'; export { default as ComicZenon } from './ComicZenon'; export { default as ComicZerosum } from './ComicZerosum'; @@ -113,6 +121,7 @@ export { default as DEXHentai } from './DEXHentai'; export { default as DiamondFansub } from './DiamondFansub'; export { default as DianxiaTrads } from './DianxiaTrads'; export { default as Digimon } from './Digimon'; +export { default as DigitalMargaret } from './DigitalMargaret'; export { default as DigitalTeam } from './DigitalTeam'; export { default as DingManhua } from './DingManhua'; export { default as DisasterScans } from './DisasterScans'; @@ -150,6 +159,7 @@ export { default as FMTeam } from './FMTeam'; export { default as FoyScan } from './FoyScan'; export { default as FreeComicOnline } from './FreeComicOnline'; export { default as FreeManga } from './FreeManga'; +export { default as Futabanet } from './Futabanet'; export { default as Futari } from './Futari'; export { default as GaiaToon } from './GaiaToon'; export { default as GalaxyManga } from './GalaxyManga'; @@ -362,6 +372,8 @@ export { default as MangaOwlio } from './MangaOwlio'; export { default as MangaPanda } from './MangaPanda'; export { default as MangaParkPublisher } from './MangaParkPublisher'; export { default as MangaPill } from './MangaPill'; +export { default as MangaPlanet } from './MangaPlanet'; +export { default as MangaPlaza } from './MangaPlaza'; export { default as MangaPro } from './MangaPro'; export { default as MangaRaw1001 } from './MangaRaw1001'; export { default as MangaRawAC } from './MangaRawAC'; @@ -452,6 +464,7 @@ export { default as Mgkomik } from './Mgkomik'; export { default as MHScans } from './MHScans'; export { default as Mi2mangaES } from './Mi2mangaES'; export { default as MiauScan } from './MiauScan'; +export { default as MichiKusa } from './MichiKusa'; export { default as Migudm } from './Migudm'; export { default as Mikoroku } from './Mikoroku'; export { default as MilaSub } from './MilaSub'; @@ -495,7 +508,9 @@ export { default as NoraNoFansub } from './NoraNoFansub'; export { default as Noromax } from './Noromax'; export { default as NovelMic } from './NovelMic'; export { default as NoxScans } from './NoxScans'; +export { default as Ohtabooks } from './Ohtabooks'; export { default as OlympusScanlation } from './OlympusScanlation'; +export { default as OneTwoThreeHon } from './OneTwoThreeHon'; export { default as Opiatoon } from './Opiatoon'; export { default as Oremanga } from './Oremanga'; export { default as OrigamiOrpheans } from './OrigamiOrpheans'; @@ -612,6 +627,7 @@ export { default as SixParkbbsClub } from './SixParkbbsClub'; export { default as SixParkbbsWeb } from './SixParkbbsWeb'; export { default as SkyManga } from './SkyManga'; export { default as SkyMangas } from './SkyMangas'; +export { default as SManga } from './SManga'; export { default as SoftKomik } from './SoftKomik'; export { default as SoulScans } from './SoulScans'; export { default as SpiderScans } from './SpiderScans'; @@ -645,6 +661,7 @@ export { default as TheBlank } from './TheBlank'; export { default as ThreeHentai } from './ThreeHentai'; export { default as ThunderScans } from './ThunderScans'; export { default as TitanManga } from './TitanManga'; +export { default as TKSuperheroComics } from './TKSuperheroComics'; export { default as TmoManga } from './TmoManga'; export { default as ToCoronaEx } from './ToCoronaEx'; export { default as TonariNoYoungJump } from './TonariNoYoungJump'; @@ -716,6 +733,7 @@ export { default as XManhwa } from './XManhwa'; export { default as XoxoComics } from './XoxoComics'; export { default as XXXYaoi } from './XXXYaoi'; export { default as YakshaScans } from './YakshaScans'; +export { default as Yanmaga } from './Yanmaga'; export { default as YanpFansub } from './YanpFansub'; export { default as YaoiChan } from './YaoiChan'; export { default as YaoiHavenReborn } from './YaoiHavenReborn'; @@ -724,6 +742,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 YoMonga } from './YoMonga'; +export { default as YoungJump } from './YoungJump'; export { default as YumeKomik } from './YumeKomik'; export { default as YuraManga } from './YuraManga'; export { default as Yurineko } from './Yurineko'; @@ -739,19 +759,13 @@ export { default as ZinMangaNet } from './ZinMangaNet'; export { default as AnimePahe } from './legacy/AnimePahe'; export { default as ArazNovel } from './legacy/ArazNovel'; export { default as BilibiliManhua } from './legacy/BilibiliManhua'; -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'; export { default as CrunchyAnime } from './legacy/CrunchyAnime'; export { default as CrunchyManga } from './legacy/CrunchyManga'; export { default as EHentai } from './legacy/EHentai'; export { default as EpikManga } from './legacy/EpikManga'; -export { default as Futabanet } from './legacy/Futabanet'; export { default as GammaPlus } from './legacy/GammaPlus'; export { default as Guoman8 } from './legacy/Guoman8'; export { default as HolyManga } from './legacy/HolyManga'; @@ -803,9 +817,7 @@ export { default as NovelcoolIT } from './legacy/NovelcoolIT'; export { default as NovelcoolRU } from './legacy/NovelcoolRU'; export { default as Novelgo } from './legacy/Novelgo'; export { default as NovelRingan } from './legacy/NovelRingan'; -export { default as Ohtabooks } from './legacy/Ohtabooks'; export { default as OnePieceTube } from './legacy/OnePieceTube'; -export { default as OneTwoThreeHon } from './legacy/OneTwoThreeHon'; export { default as PlotTwistNoFansub } from './legacy/PlotTwistNoFansub'; export { default as ShinobiScans } from './legacy/ShinobiScans'; export { default as SixMH7 } from './legacy/SixMH7'; @@ -837,6 +849,5 @@ export { default as WeLoveManga } from './legacy/WeLoveManga'; export { default as WoopRead } from './legacy/WoopRead'; export { default as WordRain } from './legacy/WordRain'; export { default as WuxiaWorld } from './legacy/WuxiaWorld'; -export { default as YoungJump } from './legacy/YoungJump'; export { default as ZinNovel } from './legacy/ZinNovel'; export { default as ZYMKMangaWeb } from './legacy/ZYMKMangaWeb'; \ No newline at end of file