1+ /**
2+ * This is <b>not</b> a dedicated Guya.moe template repo. However, I feel that it is pointless to introduce yet another
3+ * repository for what is essentially 2-3 sources.
4+ */
5+
6+ import {
7+ Source ,
8+ Manga ,
9+ Chapter ,
10+ ChapterDetails ,
11+ HomeSection ,
12+ SearchRequest ,
13+ LanguageCode ,
14+ MangaStatus ,
15+ MangaUpdates ,
16+ PagedResults ,
17+ } from "paperback-extensions-common"
18+
19+ const SPLIT_VAR = "|"
20+
21+ export abstract class GuyaTemplate extends Source {
22+ readonly abstract baseUrl :string ;
23+ async getMangaDetails ( mangaId :string ) :Promise < Manga > {
24+
25+ let request = createRequestObject ( {
26+ metadata :{ mangaId} ,
27+ url :`${ this . baseUrl } /api/get_all_series/` ,
28+ method :"GET" ,
29+ } )
30+
31+ let response = await this . requestManager . schedule ( request , 1 )
32+
33+ let result = typeof response . data === "string" ?JSON . parse ( response . data ) :response . data
34+
35+ let mangas = [ ]
36+ for ( let series in result ) {
37+ let seriesDetails = result [ series ]
38+ if ( mangaId . includes ( seriesDetails [ "slug" ] ) ) {
39+ mangas . push (
40+ createManga ( {
41+ id :seriesDetails [ "slug" ] ,
42+ titles :[ series ] ,
43+ image :`${ this . baseUrl } /${ seriesDetails [ "cover" ] } ` ,
44+ rating :5 ,
45+ status :MangaStatus . ONGOING ,
46+ artist :seriesDetails [ "artist" ] ,
47+ author :seriesDetails [ "author" ] ,
48+ desc :seriesDetails [ "description" ] ,
49+ } )
50+ )
51+ }
52+ }
53+
54+ return mangas [ 0 ]
55+ }
56+
57+
58+ async getChapters ( mangaId :string ) :Promise < Chapter [ ] > {
59+ let request = createRequestObject ( {
60+ metadata :{ mangaId} ,
61+ url :`${ this . baseUrl } /api/series/${ mangaId } /` ,
62+ method :"GET" ,
63+ } )
64+
65+ let response = await this . requestManager . schedule ( request , 1 )
66+
67+ let result = typeof response . data === "string" ?JSON . parse ( response . data ) :response . data
68+ let rawChapters = result [ "chapters" ]
69+ let groupMap = result [ "groups" ]
70+
71+ let chapters = [ ]
72+ for ( let chapter in rawChapters ) {
73+ let chapterMetadata = rawChapters [ chapter ]
74+ for ( let group in chapterMetadata [ "groups" ] ) {
75+ chapters . push (
76+ createChapter ( {
77+ id :`${ chapter } ${ SPLIT_VAR } ${ group } ` ,
78+ mangaId :mangaId ,
79+ chapNum :Number ( chapter ) ,
80+ langCode :LanguageCode . ENGLISH ,
81+ name :chapterMetadata [ "title" ] ,
82+ volume :chapterMetadata [ "volume" ] ,
83+ group :groupMap [ group ] ,
84+ time :new Date (
85+ Number ( chapterMetadata [ "release_date" ] [ group ] ) * 1000
86+ ) ,
87+ } )
88+ )
89+ }
90+ }
91+ return chapters
92+ }
93+
94+ async getChapterDetails ( mangaId :string , chapterId :string ) :Promise < ChapterDetails > {
95+
96+ const request = createRequestObject ( {
97+ url :`${ this . baseUrl } /api/series/${ mangaId } /` ,
98+ method :"GET" ,
99+ } )
100+
101+ const data = await this . requestManager . schedule ( request , 1 )
102+
103+ let result = typeof data . data === "string" ?JSON . parse ( data . data ) :data . data
104+ let rawChapters = result [ "chapters" ]
105+ let [ chapter , group ] = chapterId . split ( SPLIT_VAR )
106+ return createChapterDetails ( {
107+ id :chapterId ,
108+ longStrip :false ,
109+ mangaId :mangaId ,
110+ pages :rawChapters [ chapter ] [ "groups" ] [ group ] . map (
111+ ( page :string ) =>
112+ `${ this . baseUrl } /media/manga/${ mangaId } /chapters/${ rawChapters [ chapter ] [ "folder" ] } /${ group } /${ page } `
113+ ) ,
114+ } )
115+ }
116+
117+ async searchRequest ( searchQuery :SearchRequest , metadata :any ) :Promise < PagedResults > {
118+
119+ const request = createRequestObject ( {
120+ url :`${ this . baseUrl } /api/get_all_series/` ,
121+ method :"GET" ,
122+ } )
123+
124+ const data = await this . requestManager . schedule ( request , 1 )
125+
126+ let result = typeof data . data === "string" ?JSON . parse ( data . data ) :data . data
127+ let query = searchQuery . title ?? ''
128+
129+ let filteredResults = Object . keys ( result ) . filter ( ( e ) =>
130+ e . toLowerCase ( ) . includes ( query . toLowerCase ( ) )
131+ )
132+
133+ let tiles = filteredResults . map ( ( series ) => {
134+ let seriesMetadata = result [ series ]
135+ return createMangaTile ( {
136+ id :seriesMetadata [ "slug" ] ,
137+ image :`${ this . baseUrl } /${ seriesMetadata [ "cover" ] } ` ,
138+ title :createIconText ( { text :series } ) ,
139+ } )
140+ } )
141+
142+ return createPagedResults ( {
143+ results :tiles
144+ } )
145+ }
146+
147+ async getHomePageSections ( sectionCallback :( section :HomeSection ) => void ) :Promise < void > {
148+
149+ // Send the empty homesection back so the app can preload the section
150+ var homeSection = createHomeSection ( { id :"all_guya" , title :"ALL GUYA" } )
151+ sectionCallback ( homeSection )
152+
153+ const request = createRequestObject ( {
154+ url :`${ this . baseUrl } /api/get_all_series/` ,
155+ method :"GET"
156+ } )
157+
158+ const data = await this . requestManager . schedule ( request , 1 )
159+
160+ let result = typeof data . data === "string" ?JSON . parse ( data . data ) :data . data
161+
162+ let mangas = [ ]
163+ for ( let series in result ) {
164+ let seriesDetails = result [ series ]
165+ mangas . push (
166+ createMangaTile ( {
167+ id :seriesDetails [ "slug" ] ,
168+ image :`${ this . baseUrl } /${ seriesDetails [ "cover" ] } ` ,
169+ title :createIconText ( { text :series } ) ,
170+ } )
171+ )
172+ }
173+ homeSection . items = mangas
174+
175+ sectionCallback ( homeSection )
176+ }
177+
178+ async filterUpdatedManga ( mangaUpdatesFoundCallback :( updates :MangaUpdates ) => void , time :Date , ids :string [ ] ) :Promise < void > {
179+
180+ const request = createRequestObject ( {
181+ url :`${ this . baseUrl } /api/get_all_series/` ,
182+ method :"GET"
183+ } )
184+
185+ const data = await this . requestManager . schedule ( request , 1 )
186+
187+ let result = typeof data . data === "string" ?JSON . parse ( data . data ) :data . data
188+
189+ let foundIds :string [ ] = [ ]
190+
191+ for ( let series in result ) {
192+ const seriesDetails = result [ series ]
193+ const seriesUpdated = new Date ( seriesDetails [ "last_updated" ] * 1000 )
194+ const id = seriesDetails [ "slug" ] ;
195+ if ( seriesUpdated >= time && ids . includes ( id ) ) {
196+ foundIds . push ( id ) ;
197+ }
198+ }
199+ mangaUpdatesFoundCallback ( createMangaUpdates ( { ids :foundIds } ) )
200+ }
201+
202+ getMangaShareUrl ( mangaId :string ) {
203+ return `${ this . baseUrl } /read/manga/${ mangaId } /`
204+ }
205+ }