22
33import $ from 'jquery'
44
5- const COVER : Record < string , string > = {
6- ウェスタdeクッキング : 'https://alt.hololive.tv/wp-content/uploads/2024/11/%E3%82%AF%E3%83%83%E3%82%AD%E3%83%B3%E3%82%AF%E3%82%99.jpg' ,
7- 'Vesta de Cooking' : 'https://alt.hololive.tv/wp-content/uploads/2024/11/%E3%82%AF%E3%83%83%E3%82%AD%E3%83%B3%E3%82%AF%E3%82%99.jpg' ,
8-
9- 'それゆけ!! 魔界学校' : 'https://alt.hololive.tv/wp-content/uploads/2023/06/cover_makaigakko.jpg' ,
10- 'Underworld Academy Overload!!' : 'https://alt.hololive.tv/wp-content/uploads/2023/06/cover_makaigakko.jpg' ,
11- 'Sukaria Sekolah Alam Bawah' : 'https://alt.hololive.tv/wp-content/uploads/2023/06/cover_makaigakko.jpg' ,
12-
13- 'Yamato Phantasia' : 'https://alt.hololive.tv/wp-content/uploads/2023/06/holoearth_main-1.png' ,
14- ヤマト神想怪異譚 : 'https://alt.hololive.tv/wp-content/uploads/2023/06/holoearth_main-1.png' ,
15- 'Kisah Fantasi Yamato' : 'https://alt.hololive.tv/wp-content/uploads/2023/06/holoearth_main-1.png'
16- }
5+ const MANGA_INFO = [
6+ {
7+ title : {
8+ en : 'Vesta de Cooking' ,
9+ jp : 'ウェスタdeクッキング' ,
10+ id : 'Vesta de Cooking'
11+ } ,
12+ url : {
13+ en : 'https://holoearth.com/en/alt/holonometria/manga/vestadecooking' ,
14+ jp : 'https://holoearth.com/alt/holonometria/manga/vestadecooking' ,
15+ id : 'https://holoearth.com/id/alt/holonometria/manga/vestadecooking'
16+ } ,
17+ cover : 'https://holoearth.com/assets/img/alt/top/comic/thumb_1.jpg' ,
18+ firstEp : 'ep0'
19+ } ,
20+
21+ {
22+ title : {
23+ en : 'Underworld Academy Overload!!' ,
24+ jp : 'それゆけ!! 魔界学校' ,
25+ id : 'Sukaria Sekolah Alam Bawah'
26+ } ,
27+ url : {
28+ en : 'https://holoearth.com/en/alt/holonometria/manga/soreyukemakaigakko' ,
29+ jp : 'https://holoearth.com/alt/holonometria/manga/soreyukemakaigakko' ,
30+ id : 'https://holoearth.com/id/alt/holonometria/manga/soreyukemakaigakko'
31+ } ,
32+ cover : 'https://holoearth.com/assets/img/alt/top/comic/thumb_2.jpg' ,
33+ firstEp : 'ep0'
34+ } ,
35+
36+ {
37+ title : {
38+ en : 'Yamato Phantasia' ,
39+ jp : 'ヤマト神想怪異譚' ,
40+ id : 'Kisah Fantasi Yamato'
41+ } ,
42+ url : {
43+ en : 'https://holoearth.com/en/alt/holonometria/manga/yamatokasoukaiitan' ,
44+ jp : 'https://holoearth.com/alt/holonometria/manga/yamatokasoukaiitan' ,
45+ id : 'https://holoearth.com/id/alt/holonometria/manga/yamatokasoukaiitan'
46+ } ,
47+ cover : 'https://holoearth.com/assets/img/alt/top/comic/thumb_3.jpg' ,
48+ firstEp : 'ep0'
49+ }
50+ ]
1751
1852function sleep ( ms : number ) {
1953 return new Promise ( resolve => setTimeout ( resolve , ms ) )
@@ -35,70 +69,34 @@ async function getMangaList (
3569 keyword ?: string ,
3670 rawFilterOptions ?: string
3771) {
72+ const result : IGetMangaListResult = {
73+ list : [ ]
74+ }
75+
3876 if ( page !== '1' ) {
39- window . Rulia . endWithResult ( {
40- list : [ ]
41- } )
77+ window . Rulia . endWithResult ( result )
4278 return
4379 }
4480
4581 try {
4682 const config = window . Rulia . getUserConfig ( )
4783 const lang = ( config ?. language ?? 'en' ) . toLowerCase ( )
48-
49- const homepages : Record < string , string > = {
50- en : 'https://alt.hololive.tv/holonometria/en/' ,
51- jp : 'https://alt.hololive.tv/holonometria/' ,
52- id : 'https://alt.hololive.tv/holonometria/id/'
53- }
54-
55- const homepage = homepages [ lang ] || homepages . en
56- const response = await window . Rulia . httpRequest ( {
57- url : homepage ,
58- method : 'GET'
59- } )
60-
61- const result : IGetMangaListResult = {
62- list : [ ]
63- }
64-
65- $ ( response ) . find ( 'li[data-type="manga"] a' ) . each ( ( i , el ) => {
66- const title = $ ( el ) . text ( )
67- const url = $ ( el ) . attr ( 'href' ) ?? ''
84+ for ( const item of MANGA_INFO ) {
85+ const title = item . title [ lang as keyof typeof item . title ] ?? item . title . en
86+ const url = item . url [ lang as keyof typeof item . url ] ?? item . url . en
6887 result . list . push ( {
6988 title,
70- url,
71- coverUrl : COVER [ title ] ?? ''
89+ url : ` ${ url } / ${ item . firstEp } ?title= ${ encodeURIComponent ( title ) } ` ,
90+ coverUrl : item . cover
7291 } )
73- } )
92+ }
7493
7594 window . Rulia . endWithResult ( result )
7695 } catch ( error ) {
7796 window . Rulia . endWithException ( ( error as Error ) . message )
7897 }
7998}
8099
81- async function getChapterListFromDetailPage ( detailPage : string ) : Promise < { title : string , url : string } [ ] > {
82- const response = await window . Rulia . httpRequest ( {
83- url : detailPage ,
84- method : 'GET'
85- } )
86-
87- const result : { title : string , url : string } [ ] = [ ]
88- $ ( response ) . find ( 'article.md-list__archive--lineup--block' ) . each ( ( i , el ) => {
89- const $a = $ ( el ) . find ( 'a' )
90- const $h4 = $ ( el ) . find ( 'h4' )
91- const title = $h4 . text ( ) . trim ( )
92- const url = $a . attr ( 'href' ) ?? ''
93- result . push ( {
94- title,
95- url
96- } )
97- } )
98-
99- return result
100- }
101-
102100/**
103101 * Get data of a single manga.
104102 * This function will be invoked by Rulia when user clicks a certain manga
@@ -115,32 +113,32 @@ async function getMangaData (dataPageUrl: string) {
115113 } )
116114
117115 const $html = $ ( response )
118- const title = $html . find ( 'h1.md-ttl__pages' ) ?. text ( ) ?. trim ( ) ?? ''
119- const description = $html . find ( 'main.mangainfo--main main ' ) ?. text ( ) ?. trim ( ) ?? ''
120- const coverUrl = $html . find ( 'main.mangainfo--main img' ) ?. attr ( 'src' ) ?? ''
116+ const title = new URL ( dataPageUrl ) . searchParams . get ( 'title' ) ?? ''
117+ const description = $html . find ( '.manga-detail__caption ' ) ?. text ( ) ?. trim ( ) ?? ''
118+ const coverUrl = $html . find ( '.manga-detail__thumb img' ) ?. attr ( 'src' ) ?? ''
121119
122120 const result : IGetMangaDataResult = {
123121 title,
124122 description,
125123 coverUrl,
126- chapterList : [ ]
124+ chapterList : [ ] ,
125+ chapterListOptions : {
126+ hasPagination : true ,
127+ totalPage : 1
128+ }
127129 }
128130
129- const allDetailPages = [ dataPageUrl ]
130- $html . find ( '.pagenation-list a' ) . each ( ( i , el ) => {
131- const url = $ ( el ) . attr ( 'href' )
132- if ( url ) {
133- allDetailPages . push ( url )
134- }
135- } )
131+ $html . find ( '.manga-detail__list-item' ) . each ( ( i , el ) => {
132+ const $el = $ ( el )
133+ const title = $el . find ( '.manga-detail__list-title' ) . text ( ) . trim ( )
134+ const url = $el . find ( '.manga-detail__list-link' ) . attr ( 'href' ) ?? ''
136135
137- for ( const pageUrl of allDetailPages ) {
138- const list = await getChapterListFromDetailPage ( pageUrl )
139- result . chapterList . push ( ... list )
140- await sleep ( 300 )
141- }
136+ result . chapterList . push ( {
137+ title ,
138+ url
139+ } )
140+ } )
142141
143- result . chapterList . reverse ( )
144142 window . Rulia . endWithResult ( result )
145143 } catch ( error ) {
146144 window . Rulia . endWithException ( ( error as Error ) . message )
@@ -162,18 +160,17 @@ async function getChapterImageList (chapterUrl: string) {
162160 const result : IRuliaChapterImage [ ] = [ ]
163161 const $html = $ ( response )
164162
165- const $mangaBlocks = $html . find ( '.manga--viewer__block' )
166- $mangaBlocks . each ( ( i , el ) => {
167- const img = $ ( el ) . find ( 'img' ) [ 0 ]
168- if ( img ) {
169- result . push ( {
170- url : img . src ,
171- width : 684 ,
172- height : 997
173- } )
174- }
163+ const $images = $html . find ( '.manga-detail__swiper-slide img' )
164+ $images . each ( ( i , el ) => {
165+ const src = $ ( el ) . attr ( 'src' ) || ''
166+ result . push ( {
167+ url : src ,
168+ width : 684 ,
169+ height : 997
170+ } )
175171 } )
176172
173+ result . reverse ( ) // The image order in the html is reversed, so we need to reverse it back.
177174 window . Rulia . endWithResult ( result )
178175 } catch ( error ) {
179176 window . Rulia . endWithException ( ( error as Error ) . message )
0 commit comments