@@ -111,57 +111,84 @@ class Nekopoi : MainAPI() {
111111 }
112112
113113 override suspend fun loadLinks (
114- data : String ,
115- isCasting : Boolean ,
116- subtitleCallback : (SubtitleFile ) -> Unit ,
117- callback : (ExtractorLink ) -> Unit
118- ): Boolean = coroutineScope {
114+ data : String ,
115+ isCasting : Boolean ,
116+ subtitleCallback : (SubtitleFile ) -> Unit ,
117+ callback : (ExtractorLink ) -> Unit
118+ ): Boolean = kotlinx.coroutines. coroutineScope {
119119
120- val res = fetch.get(data).document
120+ val res = fetch.get(data).document
121121
122- // --- Handle iframe stream sources ---
123- val iframeJobs = res.select(" div#show-stream iframe" ).map { iframe ->
124- async {
125- loadExtractor(iframe.attr(" src" ), " $mainUrl /" , subtitleCallback, callback)
126- }
122+ // ambil iframe (stream) sources
123+ val iframeSrcs = if (data.contains(" movie" ) || data.contains(" live-action" )) {
124+ res.select(" #player2-1 > div[id*=div]" ).mapNotNull {
125+ fixUrl(it.select(" iframe" ).attr(" data-src" ))
126+ }
127+ } else {
128+ res.select(" .player2 > .embed2 > div[id*=player]" ).mapNotNull {
129+ fixUrl(it.select(" iframe" ).attr(" data-src" ))
130+ }
131+ }
132+
133+ // buat pekerjaan untuk setiap iframe (boleh paralel)
134+ val iframeJobs = iframeSrcs.map { src ->
135+ kotlinx.coroutines.async {
136+ loadExtractor(src, " $mainUrl /" , subtitleCallback, callback)
127137 }
138+ }
128139
129- // --- Handle mirrored download links ---
130- val mirrorJobs = res.select(" div.boxdownload div.liner" ).map { ele ->
131- async {
132- val quality = getIndexQuality(ele.select(" div.name" ).text())
133- val ouoUrl = ele.selectFirst(" a:contains(ouo)" )?.attr(" href" )
134- if (ouoUrl != null && quality != Qualities .P360 .value) {
135- val bypassed = bypassMirrored(bypassOuo(ouoUrl))
136- bypassed.forEach { adsLink ->
137- if (adsLink != null ) {
138- loadExtractor(
139- fixEmbed(adsLink) ? : return @forEach,
140- " $mainUrl /" ,
141- subtitleCallback
142- ) { link ->
143- callback(
144- newExtractorLink(
145- link.name, link.name, link.url, link.type
146- ) {
147- this .referer = link.referer
148- this .quality =
149- if (link.type == ExtractorLinkType .M3U8 ) link.quality else quality
150- this .headers = link.headers
151- this .extractorData = link.extractorData
152- }
153- )
154- }
140+ // proses bagian "boxdownload" (mirrors/ouo -> bypass -> mirrored)
141+ val boxItems = res.select(" div.boxdownload div.liner" ).map { ele ->
142+ val quality = getIndexQuality(ele.select(" div.name" ).text())
143+ val ouo = ele.selectFirst(" a:contains(ouo)" )?.attr(" href" )
144+ quality to ouo
145+ }.filter { it.second != null && it.first != Qualities .P360 .value }
146+
147+ val boxJobs = boxItems.map { (quality, ouoUrl) ->
148+ kotlinx.coroutines.async {
149+ // bypass Ouo (suspend) -- dipanggil di dalam async (yang berjalan di coroutineScope)
150+ val bypassed = try {
151+ bypassOuo(ouoUrl)
152+ } catch (e: Exception ) {
153+ null
154+ } ? : return @async
155+
156+ // bypassMirrored juga suspend
157+ val adsList = try {
158+ bypassMirrored(bypassed)
159+ } catch (e: Exception ) {
160+ emptyList<String ?>()
161+ }
162+
163+ // untuk setiap ads link yang valid, panggil loadExtractor (sink callback)
164+ adsList.filterNotNull().forEach { adsLink ->
165+ val embed = fixEmbed(adsLink) ? : return @forEach
166+ loadExtractor(embed, " $mainUrl /" , subtitleCallback) { link ->
167+ // langsung invoke callback (tidak runBlocking)
168+ callback.invoke(
169+ newExtractorLink(
170+ link.name,
171+ link.name,
172+ link.url,
173+ link.type
174+ ) {
175+ this .referer = link.referer
176+ this .quality = if (link.type == ExtractorLinkType .M3U8 ) link.quality else quality
177+ this .headers = link.headers
178+ this .extractorData = link.extractorData
155179 }
156- }
180+ )
157181 }
158182 }
159183 }
160-
161- (iframeJobs + mirrorJobs).awaitAll()
162- true
163184 }
164185
186+ // tunggu semua pekerjaan selesai
187+ (iframeJobs + boxJobs).awaitAll()
188+
189+ true
190+ }
191+
165192 private fun fixEmbed (url : String? ): String? {
166193 if (url == null ) return null
167194 val host = getBaseUrl(url)
0 commit comments