@@ -4,7 +4,9 @@ import com.lagradost.cloudstream3.*
44import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
55import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
66import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
7+ import com.lagradost.cloudstream3.amap
78import com.lagradost.cloudstream3.utils.*
9+ import kotlinx.coroutines.runBlocking
810import org.jsoup.Jsoup
911import org.jsoup.nodes.Element
1012
@@ -35,7 +37,7 @@ class AnimasuProvider : MainAPI() {
3537 fun getStatus (t : String? ): ShowStatus {
3638 if (t == null ) return ShowStatus .Completed
3739 return when {
38- t.contains(" Sedang Tayang " , true ) -> ShowStatus .Ongoing
40+ t.contains(" Ongoing " , true ) -> ShowStatus .Ongoing
3941 else -> ShowStatus .Completed
4042 }
4143 }
@@ -52,12 +54,10 @@ class AnimasuProvider : MainAPI() {
5254
5355 override suspend fun getMainPage (page : Int , request : MainPageRequest ): HomePageResponse {
5456 val document = app.get(" $mainUrl /pencarian/?${request.data} &halaman=$page " ).document
55-
56- val homeList = document.select(" div.listupd div.bs" ).mapNotNull {
57+ val home = document.select(" div.listupd div.bs" ).map {
5758 it.toSearchResult()
5859 }
59-
60- return newHomePageResponse(request.name, homeList, hasNext = homeList.isNotEmpty())
60+ return newHomePageResponse(request.name, home)
6161 }
6262
6363 private fun getProperAnimeLink (uri : String ): String {
@@ -66,70 +66,68 @@ class AnimasuProvider : MainAPI() {
6666 } else {
6767 var title = uri.substringAfter(" $mainUrl /" )
6868 title = when {
69- (title.contains(" -episode" )) && ! (title.contains(" -movie" )) -> title.substringBefore(" -episode" )
69+ (title.contains(" -episode" )) && ! (title.contains(" -movie" )) -> title.substringBefore(
70+ " -episode"
71+ )
72+
7073 (title.contains(" -movie" )) -> title.substringBefore(" -movie" )
7174 else -> title
7275 }
76+
7377 " $mainUrl /anime/$title "
7478 }
7579 }
7680
77- private fun Element.toSearchResult (): AnimeSearchResponse ? {
78- val a = this .selectFirst(" a" ) ? : return null
79- val href = getProperAnimeLink(fixUrlNull(a.attr(" href" )).toString())
81+ private fun Element.toSearchResult (): AnimeSearchResponse {
82+ val href = getProperAnimeLink(fixUrlNull(this .selectFirst(" a" )?.attr(" href" )).toString())
8083 val title = this .select(" div.tt" ).text().trim()
8184 val posterUrl = fixUrlNull(this .selectFirst(" img" )?.getImageAttr())
8285 val epNum = this .selectFirst(" span.epx" )?.text()?.filter { it.isDigit() }?.toIntOrNull()
83-
8486 return newAnimeSearchResponse(title, href, TvType .Anime ) {
8587 this .posterUrl = posterUrl
8688 addSub(epNum)
8789 }
90+
8891 }
8992
9093 override suspend fun search (query : String ): List <SearchResponse > {
91- val document = app.get(" $mainUrl /?s=$query " ).document
92- return document.select(" div.listupd div.bs" ).mapNotNull {
93- it.toSearchResult()
94+ return app.get(" $mainUrl /?s=$query " ).document.select(" div.listupd div.bs" ).map {
95+ it.toSearchResult()
9496 }
9597 }
9698
97- override suspend fun load (url : String ): LoadResponse ? {
99+ override suspend fun load (url : String ): LoadResponse {
98100 val document = app.get(url).document
99101
100- val rawTitle = document.selectFirst( " div.infox h1 " )?.text() ? : return null
101- val title = rawTitle .replace(" Sub Indo" , " " ).trim()
102+ val title =
103+ document.selectFirst( " div.infox h1 " )?.text().toString() .replace(" Sub Indo" , " " ).trim()
102104 val poster = document.selectFirst(" div.bigcontent img" )?.getImageAttr()
103105
104106 val table = document.selectFirst(" div.infox div.spe" )
105- val typeStr = table?.selectFirst(" span:contains(Jenis:)" )?.ownText()
106- val type = getType(typeStr)
107- val year = table?.selectFirst(" span:contains(Rilis:)" )?.ownText()?.substringAfterLast(" ," )?.trim()?.toIntOrNull()
108- val statusStr = table?.selectFirst(" span:contains(Status:) font" )?.text()
109- val status = getStatus(statusStr)
110-
107+ val type = getType(table?.selectFirst(" span:contains(Jenis:)" )?.ownText())
108+ val year =
109+ table?.selectFirst(" span:contains(Rilis:)" )?.ownText()?.substringAfterLast(" ," )?.trim()
110+ ?.toIntOrNull()
111+ val status = table?.selectFirst(" span:contains(Status:) font" )?.text()
111112 val trailer = document.selectFirst(" div.trailer iframe" )?.attr(" src" )
112- val tags = table?.select(" span:contains(Genre:) a" )?.map { it.text() }
113- val plotDesc = document.select(" div.sinopsis p" ).text()
114-
115- val episodes = document.select(" ul#daftarepisode > li" ).mapNotNull {
116- val link = fixUrlNull(it.selectFirst(" a" )?.attr(" href" )) ? : return @mapNotNull null
113+ val episodes = document.select(" ul#daftarepisode > li" ).map {
114+ val link = fixUrl(it.selectFirst(" a" )!! .attr(" href" ))
117115 val name = it.selectFirst(" a" )?.text() ? : " "
118- val episode = Regex (" Episode\\ s?(\\ d+)" ).find(name)?.groupValues?.getOrNull(1 )?.toIntOrNull()
116+ val episode =
117+ Regex (" Episode\\ s?(\\ d+)" ).find(name)?.groupValues?.getOrNull(0 )?.toIntOrNull()
119118 newEpisode(link) { this .episode = episode }
120119 }.reversed()
121120
122121 val tracker = APIHolder .getTracker(listOf (title), TrackerType .getTypes(type), year, true )
123122
124123 return newAnimeLoadResponse(title, url, type) {
125- engName = title
126124 posterUrl = tracker?.image ? : poster
127125 backgroundPosterUrl = tracker?.cover
128126 this .year = year
129127 addEpisodes(DubStatus .Subbed , episodes)
130- showStatus = status
131- plot = plotDesc
132- this .tags = tags
128+ showStatus = getStatus( status)
129+ plot = document.select( " div.sinopsis p " ).text()
130+ this .tags = table?.select( " span:contains(Genre:) a " )?.map { it.text() }
133131 addTrailer(trailer)
134132 addMalId(tracker?.malId)
135133 addAniListId(tracker?.aniId?.toIntOrNull())
@@ -143,62 +141,47 @@ class AnimasuProvider : MainAPI() {
143141 callback : (ExtractorLink ) -> Unit
144142 ): Boolean {
145143 val document = app.get(data).document
146-
147- document.select(" .mobius select.mirror option" ).toList().amap { option ->
148- val rawValue = option.attr(" value" )
149- if (rawValue.isNotEmpty()) {
150- val decodedHtml = base64Decode(rawValue)
151- val iframeUrl = Jsoup .parse(decodedHtml).select(" iframe" ).attr(" src" )
152- val qualityText = option.text()
153-
154- if (iframeUrl.isNotEmpty()) {
155- loadFixedExtractor(
156- fixUrl(iframeUrl),
157- qualityText,
158- data,
159- subtitleCallback,
160- callback
161- )
162- }
163- }
144+ document.select(" .mobius > .mirror > option" ).mapNotNull {
145+ fixUrl(
146+ Jsoup .parse(base64Decode(it.attr(" value" ))).select(" iframe" ).attr(" src" )
147+ ) to it.text()
148+ }.amap { (iframe, quality) ->
149+ loadFixedExtractor(iframe, quality, " $mainUrl /" , subtitleCallback, callback)
164150 }
165151 return true
166152 }
167153
168154 private suspend fun loadFixedExtractor (
169155 url : String ,
170- qualityName : String ,
156+ quality : String? ,
171157 referer : String? = null,
172158 subtitleCallback : (SubtitleFile ) -> Unit ,
173159 callback : (ExtractorLink ) -> Unit
174160 ) {
175- val extractedQuality = qualityName.fixQuality()
176-
177161 loadExtractor(url, referer, subtitleCallback) { link ->
178- val newLink = newExtractorLink(
179- source = link.source,
180- name = " $qualityName - ${link.name} " ,
181- url = link.url,
182- type = link.type
183- ) {
184- this .referer = link.referer
185- this .quality = if (link.quality == Qualities .Unknown .value) extractedQuality else link.quality
186- this .headers = link.headers
162+ runBlocking {
163+ callback.invoke(
164+ newExtractorLink(
165+ link.name,
166+ link.name,
167+ link.url,
168+ link.type
169+ ) {
170+ this .referer = link.referer
171+ this .quality = if (link.type == ExtractorLinkType .M3U8 || link.name == " Uservideo" ) link.quality else getIndexQuality(
172+ quality
173+ )
174+ this .headers = link.headers
175+ this .extractorData = link.extractorData
176+ }
177+ )
187178 }
188- callback.invoke(newLink)
189179 }
190180 }
191181
192- private fun String.fixQuality (): Int {
193- val lower = this .lowercase()
194- return when {
195- lower.contains(" 1080" ) || lower.contains(" fhd" ) -> Qualities .P1080 .value
196- lower.contains(" 720" ) || lower.contains(" hd" ) -> Qualities .P720 .value
197- lower.contains(" 480" ) || lower.contains(" sd" ) -> Qualities .P480 .value
198- lower.contains(" 360" ) -> Qualities .P360 .value
199- else -> Regex (" (\\ d{3,4})" ).find(this )?.groupValues?.getOrNull(1 )?.toIntOrNull()
200- ? : Qualities .Unknown .value
201- }
182+ private fun getIndexQuality (str : String? ): Int {
183+ return Regex (" (\\ d{3,4})[pP]" ).find(str ? : " " )?.groupValues?.getOrNull(1 )?.toIntOrNull()
184+ ? : Qualities .Unknown .value
202185 }
203186
204187 private fun Element.getImageAttr (): String? {
@@ -209,4 +192,5 @@ class AnimasuProvider : MainAPI() {
209192 else -> this .attr(" abs:src" )
210193 }
211194 }
212- }
195+
196+ }
0 commit comments