From 104c0db402f503458c4a904e8b908fd776ef8124 Mon Sep 17 00:00:00 2001 From: hexated Date: Tue, 27 Sep 2022 00:07:39 +0700 Subject: [PATCH] added TimefourTv --- TimefourTv/build.gradle.kts | 25 +++ TimefourTv/src/main/AndroidManifest.xml | 2 + .../src/main/kotlin/com/hexated/TimefourTv.kt | 159 ++++++++++++++++++ .../kotlin/com/hexated/TimefourTvPlugin.kt | 14 ++ 4 files changed, 200 insertions(+) create mode 100644 TimefourTv/build.gradle.kts create mode 100644 TimefourTv/src/main/AndroidManifest.xml create mode 100644 TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt create mode 100644 TimefourTv/src/main/kotlin/com/hexated/TimefourTvPlugin.kt diff --git a/TimefourTv/build.gradle.kts b/TimefourTv/build.gradle.kts new file mode 100644 index 00000000..9d050653 --- /dev/null +++ b/TimefourTv/build.gradle.kts @@ -0,0 +1,25 @@ +// use an integer for version numbers +version = 1 + + +cloudstream { + language = "en" + // All of these properties are optional, you can safely remove them + + description = "Sport Live Stream" + authors = listOf("Hexated") + + /** + * Status int as the following: + * 0: Down + * 1: Ok + * 2: Slow + * 3: Beta only + * */ + status = 1 // will be 3 if unspecified + tvTypes = listOf( + "Live", + ) + + iconUrl = "https://www.google.com/s2/favicons?domain=time4tv.stream&sz=%size%" +} diff --git a/TimefourTv/src/main/AndroidManifest.xml b/TimefourTv/src/main/AndroidManifest.xml new file mode 100644 index 00000000..c98063f8 --- /dev/null +++ b/TimefourTv/src/main/AndroidManifest.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt new file mode 100644 index 00000000..80d4ccf2 --- /dev/null +++ b/TimefourTv/src/main/kotlin/com/hexated/TimefourTv.kt @@ -0,0 +1,159 @@ +package com.hexated + +import com.lagradost.cloudstream3.* +import com.lagradost.cloudstream3.utils.ExtractorLink +import com.lagradost.cloudstream3.utils.Qualities +import org.jsoup.nodes.Element +import java.net.URI + +class TimefourTv : MainAPI() { + override var mainUrl = "https://time4tv.stream" + override var name = "Time4tv" + override val hasDownloadSupport = false + override val hasMainPage = true + override val supportedTypes = setOf( + TvType.Live + ) + + override val mainPage = mainPageOf( + "$mainUrl/tv-channels" to "All Channels", + "$mainUrl/usa-channels" to "USA Channels", + "$mainUrl/uk-channels" to "UK Channels", + "$mainUrl/sports-channels" to "Sport Channels", + "$mainUrl/live-sports-streams" to "Live Sport Channels", + "$mainUrl/news-channels" to "News Channels", + ) + + override suspend fun getMainPage( + page: Int, + request: MainPageRequest + ): HomePageResponse { + val document = if (request.name == "All Channels") { + if (page == 1) { + app.get("${request.data}.php").document + } else { + app.get("${request.data}${page.minus(1)}.php").document + } + } else { + app.get("${request.data}.php").document + } + val home = document.select("div.tab-content ul li").mapNotNull { + it.toSearchResult() + } + return newHomePageResponse( + list = HomePageList( + name = request.name, + list = home, + isHorizontalImages = true + ), + hasNext = true + ) + } + + private fun Element.toSearchResult(): LiveSearchResponse? { + return LiveSearchResponse( + this.selectFirst("div.channelName")?.text() ?: return null, + fixUrl(this.selectFirst("a")!!.attr("href")), + this@TimefourTv.name, + TvType.Live, + fixUrlNull(this.selectFirst("img")?.attr("src")), + ) + + } + + override suspend fun load(url: String): LoadResponse? { + val document = app.get(url).document + val title = document.selectFirst("div.channelHeading h1")?.text() ?: return null + val poster = + fixUrlNull(document.selectFirst("meta[property=\"og:image\"]")?.attr("content")) + val description = document.selectFirst("div.tvText")?.text() ?: return null + val episodes = document.selectFirst("div.playit")?.attr("onclick")?.substringAfter("open('") + ?.substringBefore("',")?.let { link -> + val doc = app.get(link).document.selectFirst("div.tv_palyer iframe")?.attr("src") + ?.let { iframe -> + app.get(fixUrl(iframe), allowRedirects = false).document + } + doc?.select("div.stream_button a")?.map { + Episode( + fixUrl(it.attr("href")), + it.text() + ) + } + } ?: throw ErrorLoadingException("Refresh page") + return newTvSeriesLoadResponse(title, url, TvType.TvSeries, episodes) { + this.posterUrl = poster + this.plot = description + } + } + + private fun getBaseUrl(url: String): String { + return URI(url).let { + "${it.scheme}://${it.host}" + } + } + + private var mainServer: String? = null + private suspend fun getLink(url: String): String? { + val (channel, iframe) = if (url.contains("width=")) { + val doc = app.get(url, referer = "$mainUrl/").document + val tempIframe = doc.selectFirst("iframe")?.attr("src") ?: return null + val doctwo = app.get(fixUrl(tempIframe), referer = url).text + listOf( + tempIframe.split("?").last().removePrefix("id=").replace(".php", ""), + doctwo.substringAfterLast("