mirror of
				https://github.com/hexated/cloudstream-extensions-hexated.git
				synced 2024-08-15 00:03:22 +00:00 
			
		
		
		
	fixed Oploverz
This commit is contained in:
		
							parent
							
								
									a5fec0f77e
								
							
						
					
					
						commit
						541736305d
					
				
					 2 changed files with 125 additions and 163 deletions
				
			
		|  | @ -1,5 +1,5 @@ | |||
| // use an integer for version numbers | ||||
| version = 18 | ||||
| version = 19 | ||||
| 
 | ||||
| 
 | ||||
| cloudstream { | ||||
|  |  | |||
|  | @ -1,11 +1,8 @@ | |||
| package com.hexated | ||||
| 
 | ||||
| import com.fasterxml.jackson.annotation.JsonProperty | ||||
| import com.lagradost.cloudstream3.* | ||||
| import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer | ||||
| import com.lagradost.cloudstream3.extractors.Filesim | ||||
| import com.lagradost.cloudstream3.utils.* | ||||
| import org.jsoup.Jsoup | ||||
| import org.jsoup.nodes.Element | ||||
| 
 | ||||
| class OploverzProvider : MainAPI() { | ||||
|  | @ -23,159 +20,120 @@ class OploverzProvider : MainAPI() { | |||
| 
 | ||||
|     companion object { | ||||
|         const val acefile = "https://acefile.co" | ||||
|         const val lbx = "https://lbx.to" | ||||
|         const val linkbox = "https://www.linkbox.to" | ||||
| 
 | ||||
|         fun getType(t: String): TvType { | ||||
|             return when { | ||||
|                 t.contains("TV") -> TvType.Anime | ||||
|                 t.contains("Movie") -> TvType.AnimeMovie | ||||
|                 else -> TvType.OVA | ||||
|             } | ||||
|             return if (t.contains("OVA", true) || t.contains("Special")) TvType.OVA | ||||
|             else if (t.contains("Movie", true)) TvType.AnimeMovie | ||||
|             else TvType.Anime | ||||
|         } | ||||
| 
 | ||||
|         fun getStatus(t: String): ShowStatus { | ||||
|         fun getStatus(t: String?): ShowStatus { | ||||
|             return when (t) { | ||||
|                 "Finished Airing" -> ShowStatus.Completed | ||||
|                 "Completed" -> ShowStatus.Completed | ||||
|                 "Currently Airing" -> ShowStatus.Ongoing | ||||
|                 "Ongoing" -> ShowStatus.Ongoing | ||||
|                 else -> ShowStatus.Completed | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     override val mainPage = mainPageOf( | ||||
|         "&status=&type=&order=update" to "Episode Terbaru", | ||||
|         "&status=&type=&order=latest" to "Anime Terbaru", | ||||
|         "&sub=&order=popular" to "Popular Anime", | ||||
|         "update" to "Latest Update", | ||||
|         "latest" to "Latest Added", | ||||
|         "popular" to "Popular Anime", | ||||
|         "rating" to "Top Rated", | ||||
|     ) | ||||
| 
 | ||||
|     override suspend fun getMainPage( | ||||
|         page: Int, | ||||
|         request: MainPageRequest | ||||
|     ): HomePageResponse { | ||||
|         val document = app.get("$mainUrl/anime/?page=$page${request.data}").document | ||||
|         val home = document.select("article[itemscope=itemscope]").mapNotNull { | ||||
|         val document = app.get("$mainUrl/anime-list/page/$page/?title&order=${request.data}&status&type").document | ||||
|         val home = document.select("div.relat > article").mapNotNull { | ||||
|             it.toSearchResult() | ||||
|         } | ||||
|         return newHomePageResponse(request.name, home) | ||||
|     } | ||||
| 
 | ||||
|     private fun getProperAnimeLink(uri: String): String { | ||||
| 
 | ||||
|         return if (uri.contains("/anime/")) { | ||||
|             uri | ||||
|         } else { | ||||
|             var title = uri.substringAfter("$mainUrl/") | ||||
|             title = when { | ||||
|                 (title.contains("-episode")) && !(title.contains("-ova")) -> Regex("(.+)-episode").find( | ||||
|                 (title.contains("-episode")) && !(title.contains("-movie")) -> Regex("(.+)-episode").find( | ||||
|                     title | ||||
|                 )?.groupValues?.get(1).toString() | ||||
|                 (title.contains("-ova")) -> Regex("(.+)-ova").find(title)?.groupValues?.get(1) | ||||
|                     .toString() | ||||
|                 (title.contains("-movie")) -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1) | ||||
|                     .toString() | ||||
|                 else -> Regex("(.+)-subtitle").find(title)?.groupValues?.get(1).toString() | ||||
|                     .replace(Regex("-\\d+"), "") | ||||
|                 (title.contains("-movie")) -> Regex("(.+)-movie").find(title)?.groupValues?.get( | ||||
|                     1 | ||||
|                 ).toString() | ||||
|                 else -> title | ||||
|             } | ||||
| 
 | ||||
|             when { | ||||
|                 title.contains("overlord") -> { | ||||
|                     title = title.replace("s", "season-") | ||||
|                 } | ||||
|                 title.contains("kaguya-sama") -> { | ||||
|                     title = title.replace("s3", "ultra-romantic") | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|             "$mainUrl/anime/$title" | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     private fun Element.toSearchResult(): AnimeSearchResponse? { | ||||
|         val href = getProperAnimeLink(this.selectFirst("a.tip")!!.attr("href")) | ||||
|         val title = this.selectFirst("h2[itemprop=headline]")?.text()?.trim() ?: return null | ||||
|         val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src")) | ||||
|         val type = getType(this.selectFirst(".eggtype, .typez")?.text()?.trim().toString()) | ||||
| 
 | ||||
|         val title = this.selectFirst("div.title")?.text()?.trim() ?: return null | ||||
|         val href = getProperAnimeLink(this.selectFirst("a")!!.attr("href")) | ||||
|         val posterUrl = this.select("img[itemprop=image]").attr("src").toString() | ||||
|         val type = getType(this.select("div.type").text().trim()) | ||||
|         val epNum = | ||||
|             this.selectFirst("span.episode")?.ownText()?.replace(Regex("\\D"), "")?.trim() | ||||
|                 ?.toIntOrNull() | ||||
|         return newAnimeSearchResponse(title, href, type) { | ||||
|             this.posterUrl = posterUrl | ||||
|             addSub(epNum) | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun search(query: String): List<SearchResponse> { | ||||
|         val link = "$mainUrl/?s=$query" | ||||
|         val document = app.get(link).document | ||||
| 
 | ||||
|         return document.select("article[itemscope=itemscope]").map { | ||||
|             val title = it.selectFirst(".tt")?.ownText()?.trim().toString() | ||||
|             val poster = fixUrlNull(it.selectFirst("img")?.attr("src")) | ||||
|             val tvType = getType(it.selectFirst(".typez")?.text().toString()) | ||||
|             val href = fixUrl(it.selectFirst("a.tip")!!.attr("href")) | ||||
| 
 | ||||
|             newAnimeSearchResponse(title, href, tvType) { | ||||
|                 this.posterUrl = poster | ||||
|                 addDubStatus(dubExist = false, subExist = true) | ||||
|         val anime = mutableListOf<SearchResponse>() | ||||
|         (1..2).forEach { page -> | ||||
|             val link = "$mainUrl/page/$page/?s=$query" | ||||
|             val document = app.get(link).document | ||||
|             val media = document.select(".site-main.relat > article").mapNotNull { | ||||
|                 val title = it.selectFirst("div.title > h2")!!.ownText().trim() | ||||
|                 val href = it.selectFirst("a")!!.attr("href") | ||||
|                 val posterUrl = it.selectFirst("img")!!.attr("src").toString() | ||||
|                 val type = getType(it.select("div.type").text().trim()) | ||||
|                 newAnimeSearchResponse(title, href, type) { | ||||
|                     this.posterUrl = posterUrl | ||||
|                 } | ||||
|             } | ||||
|             if(media.isNotEmpty()) anime.addAll(media) | ||||
|         } | ||||
|         return anime | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun load(url: String): LoadResponse { | ||||
|         val document = app.get(url).document | ||||
| 
 | ||||
|         val title = document.selectFirst("h1.entry-title")!!.text().trim() | ||||
|         val poster = document.select(".thumb > img").attr("src") | ||||
|         val tags = document.select(".genxed > a").map { it.text() } | ||||
|         val title = document.selectFirst("h1.entry-title")?.text() | ||||
|             ?.replace("Subtitle Indonesia", "")?.trim() ?: "" | ||||
|         val type = document.selectFirst("div.alternati span.type")?.text() ?: "" | ||||
| 
 | ||||
|         val year = Regex("\\d, (\\d*)").find( | ||||
|             document.selectFirst(".info-content > .spe > span > time")!!.text().trim() | ||||
|         )?.groupValues?.get(1).toString().toIntOrNull() | ||||
|         val status = getStatus( | ||||
|             document.select(".info-content > .spe > span:nth-child(1)") | ||||
|                 .text().trim().replace("Status: ", "") | ||||
|         ) | ||||
|         val typeCheck = | ||||
|             when (document.select(".info-content > .spe > span:nth-child(5), .info-content > .spe > span") | ||||
|                 .text().trim()) { | ||||
|                 "OVA" -> "OVA" | ||||
|                 "Movie" -> "Movie" | ||||
|                 else -> "TV" | ||||
|             } | ||||
|         val description = document.select(".entry-content > p").text().trim() | ||||
|         val trailer = document.selectFirst("a.trailerbutton")?.attr("href") | ||||
| 
 | ||||
|         val episodes = document.select(".eplister > ul > li").map { | ||||
|             val link = fixUrl(it.select("a").attr("href")) | ||||
|             val name = it.select(".epl-title").text() | ||||
|             val episode = Regex("Episode\\s?(\\d+[.,]?\\d*)").find(name)?.groupValues?.getOrNull(1)?.toIntOrNull() | ||||
|             Episode(link, name, episode = episode) | ||||
|         val episodes = document.select("div.lstepsiode.listeps ul li").mapNotNull { | ||||
|             val header = it.selectFirst("a") ?: return@mapNotNull null | ||||
|             val episode = header.text().trim().toIntOrNull() | ||||
|             val link = fixUrl(header.attr("href")) | ||||
|             Episode(link, header.text(), episode = episode) | ||||
|         }.reversed() | ||||
| 
 | ||||
|         val recommendations = | ||||
|             document.select(".listupd > article[itemscope=itemscope]").mapNotNull { rec -> | ||||
|                 val epTitle = rec.selectFirst(".tt")!!.ownText().trim() | ||||
|                 val epPoster = rec.selectFirst("img")!!.attr("src") | ||||
|                 val epType = getType(rec.selectFirst(".typez")?.text().toString()) | ||||
|                 val epHref = fixUrl(rec.selectFirst("a.tip")!!.attr("href")) | ||||
| 
 | ||||
|                 newAnimeSearchResponse(epTitle, epHref, epType) { | ||||
|                     this.posterUrl = epPoster | ||||
|                     addDubStatus(dubExist = false, subExist = true) | ||||
|                 } | ||||
|             } | ||||
| 
 | ||||
|         return newAnimeLoadResponse(title, url, getType(typeCheck)) { | ||||
|             engName = title | ||||
|             posterUrl = poster | ||||
|             this.year = year | ||||
|         return newAnimeLoadResponse(title, url, getType(type)) { | ||||
|             posterUrl = document.selectFirst("div.thumb > img")?.attr("src") | ||||
|             this.year = document.selectFirst("div.alternati a")?.text()?.filter { it.isDigit() }?.toIntOrNull() | ||||
|             addEpisodes(DubStatus.Subbed, episodes) | ||||
|             showStatus = status | ||||
|             plot = description | ||||
|             this.tags = tags | ||||
|             this.recommendations = recommendations | ||||
|             addTrailer(trailer) | ||||
|             showStatus = | ||||
|                 getStatus( | ||||
|                     document.selectFirst("div.alternati span:nth-child(2)")?.text()?.trim() | ||||
|                 ) | ||||
|             plot = document.selectFirst("div.entry-content > p")?.text()?.trim() | ||||
|             this.tags = | ||||
|                 document.select("div.genre-info a").map { it.text() } | ||||
|         } | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
|     override suspend fun loadLinks( | ||||
|  | @ -184,78 +142,82 @@ class OploverzProvider : MainAPI() { | |||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ): Boolean { | ||||
|         val document = app.get(data).document | ||||
|         val sources = mutableListOf<Pair<String?, String>>() | ||||
|         val streamingSources = document.select(".mobius > .mirror > option").mapNotNull { | ||||
|             "" to fixUrl(Jsoup.parse(base64Decode(it.attr("value"))).select("iframe").attr("src")) | ||||
|         } | ||||
|         if (streamingSources.isNotEmpty()) sources.addAll(streamingSources) | ||||
|         val downloadSources = | ||||
|             document.select("div.mctnx div.soraurlx").mapNotNull { item -> | ||||
|                 item.select("a").map { item.select("strong").text() to it.attr("href") } | ||||
|             }.flatten() | ||||
|         if (downloadSources.isNotEmpty()) sources.addAll(downloadSources) | ||||
| 
 | ||||
|         sources.filter { it.second.startsWith("https") }. | ||||
|         apmap { (quality, source) -> | ||||
|             val video = fixedIframe(source) | ||||
|             val videoQuality = getQualityFromName(quality) | ||||
|             if(video.endsWith(".mp4") || video.endsWith(".mkv")) { | ||||
|                 callback.invoke( | ||||
|                     ExtractorLink( | ||||
|                         "Direct", | ||||
|                         "Direct", | ||||
|                         video, | ||||
|                         "", | ||||
|                         videoQuality | ||||
|                     ) | ||||
|                 ) | ||||
|             } else { | ||||
|                 loadExtractor(video, data, subtitleCallback) { link -> | ||||
|                     callback.invoke( | ||||
|                         ExtractorLink( | ||||
|                             link.name, | ||||
|                             link.name, | ||||
|                             link.url, | ||||
|                             link.referer, | ||||
|                             videoQuality, | ||||
|                             link.isM3u8, | ||||
|                             link.headers, | ||||
|                             link.extractorData | ||||
|                         ) | ||||
|                     ) | ||||
|         val document = app.get(data).document | ||||
| 
 | ||||
|         argamap( | ||||
|             { | ||||
|                 document.select("div#server ul li div").apmap { | ||||
|                     val dataPost = it.attr("data-post") | ||||
|                     val dataNume = it.attr("data-nume") | ||||
|                     val dataType = it.attr("data-type") | ||||
| 
 | ||||
|                     val iframe = app.post( | ||||
|                         url = "$mainUrl/wp-admin/admin-ajax.php", | ||||
|                         data = mapOf( | ||||
|                             "action" to "player_ajax", | ||||
|                             "post" to dataPost, | ||||
|                             "nume" to dataNume, | ||||
|                             "type" to dataType | ||||
|                         ), | ||||
|                         referer = data, | ||||
|                         headers = mapOf("X-Requested-With" to "XMLHttpRequest") | ||||
|                     ).document.select("iframe").attr("src") | ||||
| 
 | ||||
|                     loadExtractor(fixedIframe(iframe), "$mainUrl/", subtitleCallback, callback) | ||||
| 
 | ||||
|                 } | ||||
|             }, | ||||
|             { | ||||
|                 document.select("div#download tr").map { el -> | ||||
|                     el.select("a").apmap { | ||||
|                         loadFixedExtractor(fixedIframe(it.attr("href")), el.select("strong").text(), "$mainUrl/", subtitleCallback, callback) | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         ) | ||||
| 
 | ||||
|         return true | ||||
|     } | ||||
| 
 | ||||
|     private suspend fun fixedIframe(url: String): String { | ||||
|         val id = Regex("""(?:/f/|/file/)(\w+)""").find(url)?.groupValues?.getOrNull(1) | ||||
|         return when { | ||||
|             url.startsWith(acefile) -> "$acefile/player/$id" | ||||
|             url.startsWith(lbx) -> { | ||||
|                 val itemId = app.get("$linkbox/api/file/share_out_list/?sortField=utime&sortAsc=0&pageNo=1&pageSize=50&shareToken=$id&scene=singleItem&needTpInfo=1&lan=en").parsedSafe<Responses>()?.data?.itemId | ||||
|                 "$linkbox/a/f/$itemId" | ||||
|             } | ||||
|             else -> url | ||||
|     private suspend fun loadFixedExtractor( | ||||
|         url: String, | ||||
|         name: String, | ||||
|         referer: String? = null, | ||||
|         subtitleCallback: (SubtitleFile) -> Unit, | ||||
|         callback: (ExtractorLink) -> Unit | ||||
|     ) { | ||||
|         loadExtractor(url, referer, subtitleCallback) { link -> | ||||
|             callback.invoke( | ||||
|                 ExtractorLink( | ||||
|                     link.name, | ||||
|                     link.name, | ||||
|                     link.url, | ||||
|                     link.referer, | ||||
|                     name.fixQuality(), | ||||
|                     link.isM3u8, | ||||
|                     link.headers, | ||||
|                     link.extractorData | ||||
|                 ) | ||||
|             ) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     data class RList( | ||||
|         @JsonProperty("url") val url: String, | ||||
|         @JsonProperty("resolution") val resolution: String?, | ||||
|     ) | ||||
|     private fun String.fixQuality() : Int { | ||||
|         return when(this) { | ||||
|             "MP4HD" -> Qualities.P720.value | ||||
|             "FULLHD" -> Qualities.P1080.value | ||||
|             else -> Regex("(\\d{3,4})p").find(this)?.groupValues?.get(1)?.toIntOrNull() ?: Qualities.Unknown.value | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     data class Data( | ||||
|         @JsonProperty("rList") val rList: List<RList>? = arrayListOf(), | ||||
|         @JsonProperty("itemId") val itemId: String? = null, | ||||
|     ) | ||||
| 
 | ||||
|     data class Responses( | ||||
|         @JsonProperty("data") val data: Data?, | ||||
|     ) | ||||
|     private fun fixedIframe(url: String): String { | ||||
|         val id = Regex("""(?:/f/|/file/)(\w+)""").find(url)?.groupValues?.getOrNull(1) | ||||
|         return when { | ||||
|             url.startsWith(acefile) -> "${acefile}/player/$id" | ||||
|             else -> fixUrl(url) | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue