mirror of
https://github.com/hexated/cloudstream-extensions-hexated.git
synced 2024-08-15 00:03:22 +00:00
fix some providers: Anichi, Layarkaca, Anroll, Movierulzhd
This commit is contained in:
parent
20dbd2a774
commit
1e272a0893
9 changed files with 143 additions and 50 deletions
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 4
|
||||
version = 5
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -2,12 +2,12 @@ package com.hexated
|
|||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.getTracker
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addAniListId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addMalId
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
||||
import com.lagradost.cloudstream3.extractors.helper.GogoHelper
|
||||
import com.lagradost.cloudstream3.mvvm.logError
|
||||
import com.lagradost.cloudstream3.mvvm.safeApiCall
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.parseJson
|
||||
|
@ -32,14 +32,6 @@ class Anichi : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
private fun getType(t: String?): TvType {
|
||||
return when {
|
||||
t.equals("OVA", true) || t.equals("Special") -> TvType.OVA
|
||||
t.equals("Movie", true) -> TvType.AnimeMovie
|
||||
else -> TvType.Anime
|
||||
}
|
||||
}
|
||||
|
||||
override val supportedTypes = setOf(TvType.Anime, TvType.AnimeMovie)
|
||||
|
||||
private val popularTitle = "Popular"
|
||||
|
@ -141,7 +133,6 @@ class Anichi : MainAPI() {
|
|||
val title = showData.name
|
||||
val description = showData.description
|
||||
val poster = showData.thumbnail
|
||||
val type = getType(showData.type ?: "")
|
||||
|
||||
val episodes = showData.availableEpisodesDetail.let {
|
||||
if (it == null) return@let Pair(null, null)
|
||||
|
@ -164,13 +155,12 @@ class Anichi : MainAPI() {
|
|||
Pair(Actor(name, image), role)
|
||||
}
|
||||
|
||||
val names = showData.altNames?.plus(title)?.filterNotNull() ?: emptyList()
|
||||
val trackers = getTracker(names, TrackerType.getTypes(type), showData.airedStart?.year)
|
||||
val trackers = getTracker(title, showData.altNames?.firstOrNull(), showData.airedStart?.year, showData.season?.quarter, showData.type)
|
||||
|
||||
return newAnimeLoadResponse(title ?: "", url, TvType.Anime) {
|
||||
engName = showData.altNames?.firstOrNull()
|
||||
posterUrl = trackers?.image ?: poster
|
||||
backgroundPosterUrl = trackers?.cover ?: showData.banner
|
||||
posterUrl = trackers?.coverImage?.extraLarge ?: trackers?.coverImage?.large ?: poster
|
||||
backgroundPosterUrl = trackers?.bannerImage ?: showData.banner
|
||||
rating = showData.averageScore?.times(100)
|
||||
tags = showData.genres
|
||||
year = showData.airedStart?.year
|
||||
|
@ -184,8 +174,8 @@ class Anichi : MainAPI() {
|
|||
//this.recommendations = recommendations
|
||||
|
||||
showStatus = getStatus(showData.status.toString())
|
||||
addMalId(trackers?.malId)
|
||||
addAniListId(trackers?.aniId?.toIntOrNull())
|
||||
addMalId(trackers?.idMal)
|
||||
addAniListId(trackers?.id)
|
||||
plot = description?.replace(Regex("""<(.*?)>"""), "")
|
||||
}
|
||||
}
|
||||
|
@ -273,6 +263,14 @@ class Anichi : MainAPI() {
|
|||
isDash = server.resolutionStr == "Dash 1"
|
||||
)
|
||||
)
|
||||
server.subtitles?.map { sub ->
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
SubtitleHelper.fromTwoLettersToLanguage(sub.lang ?: "") ?: sub.lang ?: "",
|
||||
httpsify(sub.src ?: return@map)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -315,7 +313,8 @@ class Anichi : MainAPI() {
|
|||
return meta.map { eps ->
|
||||
Episode(
|
||||
AnichiLoadData(id, lang, eps).toJson(),
|
||||
"Ep $eps"
|
||||
"Ep $eps",
|
||||
episode = eps.toIntOrNull()
|
||||
)
|
||||
}.reversed()
|
||||
}
|
||||
|
@ -382,6 +381,69 @@ class Anichi : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
private suspend fun getTracker(name: String?, altName: String?, year: Int?, season: String?, type: String?): AniMedia? {
|
||||
val ids = fetchId(name, year, season, type)
|
||||
return if (ids?.id == null && ids?.idMal == null) fetchId(
|
||||
altName,
|
||||
year,
|
||||
season,
|
||||
type
|
||||
) else ids
|
||||
}
|
||||
|
||||
private suspend fun fetchId(title: String?, year: Int?, season: String?, type: String?): AniMedia? {
|
||||
val query = """
|
||||
query (
|
||||
${'$'}page: Int = 1
|
||||
${'$'}search: String
|
||||
${'$'}sort: [MediaSort] = [POPULARITY_DESC, SCORE_DESC]
|
||||
${'$'}type: MediaType
|
||||
${'$'}season: MediaSeason
|
||||
${'$'}year: String
|
||||
${'$'}format: [MediaFormat]
|
||||
) {
|
||||
Page(page: ${'$'}page, perPage: 20) {
|
||||
media(
|
||||
search: ${'$'}search
|
||||
sort: ${'$'}sort
|
||||
type: ${'$'}type
|
||||
season: ${'$'}season
|
||||
startDate_like: ${'$'}year
|
||||
format_in: ${'$'}format
|
||||
) {
|
||||
id
|
||||
idMal
|
||||
coverImage { extraLarge large }
|
||||
bannerImage
|
||||
}
|
||||
}
|
||||
}
|
||||
""".trimIndent().trim()
|
||||
|
||||
val variables = mapOf(
|
||||
"search" to title,
|
||||
"sort" to "SEARCH_MATCH",
|
||||
"type" to "ANIME",
|
||||
"season" to if(type.equals("ona", true)) "" else season?.uppercase(),
|
||||
"year" to "$year%",
|
||||
"format" to listOf(type?.uppercase())
|
||||
).filterValues { value -> value != null && value.toString().isNotEmpty() }
|
||||
|
||||
val data = mapOf(
|
||||
"query" to query,
|
||||
"variables" to variables
|
||||
).toJson().toRequestBody(RequestBodyTypes.JSON.toMediaTypeOrNull())
|
||||
|
||||
return try {
|
||||
app.post("https://graphql.anilist.co", requestBody = data)
|
||||
.parsedSafe<AniSearch>()?.data?.Page?.media?.firstOrNull()
|
||||
} catch (t: Throwable) {
|
||||
logError(t)
|
||||
null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val apiUrl = BuildConfig.ANICHI_API
|
||||
private const val serverUrl = BuildConfig.ANICHI_SERVER
|
||||
|
@ -406,6 +468,30 @@ class Anichi : MainAPI() {
|
|||
val episode: String
|
||||
)
|
||||
|
||||
data class CoverImage(
|
||||
@JsonProperty("extraLarge") var extraLarge: String? = null,
|
||||
@JsonProperty("large") var large: String? = null,
|
||||
)
|
||||
|
||||
data class AniMedia(
|
||||
@JsonProperty("id") var id: Int? = null,
|
||||
@JsonProperty("idMal") var idMal: Int? = null,
|
||||
@JsonProperty("coverImage") var coverImage: CoverImage? = null,
|
||||
@JsonProperty("bannerImage") var bannerImage: String? = null,
|
||||
)
|
||||
|
||||
data class AniPage(
|
||||
@JsonProperty("media") var media: ArrayList<AniMedia> = arrayListOf()
|
||||
)
|
||||
|
||||
data class AniData(
|
||||
@JsonProperty("Page") var Page: AniPage? = AniPage()
|
||||
)
|
||||
|
||||
data class AniSearch(
|
||||
@JsonProperty("data") var data: AniData? = AniData()
|
||||
)
|
||||
|
||||
data class AkIframe(
|
||||
@JsonProperty("idUrl") val idUrl: String? = null,
|
||||
)
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 1
|
||||
version = 2
|
||||
|
||||
cloudstream {
|
||||
language = "pt-pt"
|
||||
|
|
|
@ -35,7 +35,7 @@ class Anroll : MainAPI() {
|
|||
): HomePageResponse {
|
||||
val document = app.get("$mainUrl/home").document
|
||||
val home = mutableListOf<HomePageList>()
|
||||
document.select("div.sc-f5d5b250-1.iJHcsI").map { div ->
|
||||
document.select("div.hAbQAe").map { div ->
|
||||
val header = div.selectFirst("h2")?.text() ?: return@map
|
||||
val child = HomePageList(
|
||||
header,
|
||||
|
@ -91,11 +91,11 @@ class Anroll : MainAPI() {
|
|||
val fixUrl = getProperAnimeLink(url) ?: throw ErrorLoadingException()
|
||||
val document = app.get(fixUrl).document
|
||||
|
||||
val article = document.selectFirst("article.sc-f5d5b250-9") ?: return null
|
||||
val article = document.selectFirst("article.animedetails") ?: return null
|
||||
val title = article.selectFirst("h2")?.text() ?: return null
|
||||
val poster = fixUrlNull(document.select("article.sc-f5d5b250-8 img").attr("src"))
|
||||
val poster = fixUrlNull(document.select("section.animecontent img").attr("src"))
|
||||
val tags = article.select("div#generos a").map { it.text() }
|
||||
val year = article.selectFirst("div.sc-f5d5b250-4")?.nextElementSibling()?.text()
|
||||
val year = article.selectFirst("div.dfuefM")?.nextElementSibling()?.text()
|
||||
?.toIntOrNull()
|
||||
val description = document.select("div.sinopse").text().trim()
|
||||
val type = if (fixUrl.contains("/a/")) TvType.Anime else TvType.AnimeMovie
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 13
|
||||
version = 14
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -6,11 +6,10 @@ import com.lagradost.cloudstream3.LoadResponse.Companion.addTrailer
|
|||
import com.lagradost.cloudstream3.utils.*
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URLDecoder
|
||||
import java.net.URI
|
||||
|
||||
class LayarKacaProvider : MainAPI() {
|
||||
override var mainUrl = "https://d21.fun"
|
||||
private var seriesUrl = "https://tv.nontondrama.click"
|
||||
override var mainUrl = "https://tv.lk21official.pro"
|
||||
private var seriesUrl = "https://tv1.nontondrama.click"
|
||||
override var name = "LayarKaca"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
|
@ -57,7 +56,7 @@ class LayarKacaProvider : MainAPI() {
|
|||
private fun Element.toSearchResult(): SearchResponse? {
|
||||
val title = this.selectFirst("h1.grid-title > a")?.ownText()?.trim() ?: return null
|
||||
val href = fixUrl(this.selectFirst("a")!!.attr("href"))
|
||||
val posterUrl = fixUrlNull(this.selectFirst(".grid-poster > a > img")?.attr("src"))
|
||||
val posterUrl = fixUrlNull(this.selectFirst("img")?.attr("src"))
|
||||
val type =
|
||||
if (this.selectFirst("div.last-episode") == null) TvType.Movie else TvType.TvSeries
|
||||
return if (type == TvType.TvSeries) {
|
||||
|
@ -176,33 +175,34 @@ class LayarKacaProvider : MainAPI() {
|
|||
it
|
||||
}
|
||||
}
|
||||
invokeCast(link, callback)
|
||||
loadExtractor(link, bananalicious, subtitleCallback, callback)
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
private suspend fun invokeCast(
|
||||
url: String,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val response = app.get(url, referer = bananalicious).document
|
||||
response.select("script[type=text/javascript]").map { script ->
|
||||
if (script.data().contains(Regex("eval\\(function\\(p,a,c,k,e,[rd]"))) {
|
||||
val unpackedscript = getAndUnpack(script.data())
|
||||
val m3u8Regex = Regex("file.\"(.*?m3u8.*?)\"")
|
||||
val m3u8 = m3u8Regex.find(unpackedscript)?.destructured?.component1() ?: ""
|
||||
if (m3u8.isNotEmpty()) {
|
||||
M3u8Helper.generateM3u8(
|
||||
fixTitle(URI(url).host).substringBefore("."),
|
||||
m3u8,
|
||||
mainUrl
|
||||
).forEach(callback)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun decode(input: String): String = URLDecoder.decode(input, "utf-8").replace(" ", "%20")
|
||||
|
||||
}
|
||||
|
||||
open class Emturbovid : ExtractorApi() {
|
||||
override val name = "Emturbovid"
|
||||
override val mainUrl = "https://emturbovid.com"
|
||||
override val requiresReferer = true
|
||||
|
||||
override suspend fun getUrl(
|
||||
url: String,
|
||||
referer: String?,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val response = app.get(url, referer = referer)
|
||||
val m3u8 = Regex("[\"'](.*?master\\.m3u8.*?)[\"']").find(response.text)?.groupValues?.getOrNull(1)
|
||||
M3u8Helper.generateM3u8(
|
||||
name,
|
||||
m3u8 ?: return,
|
||||
mainUrl
|
||||
).forEach(callback)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -10,5 +10,6 @@ class LayarKacaProviderPlugin: Plugin() {
|
|||
override fun load(context: Context) {
|
||||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(LayarKacaProvider())
|
||||
registerExtractorAPI(Emturbovid())
|
||||
}
|
||||
}
|
|
@ -11,6 +11,11 @@ import kotlin.random.Random
|
|||
|
||||
const val twoEmbedAPI = "https://www.2embed.to"
|
||||
|
||||
class Sbnmp : Sbflix() {
|
||||
override val name = "Sbnmp"
|
||||
override var mainUrl = "https://sbnmp.bar"
|
||||
}
|
||||
|
||||
class Sbrulz : Sbflix() {
|
||||
override val name = "Sbrulz"
|
||||
override var mainUrl = "https://sbrulz.xyz"
|
||||
|
|
|
@ -13,5 +13,6 @@ class MovierulzhdPlugin: Plugin() {
|
|||
registerExtractorAPI(Sbflix())
|
||||
registerExtractorAPI(Sbrulz())
|
||||
registerExtractorAPI(Sbmiz())
|
||||
registerExtractorAPI(Sbnmp())
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue