@@ -3,11 +3,10 @@ package com.hexated
33import com.lagradost.cloudstream3.*
44import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
55import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
6- import com.lagradost.cloudstream3.utils.ExtractorLink
7- import com.lagradost.cloudstream3.utils.INFER_TYPE
8- import com.lagradost.cloudstream3.utils.Qualities
9- import com.lagradost.cloudstream3.utils.loadExtractor
10- import com.lagradost.cloudstream3.utils.newExtractorLink
6+ import com.lagradost.cloudstream3.utils.*
7+ import kotlinx.coroutines.async
8+ import kotlinx.coroutines.awaitAll
9+ import kotlinx.coroutines.coroutineScope
1110import org.jsoup.Jsoup
1211import org.jsoup.nodes.Element
1312
@@ -50,15 +49,11 @@ class KuramanimeProvider : MainAPI() {
5049 " $mainUrl /anime/movie?order_by=updated&page=" to " Film Layar Lebar" ,
5150 )
5251
53- override suspend fun getMainPage (
54- page : Int ,
55- request : MainPageRequest
56- ): HomePageResponse {
52+ override suspend fun getMainPage (page : Int , request : MainPageRequest ): HomePageResponse {
5753 val document = app.get(request.data + page).document
5854 val home = document.select(" div#animeList div.product__item" ).mapNotNull {
5955 it.toSearchResult()
6056 }
61-
6257 return newHomePageResponse(request.name, home)
6358 }
6459
@@ -82,7 +77,6 @@ class KuramanimeProvider : MainAPI() {
8277 this .posterUrl = posterUrl
8378 addSub(episode)
8479 }
85-
8680 }
8781
8882 override suspend fun search (query : String ): List <SearchResponse > {
@@ -98,9 +92,9 @@ class KuramanimeProvider : MainAPI() {
9892
9993 val title = document.selectFirst(" .anime__details__title > h3" )!! .text().trim()
10094 val poster = document.selectFirst(" .anime__details__pic" )?.attr(" data-setbg" )
101- val tags =
102- document .select(" div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)" )
103- .text().trim().replace(" Genre: " , " " ).split(" , " )
95+ val tags = document
96+ .select(" div.anime__details__widget > div > div:nth-child(2) > ul > li:nth-child(1)" )
97+ .text().trim().replace(" Genre: " , " " ).split(" , " )
10498
10599 val year = Regex (" \\ D" ).replace(
106100 document.select(" div.anime__details__widget > div > div:nth-child(1) > ul > li:nth-child(5)" )
@@ -113,7 +107,6 @@ class KuramanimeProvider : MainAPI() {
113107 val description = document.select(" .anime__details__text > p" ).text().trim()
114108
115109 val episodes = mutableListOf<Episode >()
116-
117110 for (i in 1 .. 30 ) {
118111 val doc = app.get(" $url ?page=$i " ).document
119112 val eps = Jsoup .parse(doc.select(" #episodeLists" ).attr(" data-content" ))
@@ -132,6 +125,7 @@ class KuramanimeProvider : MainAPI() {
132125 document.selectFirst(" div.col-lg-6.col-md-6 ul li:contains(Tipe:) a" )?.text()
133126 ?.lowercase() ? : " tv" , episodes.size
134127 )
128+
135129 val recommendations = document.select(" div#randomList > a" ).mapNotNull {
136130 val epHref = it.attr(" href" )
137131 val epTitle = it.select(" h5.sidebar-title-h5.px-2.py-2" ).text()
@@ -157,7 +151,6 @@ class KuramanimeProvider : MainAPI() {
157151 addMalId(tracker?.malId)
158152 addAniListId(tracker?.aniId?.toIntOrNull())
159153 }
160-
161154 }
162155
163156 private suspend fun invokeLocalSource (
@@ -166,13 +159,9 @@ class KuramanimeProvider : MainAPI() {
166159 headers : Map <String , String >,
167160 subtitleCallback : (SubtitleFile ) -> Unit ,
168161 callback : (ExtractorLink ) -> Unit
169- ) {
170- val document = app.get(
171- url,
172- headers = headers,
173- cookies = cookies
174- ).document
175- document.select(" video#player > source" ).map {
162+ ) = coroutineScope {
163+ val document = app.get(url, headers = headers, cookies = cookies).document
164+ document.select(" video#player > source" ).forEach {
176165 val link = fixUrl(it.attr(" src" ))
177166 val quality = it.attr(" size" ).toIntOrNull()
178167 callback.invoke(
@@ -192,10 +181,14 @@ class KuramanimeProvider : MainAPI() {
192181 }
193182 )
194183 }
184+
195185 if (server == " kuramadrive" ) {
196- document.select(" div#animeDownloadLink a" ).apmap {
197- loadExtractor(it.attr(" href" ), " $mainUrl /" , subtitleCallback, callback)
198- }
186+ // FIXED: replace apmap with async + awaitAll
187+ document.select(" div#animeDownloadLink a" ).map { link ->
188+ async {
189+ loadExtractor(link.attr(" href" ), " $mainUrl /" , subtitleCallback, callback)
190+ }
191+ }.awaitAll()
199192 }
200193 }
201194
@@ -204,16 +197,14 @@ class KuramanimeProvider : MainAPI() {
204197 isCasting : Boolean ,
205198 subtitleCallback : (SubtitleFile ) -> Unit ,
206199 callback : (ExtractorLink ) -> Unit
207- ): Boolean {
200+ ): Boolean = coroutineScope {
208201
209202 val req = app.get(data)
210203 val res = req.document
211204 cookies = req.cookies
212205
213- val token = res.selectFirst(" meta[name=csrf-token]" )?.attr(" content" ) ? : return false
214- val dataKps =
215- res.selectFirst(" div.col-lg-12.mt-3" )?.attributes()?.last()?.value ? : return false
216-
206+ val token = res.selectFirst(" meta[name=csrf-token]" )?.attr(" content" ) ? : return @coroutineScope false
207+ val dataKps = res.selectFirst(" div.col-lg-12.mt-3" )?.attributes()?.last()?.value ? : return @coroutineScope false
217208 val assets = getAssets(dataKps)
218209
219210 var headers = mapOf (
@@ -235,26 +226,26 @@ class KuramanimeProvider : MainAPI() {
235226 " X-Requested-With" to " XMLHttpRequest" ,
236227 )
237228
238- res.select(" select#changeServer option" ).apmap { source ->
239- val server = source.attr(" value" )
240- val link =
241- " $data ?${assets.MIX_PAGE_TOKEN_KEY } =$tokenKey &${assets.MIX_STREAM_SERVER_KEY } =$server "
242- if (server.contains(Regex (" (?i)kuramadrive|archive" ))) {
243- invokeLocalSource(link, server, headers, subtitleCallback, callback)
244- } else {
245- app.get(
246- link,
247- referer = data,
248- headers = headers,
249- cookies = cookies
250- ).document.select(" div.iframe-container iframe" ).attr(" src" ).let { videoUrl ->
251- loadExtractor(fixUrl(videoUrl), " $mainUrl /" , subtitleCallback, callback)
229+ // FIXED: replace apmap with async + awaitAll
230+ res.select(" select#changeServer option" ).map { source ->
231+ async {
232+ val server = source.attr(" value" )
233+ val link =
234+ " $data ?${assets.MIX_PAGE_TOKEN_KEY } =$tokenKey &${assets.MIX_STREAM_SERVER_KEY } =$server "
235+
236+ if (server.contains(Regex (" (?i)kuramadrive|archive" ))) {
237+ invokeLocalSource(link, server, headers, subtitleCallback, callback)
238+ } else {
239+ app.get(link, referer = data, headers = headers, cookies = cookies)
240+ .document.select(" div.iframe-container iframe" )
241+ .attr(" src" ).let { videoUrl ->
242+ loadExtractor(fixUrl(videoUrl), " $mainUrl /" , subtitleCallback, callback)
243+ }
252244 }
253245 }
254- }
255-
246+ }.awaitAll()
256247
257- return true
248+ true
258249 }
259250
260251 private suspend fun getAssets (bpjs : String? ): Assets {
@@ -280,9 +271,7 @@ class KuramanimeProvider : MainAPI() {
280271
281272 private fun randomId (length : Int = 6): String {
282273 val allowedChars = (' a' .. ' z' ) + (' A' .. ' Z' ) + (' 0' .. ' 9' )
283- return (1 .. length)
284- .map { allowedChars.random() }
285- .joinToString(" " )
274+ return (1 .. length).map { allowedChars.random() }.joinToString(" " )
286275 }
287276
288277 data class Assets (
@@ -293,5 +282,4 @@ class KuramanimeProvider : MainAPI() {
293282 val MIX_PAGE_TOKEN_KEY : String? ,
294283 val MIX_STREAM_SERVER_KEY : String? ,
295284 )
296-
297- }
285+ }
0 commit comments