diff --git a/ElOstora/build.gradle.kts b/ElOstora/build.gradle.kts index 114c318a..504d476d 100644 --- a/ElOstora/build.gradle.kts +++ b/ElOstora/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 4 +version = 5 cloudstream { diff --git a/ElOstora/src/main/kotlin/com/elostoratv/ElOstoraTV.kt b/ElOstora/src/main/kotlin/com/elostoratv/ElOstoraTV.kt index 2af88e17..f2001f7d 100644 --- a/ElOstora/src/main/kotlin/com/elostoratv/ElOstoraTV.kt +++ b/ElOstora/src/main/kotlin/com/elostoratv/ElOstoraTV.kt @@ -4,7 +4,6 @@ import android.icu.util.Calendar import android.util.Log import com.fasterxml.jackson.annotation.JsonProperty import com.lagradost.cloudstream3.* -import com.lagradost.cloudstream3.ui.player.RepoLinkGenerator import com.lagradost.cloudstream3.utils.AppUtils.parseJson import com.lagradost.cloudstream3.utils.AppUtils.toJson import com.lagradost.cloudstream3.utils.DrmExtractorLink @@ -24,7 +23,7 @@ class ElOstoraTV : MainAPI() { setOf( TvType.Live ) - private val APIurl = "https://z420572.radwan.shop/api/v4_8.php" + private val apiUrl = "https://z420572.radwan.shop/api/v4_8.php" //override val mainPage = generateHomePage() override val mainPage = generateServersHomePage() @@ -34,10 +33,10 @@ class ElOstoraTV : MainAPI() { "main" to "1", "id" to "", ) - val decodedbody = getDecoded(data) - //Log.d("King", "decodedbody:$decodedbody") + val decodedBody = getDecoded(data) + //Log.d("King", "decodedBody:decodedBody") - parseJson(decodedbody).results?.map { element -> + parseJson(decodedBody).results?.map { element -> homepage.add(mainPage(name = element.category_name, url = element.cid)) } ?: throw ErrorLoadingException("Invalid Json response") //Log.d("King", "homepage:$homepage") @@ -52,9 +51,9 @@ class ElOstoraTV : MainAPI() { "id" to "", "sub_id" to "0" ) - val decodedbody = getDecoded(data) - //Log.d("King", "getMaindecodedbody:$decodedbody") - val list = parseJson(decodedbody).results?.map { element -> + val decodedBody = getDecoded(data) + //Log.d("King", "getMainDecodedBody:decodedBody") + val list = parseJson(decodedBody).results?.map { element -> element.toSearchResponse(request) } ?: throw ErrorLoadingException("Invalid Json response") if (list.isNotEmpty()) items.add(HomePageList(request.name, list, false)) @@ -75,13 +74,13 @@ class ElOstoraTV : MainAPI() { Log.d("King", "Load:$url") val data = parseJson(url) - val Postdata = mapOf( + val postData = mapOf( "id" to "", "cat_id" to data.id ) - val decodedbody = getDecoded(Postdata) - Log.d("King", "decodedbody:$decodedbody") - var channels = parseJson(decodedbody).results?.map { element -> + val decodedBody = getDecoded(postData) + Log.d("King", "decodedBody:$decodedBody") + var channels = parseJson(decodedBody).results?.map { element -> Episode( name = element.channel_title, posterUrl = element.channel_thumbnail, @@ -121,11 +120,9 @@ class ElOstoraTV : MainAPI() { callback: (ExtractorLink) -> Unit ): Boolean { Log.d("King", "loadLinks:$data") - val data = parseJson(data) + val parsedData = parseJson(data) - var fullUrl = fixUrl(data.channel_url) - var key: String = "" - var kid: String = "" + val fullUrl = fixUrl(parsedData.channel_url) val encrypted : Boolean = fullUrl.contains("###") Log.d("King", "fullUrl:$fullUrl") @@ -133,29 +130,36 @@ class ElOstoraTV : MainAPI() { { Log.d("King", "encrypted") val suffix = fullUrl.split("###")[1].split(":") - key = suffix[0] - kid = suffix[1] - fullUrl = fullUrl.split("###")[0] - Log.d("King", "fullUrl:$fullUrl") + val key = suffix[0] + val kid = suffix[1] + val mediaUrl = fullUrl.split("###")[0] + Log.d("King", "mediaUrl:$mediaUrl") Log.d("King", "key:$key") Log.d("King", "kid:$kid") - DrmExtractorLink( - source = data.channel_title, - name = data.channel_title, - url = fullUrl, - referer = "", - quality = Qualities.Unknown.value, - key = key, - kid = kid, - kty = "oct", - type = INFER_TYPE, + callback.invoke( + DrmExtractorLink( + source = parsedData.channel_title, + name = parsedData.channel_title, + url = mediaUrl, + referer = "", + quality = Qualities.Unknown.value, + key = key, + kid = kid, + type = INFER_TYPE, + headers = mapOf( + "Accept-Encoding" to "identity", + "Connection" to "Keep-Alive", + "Host" to "cdxaws-ak.akamaized.net", + "User-Agent" to "Url-Player" + ) + ) ) return true } callback.invoke( ExtractorLink( - source = data.channel_title, - name = data.channel_title, + source = parsedData.channel_title, + name = parsedData.channel_title, url = fullUrl, referer = "", quality = Qualities.Unknown.value, @@ -177,17 +181,16 @@ class ElOstoraTV : MainAPI() { val request = requestCreator( method = "POST", - url = APIurl, + url = apiUrl, headers = mapOf( - "user-agent" to "Mozilla/5.0 (Linux; U; Android 10; en; YAL-L41 Api/HUAWEIYAL-L41) AppleWebKit/534.30 (KHTML, like Gecko) Version/5.0 Mobile Safari/534.30", + "user-agent" to USER_AGENT, "Time" to t, ), data = payload, ) val req = client.newCall(request).execute() - val decryptedBody = decrypt(req.body.string(), t.toCharArray()) - //Log.d("King", "decryptedBody:" + decryptedBody) - return decryptedBody + + return decrypt(req.body.string(), t.toCharArray()) } private fun decrypt(str: String, key: CharArray): String { diff --git a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt index 933475ca..9fd2a209 100644 --- a/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt +++ b/SoraStream/src/main/kotlin/com/hexated/SoraExtractor.kt @@ -15,6 +15,8 @@ import okhttp3.RequestBody.Companion.toRequestBody import okio.ByteString.Companion.encode import org.jsoup.Jsoup import org.jsoup.nodes.Document +import com.lagradost.cloudstream3.utils.INFER_TYPE + val session = Session(Requests().baseClient) @@ -123,9 +125,9 @@ object SoraExtractor : SoraStream() { link.url, link.referer, if (link.name == "VidSrc") Qualities.P1080.value else link.quality, - link.isM3u8, link.headers, - link.extractorData + link.extractorData, + type = INFER_TYPE, ) ) } @@ -269,7 +271,7 @@ object SoraExtractor : SoraStream() { video.url, video.referer, Qualities.P1080.value, - video.isM3u8, + type = INFER_TYPE, video.headers, video.extractorData ) @@ -339,7 +341,7 @@ object SoraExtractor : SoraStream() { link.url, link.referer, Qualities.P1080.value, - link.isM3u8, + type = INFER_TYPE, link.headers, link.extractorData ) diff --git a/YacienTVProvider/build.gradle.kts b/YacienTVProvider/build.gradle.kts index 27d450f7..d42ee395 100644 --- a/YacienTVProvider/build.gradle.kts +++ b/YacienTVProvider/build.gradle.kts @@ -1,5 +1,5 @@ // use an integer for version numbers -version = 3 +version = 4 cloudstream { diff --git a/YacienTVProvider/src/main/kotlin/com/yacientv/YacienTVProvider.kt b/YacienTVProvider/src/main/kotlin/com/yacientv/YacienTVProvider.kt index 9e7da3cb..c851c9cd 100644 --- a/YacienTVProvider/src/main/kotlin/com/yacientv/YacienTVProvider.kt +++ b/YacienTVProvider/src/main/kotlin/com/yacientv/YacienTVProvider.kt @@ -22,10 +22,10 @@ class YacienTV : MainAPI() { TvType.Live ) private val yacienTVAPI = "http://ver3.yacinelive.com/api" - private val mainkey = "YyF4WmorTjkmR0BFdkB2dw==" + private val mainKey = "YyF4WmorTjkmR0BFdkB2dw==" - private fun decrypt(enc: String, headerstr: String): String { - val key = Base64.decode(mainkey, Base64.DEFAULT).toString(charset("UTF-8")) + headerstr + private fun decrypt(enc: String, headerStr: String): String { + val key = Base64.decode(mainKey, Base64.DEFAULT).toString(charset("UTF-8")) + headerStr val decodedBytes = Base64.decode(enc, Base64.DEFAULT) val encString = decodedBytes.toString(charset("UTF-8")) var result = "" @@ -36,7 +36,7 @@ class YacienTV : MainAPI() { } override val mainPage = mainPageOf( - //"$yacienTVAPI/events" to "Live Events", + "$yacienTVAPI/events" to "Live Events", "$yacienTVAPI/categories/4/channels" to "beIN SPORTS (1080P)", "$yacienTVAPI/categories/5/channels" to "beIN SPORTS (720P)", "$yacienTVAPI/categories/6/channels" to "beIN SPORTS (360P)", @@ -56,12 +56,24 @@ class YacienTV : MainAPI() { val items = mutableListOf() if (page <= 1) { //Log.d("King", "request:$request") - val decodedbody = getDecoded(request.data) - Log.d("King", "decodedbody:$decodedbody") - val list = parseJson(decodedbody).results?.mapNotNull { element -> - element.toSearchResponse(request) - } ?: throw ErrorLoadingException("Invalid Json response") - if (list.isNotEmpty()) items.add(HomePageList(request.name, list, true)) + val decodedBody = getDecoded(request.data) + Log.d("King", "decodedBody:$decodedBody") + + if (request.name == "Live Events") { + val parsedData = parseJson(decodedBody).results + Log.d("King", "parsedEventData:$parsedData") + val list = parsedData?.mapNotNull { element -> + element.toSearchResponse(request) + } ?: throw ErrorLoadingException("Invalid Json response") + if (list.isNotEmpty()) items.add(HomePageList(request.name, list, true)) + + } else { + val parsedData = parseJson(decodedBody).results + val list = parsedData?.mapNotNull { element -> + element.toSearchResponse(request) + } ?: throw ErrorLoadingException("Invalid Json response") + if (list.isNotEmpty()) items.add(HomePageList(request.name, list, true)) + } } return newHomePageResponse(items) } @@ -75,31 +87,51 @@ class YacienTV : MainAPI() { ) } private fun Event.toSearchResponse(request: MainPageRequest, type: String? = null): SearchResponse? { + Log.d("King", "SearchResp${request}") + return LiveSearchResponse( - name ?: return null, - Data(id = id, name = name, posterUrl = "logo", category = request.name).toJson(), + name = "${team_1["name"].toString()} vs ${team_2["name"].toString()}" , + LinksData( + id = id, + start_time = start_time, + end_time = end_time, + champions = champions, + channel = channel, + team_1 = mapOf( + "name" to team_1["name"].toString(), + "logo" to team_1["logo"].toString() + ), + team_2 = mapOf( + "name" to team_2["name"].toString(), + "logo" to team_2["logo"].toString() + ), + category = request.name, + name = "${team_1["name"].toString()} vs ${team_2["name"].toString()}", + commentary = commentary, + ).toJson(), this@YacienTV.name, - TvType.Live, - "logo", + type = TvType.Live, ) } override suspend fun load(url: String): LoadResponse { Log.d("King", "Load:$url") + val data = parseJson(url) - if (data.category == "ARABIC CHANNELS"){ - val decodedbody = getDecoded("$yacienTVAPI/categories/${data.id}/channels") - //Log.d("King", "Arabicdecodedbody:$decodedbody") + if (data.category == "ARABIC CHANNELS") { + val decodedBody = getDecoded("$yacienTVAPI/categories/${data.id}/channels") + //Log.d("King", "ArabicDecodedBody:decodedBody") - var channels = parseJson(decodedbody).results?.map { element -> + val channels = parseJson(decodedBody).results?.map { element -> Episode( name = element.name, posterUrl = element.logo, data = element.id.toString(), ) } ?: throw ErrorLoadingException("Invalid Json response") + return newTvSeriesLoadResponse( - name = data.name, + name = data.name.toString(), url = Data( id = data.id, name = data.name, @@ -113,15 +145,25 @@ class YacienTV : MainAPI() { this.plot = "${data.name} livestreams of ${data.category} category." } } + var plotStr = "" + + if (data.category == "Live Events") { + plotStr = "Teams: ${data.name}" + + "
Time: ${data.start_time}" + + "
Commentary: ${data.commentary}" + + "
Channel: ${data.channel}" + } else { + plotStr = "${data.name} channel livestream of ${data.category} category." + } return LiveStreamLoadResponse( - name = data.name, - url = Data(id = data.id, name = data.name, posterUrl = data.posterUrl, category = data.category).toJson(), - dataUrl = data.id, + name = data.name.toString(), + url = Data(id = data.id, name = data.name, posterUrl = data.posterUrl, category = data.category.toString()).toJson(), + dataUrl = LinksData(id = data.id, name = data.name, posterUrl = data.posterUrl, category = data.category).toJson(), apiName = name, posterUrl = data.posterUrl, type = TvType.Live, - plot = "${data.name} channel livestream of ${data.category} category." + plot = plotStr, ) } override suspend fun loadLinks( @@ -130,11 +172,18 @@ class YacienTV : MainAPI() { subtitleCallback: (SubtitleFile) -> Unit, callback: (ExtractorLink) -> Unit ): Boolean { + Log.d("King", "loadLinks:$data") + val linksData = parseJson(data) - val decodedbody = getDecoded("$yacienTVAPI/channel/$data") + var decodedBody = "" + if (linksData.category == "Live Events") { + decodedBody = getDecoded("$yacienTVAPI/event/${linksData.id}") + } else { + decodedBody = getDecoded("$yacienTVAPI/channel/${linksData.id}") + } - parseJson(decodedbody).links?.map { element -> + parseJson(decodedBody).links?.map { element -> callback.invoke( ExtractorLink( source = element.name, @@ -166,17 +215,18 @@ class YacienTV : MainAPI() { return decrypt(req.body.string(), req.headers["t"].toString()) } data class Team( - @JsonProperty("name") val name: String? = null, - @JsonProperty("logo") val logo: String? = null, + @JsonProperty("name") val name: String, + @JsonProperty("logo") val logo: String, ) data class Event( - @JsonProperty("id") val id: String? = null, - @JsonProperty("start_time") val start_time: String? = null, - @JsonProperty("end_time") val end_time: String? = null, - @JsonProperty("champions") val champions: String? = null, - @JsonProperty("channel") val channel: String? = null, - @JsonProperty("team_1") val team_1: ArrayList? = arrayListOf(), - @JsonProperty("team_2") val team_2: ArrayList? = arrayListOf(), + @JsonProperty("id") val id: String, + @JsonProperty("start_time") val start_time: String, + @JsonProperty("end_time") val end_time: String, + @JsonProperty("champions") val champions: String, + @JsonProperty("commentary") val commentary: String, + @JsonProperty("channel") val channel: String, + @JsonProperty("team_1") val team_1: Map = mapOf(), + @JsonProperty("team_2") val team_2: Map = mapOf(), ) data class EventsResults( @JsonProperty("data") val results: ArrayList? = arrayListOf(), @@ -201,14 +251,21 @@ class YacienTV : MainAPI() { ) data class Data( val id: String? = null, - val name: String, + val name: String? = null, val posterUrl: String? = null, val category: String, ) data class LinksData( - val id: String, - val name: String, + val id: String? = null, + val name: String? = null, val posterUrl: String? = null, - val category: String, + val category: String? = null, + val start_time: String? = null, + val end_time: String? = null, + val champions: String? = null, + val channel: String? = null, + val commentary: String? = null, + val team_1: Map? = null, + val team_2: Map? = null, ) } \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index ce352dd2..1f7d5283 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -45,7 +45,7 @@ subprojects { compileSdkVersion(33) defaultConfig { - minSdk = 21 + minSdk = 24 targetSdk = 33 }