1- import Connector from '../engine/Connector .mjs' ;
1+ import Comici from './templates/Comici .mjs' ;
22import Manga from '../engine/Manga.mjs' ;
33
4- //very Similar to Yanmaga - its called ComiciViewer
5- export default class YoungChampion extends Connector {
4+ export default class YoungChampion extends Comici {
65 constructor ( ) {
76 super ( ) ;
87 super . id = 'youngchampion' ;
98 super . label = 'YoungChampion' ;
109 this . tags = [ 'manga' , 'japanese' ] ;
1110 this . url = 'https://youngchampion.jp' ;
1211 this . apiUrl = this . url ;
13- this . defaultOrder = [ ] ;
1412 this . links = {
1513 login : 'https://youngchampion.jp/signin'
1614 } ;
17- for ( let i = 0 ; i < 4 ; i ++ ) {
18- for ( let j = 0 ; j < 4 ; j ++ ) {
19- this . defaultOrder . push ( [ i , j ] ) ;
20- }
21- }
2215
23- this . mangaListPath = '/series/list?page={page}' ;
2416 this . queryMangaTitleURI = 'h1.series-h-title span:not([class])' ;
25- this . queryManga = 'div.series-box-vertical > a' ;
26- this . queryMangaTitle = 'h2.title-text' ;
2717 this . queryChapter = 'div.series-ep-list a[data-href]' ;
2818 this . queryChapterTitle = 'span.series-ep-list-item-h-text' ;
2919 }
3020
3121 async _getMangaFromURI ( uri ) {
3222 const request = new Request ( uri ) ;
3323 const [ data ] = await this . fetchDOM ( request , this . queryMangaTitleURI ) ;
34- const id = uri . pathname ;
24+ const id = uri . pathname . replace ( '/series/' , '' ) ;
3525 const title = ( data . textContent || data . text ) . trim ( ) ;
3626 return new Manga ( this , id , title ) ;
3727 }
3828
39- async _getMangas ( ) {
40- let mangaList = [ ] ;
41- for ( let page = 1 , run = true ; run ; page ++ ) {
42- const mangas = await this . _getMangasFromPage ( page ) ;
43- mangas . length > 0 ? mangaList . push ( ...mangas ) : run = false ;
44- }
45- return mangaList ;
46- }
47-
48- async _getMangasFromPage ( page ) {
49- const uri = new URL ( this . mangaListPath . replace ( '{page}' , page ) , this . url ) ;
50- const request = new Request ( uri , this . requestOptions ) ;
51- const data = await this . fetchDOM ( request , this . queryManga ) ;
52- return data . map ( element => {
53- const titleElement = element . querySelector ( this . queryMangaTitle ) ;
54- return {
55- id : this . getRootRelativeOrAbsoluteLink ( element , this . url ) ,
56- title : titleElement ? ( titleElement . textContent || titleElement . text ) . trim ( ) : element . text . trim ( )
57- } ;
58- } ) ;
59- }
60-
6129 async _getChapters ( manga ) {
62- const uri = new URL ( manga . id + '/list' , this . url ) ;
30+ const uri = new URL ( '/series/' + manga . id + '/list' , this . url ) ;
6331 const request = new Request ( uri ) ;
6432 const data = await this . fetchDOM ( request , this . queryChapter ) ;
6533 return data . map ( element => {
6634 const titleElement = element . querySelector ( this . queryChapterTitle ) ;
6735 return {
68- id : new URL ( element . dataset [ 'href' ] ) . pathname ,
36+ id : new URL ( element . dataset [ 'href' ] ) . pathname . replace ( '/series/' , '' ) ,
6937 title : titleElement ? ( titleElement . textContent || titleElement . text ) . trim ( ) : element . text . trim ( )
7038 } ;
7139 } ) ;
7240 }
7341
74- async _getPages ( chapter ) {
75- const uri = new URL ( chapter . id , this . url ) ;
76- const request = new Request ( uri ) ;
77- const [ viewer ] = await this . fetchDOM ( request , '#comici-viewer' ) ;
78- if ( ! viewer ) {
79- throw new Error ( `The chapter '${ chapter . title } ' is neither public, nor purchased!` ) ;
80- }
81- const coord = await this . _fetchCoordInfo ( viewer ) ;
82- return coord . result . map ( image => {
83- return this . createConnectorURI ( {
84- url : image . imageUrl ,
85- scramble : image . scramble ,
86- } ) ;
87- } ) ;
88- }
89-
90- async _handleConnectorURI ( payload ) {
91- const request = new Request ( new URL ( payload . url ) ) ;
92- request . headers . set ( 'x-origin' , this . url ) ;
93- request . headers . set ( 'x-referer' , this . url ) ;
94- const res = await fetch ( request ) ;
95- const blob = await res . blob ( ) ;
96- const image = await createImageBitmap ( blob ) ;
97- const canvas = this . _descramble ( image , payload . scramble ) ;
98- const blobFinally = await this . _canvasToBlob ( canvas ) ;
99- return this . _blobToBuffer ( blobFinally ) ;
100- }
101-
10242 async _fetchCoordInfo ( viewer ) {
10343 //first request get page count
104- let uri = new URL ( '/ book/contentsInfo', this . url ) ;
44+ let uri = new URL ( this . apiPath + ' book/contentsInfo', this . url ) ;
10545 uri . searchParams . set ( 'comici-viewer-id' , viewer . getAttribute ( 'comici-viewer-id' ) ) ;
10646 uri . searchParams . set ( 'user-id' , viewer . dataset [ 'memberJwt' ] ) ;
10747 uri . searchParams . set ( 'page-from' , '0' ) ;
@@ -113,7 +53,7 @@ export default class YoungChampion extends Connector {
11353
11454 //second request fetch actual pages data
11555 const numbers = data . totalPages ;
116- uri = new URL ( '/ book/contentsInfo', this . url ) ;
56+ uri = new URL ( this . apiPath + ' book/contentsInfo', this . url ) ;
11757 uri . searchParams . set ( 'comici-viewer-id' , viewer . getAttribute ( 'comici-viewer-id' ) ) ;
11858 uri . searchParams . set ( 'user-id' , viewer . dataset [ 'memberJwt' ] ) ;
11959 uri . searchParams . set ( 'page-from' , '0' ) ;
@@ -123,43 +63,4 @@ export default class YoungChampion extends Connector {
12363 request . headers . set ( 'x-referer' , this . url ) ;
12464 return await this . fetchJSON ( request ) ;
12565 }
126-
127- _decodeScrambleArray ( scramble ) {
128- const decoded = [ ] ;
129- const encoded = scramble . replace ( / \s + / g, '' ) . slice ( 1 ) . slice ( 0 , - 1 ) . split ( ',' ) ;
130- for ( let i = 0 ; i < this . defaultOrder . length ; i ++ ) {
131- decoded . push ( this . defaultOrder [ encoded [ i ] ] ) ;
132- }
133- return decoded ;
134- }
135-
136- _descramble ( imageDom , scrambleString ) {
137- const width = imageDom . width ;
138- const height = imageDom . height ;
139-
140- const canvas = document . createElement ( 'canvas' ) ;
141- canvas . width = width ;
142- canvas . height = height ;
143-
144- const context = canvas . getContext ( '2d' ) ;
145- const decodedArray = this . _decodeScrambleArray ( scrambleString ) ;
146- const tileWidth = Math . floor ( width / 4 ) ;
147- const tileHeight = Math . floor ( height / 4 ) ;
148- for ( let k = 0 , i = 0 ; i < 4 ; i ++ ) {
149- for ( let j = 0 ; j < 4 ; j ++ ) {
150- const x = decodedArray [ k ] [ 0 ] , y = decodedArray [ k ] [ 1 ] ;
151- context . drawImage ( imageDom , tileWidth * x , tileHeight * y , tileWidth , tileHeight , tileWidth * i , tileHeight * j , tileWidth , tileHeight ) ;
152- k ++ ;
153- }
154- }
155- return canvas ;
156- }
157-
158- _canvasToBlob ( canvas ) {
159- return new Promise ( resolve => {
160- canvas . toBlob ( data => {
161- resolve ( data ) ;
162- } , Engine . Settings . recompressionFormat . value , parseFloat ( Engine . Settings . recompressionQuality . value ) / 100 ) ;
163- } ) ;
164- }
16566}
0 commit comments