Merge remote-tracking branch 'OriginHexa/master' into update2
# Conflicts: # Movierulzhd/build.gradle.kts # Movierulzhd/src/main/kotlin/com/hexated/Movierulzhd.kt
This commit is contained in:
commit
8215b17940
|
@ -54,7 +54,7 @@ jobs:
|
|||
ZSHOW_API: ${{ secrets.ZSHOW_API }}
|
||||
SFMOVIES_API: ${{ secrets.SFMOVIES_API }}
|
||||
CINEMATV_API: ${{ secrets.CINEMATV_API }}
|
||||
OMOVIES_API: ${{ secrets.OMOVIES_API }}
|
||||
GHOSTX_API: ${{ secrets.GHOSTX_API }}
|
||||
SUPERSTREAM_FIRST_API: ${{ secrets.SUPERSTREAM_FIRST_API }}
|
||||
SUPERSTREAM_SECOND_API: ${{ secrets.SUPERSTREAM_SECOND_API }}
|
||||
SUPERSTREAM_THIRD_API: ${{ secrets.SUPERSTREAM_THIRD_API }}
|
||||
|
@ -73,7 +73,7 @@ jobs:
|
|||
echo ZSHOW_API=$ZSHOW_API >> local.properties
|
||||
echo SFMOVIES_API=$SFMOVIES_API >> local.properties
|
||||
echo CINEMATV_API=$CINEMATV_API >> local.properties
|
||||
echo OMOVIES_API=$OMOVIES_API >> local.properties
|
||||
echo GHOSTX_API=$GHOSTX_API >> local.properties
|
||||
echo SUPERSTREAM_FIRST_API=$SUPERSTREAM_FIRST_API >> local.properties
|
||||
echo SUPERSTREAM_SECOND_API=$SUPERSTREAM_SECOND_API >> local.properties
|
||||
echo SUPERSTREAM_THIRD_API=$SUPERSTREAM_THIRD_API >> local.properties
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 9
|
||||
version = 10
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
@ -38,5 +38,5 @@ cloudstream {
|
|||
"OVA",
|
||||
)
|
||||
|
||||
iconUrl = "https://media.discordapp.net/attachments/1059306855865782282/1123970193274712096/Anichi.png"
|
||||
iconUrl = "https://cdn.discordapp.com/attachments/1109266606292488297/1200425504432472176/Anichi.png"
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
package com.hexated
|
||||
|
||||
import com.hexated.AnichiExtractors.invokeExternalSources
|
||||
import com.hexated.AnichiExtractors.invokeInternalSources
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.LoadResponse.Companion.addActors
|
||||
|
@ -214,25 +213,12 @@ open class Anichi : MainAPI() {
|
|||
|
||||
val loadData = parseJson<AnichiLoadData>(data)
|
||||
|
||||
argamap(
|
||||
{
|
||||
invokeInternalSources(
|
||||
loadData.hash,
|
||||
loadData.dubStatus,
|
||||
loadData.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeExternalSources(
|
||||
loadData.idMal,
|
||||
loadData.dubStatus,
|
||||
loadData.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
}
|
||||
invokeInternalSources(
|
||||
loadData.hash,
|
||||
loadData.dubStatus,
|
||||
loadData.episode,
|
||||
subtitleCallback,
|
||||
callback
|
||||
)
|
||||
|
||||
return true
|
||||
|
@ -245,7 +231,6 @@ open class Anichi : MainAPI() {
|
|||
|
||||
const val anilistApi = "https://graphql.anilist.co"
|
||||
const val jikanApi = "https://api.jikan.moe/v4"
|
||||
const val marinHost = "https://marin.moe"
|
||||
|
||||
private const val mainHash = "e42a4466d984b2c0a2cecae5dd13aa68867f634b16ee0f17b380047d14482406"
|
||||
private const val popularHash = "31a117653812a2547fd981632e8c99fa8bf8a75c4ef1a77a1567ef1741a7ab9c"
|
||||
|
|
|
@ -121,67 +121,6 @@ object AnichiExtractors : Anichi() {
|
|||
}
|
||||
}
|
||||
|
||||
suspend fun invokeExternalSources(
|
||||
idMal: Int? = null,
|
||||
dubStatus: String,
|
||||
episode: String,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val ids = app.get("https://api.malsync.moe/mal/anime/${idMal ?: return}")
|
||||
.parsedSafe<MALSyncResponses>()?.sites
|
||||
|
||||
if (dubStatus == "sub") invokeMarin(ids?.marin?.keys?.firstOrNull(), episode, callback)
|
||||
|
||||
}
|
||||
|
||||
private suspend fun invokeMarin(
|
||||
id: String? = null,
|
||||
episode: String,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val url = "$marinHost/anime/${id ?: return}/$episode"
|
||||
val cookies = app.get(
|
||||
"$marinHost/anime",
|
||||
headers = mapOf(
|
||||
"Cookie" to "__ddg1_=;__ddg2_=;"
|
||||
),
|
||||
referer = "$marinHost/anime",
|
||||
).cookies.let {
|
||||
decode(it["XSRF-TOKEN"].toString()) to decode(it["marin_session"].toString())
|
||||
}
|
||||
|
||||
val json = app.get(
|
||||
url,
|
||||
headers = mapOf(
|
||||
"Accept" to "text/html, application/xhtml+xml",
|
||||
"Cookie" to "__ddg1=;__ddg2_=;XSRF-TOKEN=${cookies.first};marin_session=${cookies.second};",
|
||||
"X-XSRF-TOKEN" to cookies.first
|
||||
),
|
||||
referer = "$marinHost/anime/$id"
|
||||
).document.selectFirst("div#app")?.attr("data-page")
|
||||
tryParseJson<MarinResponses>(json)?.props?.video?.data?.mirror?.map { video ->
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Marin",
|
||||
"Marin",
|
||||
video.code?.file ?: return@map,
|
||||
url,
|
||||
video.code.height ?: Qualities.Unknown.value,
|
||||
headers = mapOf(
|
||||
"Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5",
|
||||
"Accept-Language" to "en-US,en;q=0.5",
|
||||
"Cookie" to "__ddg1=;__ddg2_=; XSRF-TOKEN=${cookies.first}; marin_session=${cookies.second};",
|
||||
"Connection" to "keep-alive",
|
||||
"Sec-Fetch-Dest" to "video",
|
||||
"Sec-Fetch-Mode" to "cors",
|
||||
"Sec-Fetch-Site" to "cross-site",
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun invokeGogo(
|
||||
link: String,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
|
|
|
@ -240,7 +240,6 @@ data class PageStatus(
|
|||
@JsonProperty("__typename") val _typename: String? = null
|
||||
)
|
||||
|
||||
|
||||
data class Recommendations(
|
||||
@JsonProperty("anyCard") val anyCard: AnyCard? = null,
|
||||
@JsonProperty("pageStatus") val pageStatus: PageStatus? = PageStatus(),
|
||||
|
@ -255,38 +254,4 @@ data class QueryPopular(
|
|||
|
||||
data class DataPopular(
|
||||
@JsonProperty("queryPopular") val queryPopular: QueryPopular? = QueryPopular()
|
||||
)
|
||||
|
||||
data class MALSyncSites(
|
||||
@JsonProperty("Zoro") val zoro: HashMap<String?, HashMap<String, String?>>? = hashMapOf(),
|
||||
@JsonProperty("Marin") val marin: HashMap<String?, HashMap<String, String?>>? = hashMapOf(),
|
||||
)
|
||||
|
||||
data class MALSyncResponses(
|
||||
@JsonProperty("Sites") val sites: MALSyncSites? = null,
|
||||
)
|
||||
|
||||
data class MarinCode(
|
||||
@JsonProperty("file") val file: String? = null,
|
||||
@JsonProperty("height") val height: Int? = null,
|
||||
)
|
||||
|
||||
data class MarinMirror(
|
||||
@JsonProperty("code") val code: MarinCode? = null,
|
||||
)
|
||||
|
||||
data class MarinData(
|
||||
@JsonProperty("mirror") val mirror: ArrayList<MarinMirror>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class MarinVideos(
|
||||
@JsonProperty("data") val data: MarinData? = null,
|
||||
)
|
||||
|
||||
data class MarinProps(
|
||||
@JsonProperty("video") val video: MarinVideos? = null,
|
||||
)
|
||||
|
||||
data class MarinResponses(
|
||||
@JsonProperty("props") val props: MarinProps? = null,
|
||||
)
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 30
|
||||
version = 31
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -10,7 +10,7 @@ import org.jsoup.nodes.Element
|
|||
import java.net.URI
|
||||
|
||||
open class Gomov : MainAPI() {
|
||||
override var mainUrl = "https://gomov.bio"
|
||||
override var mainUrl = "https://gomov.co"
|
||||
private var directUrl: String? = null
|
||||
override var name = "Gomov"
|
||||
override val hasMainPage = true
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.hexated
|
|||
import com.lagradost.cloudstream3.mainPageOf
|
||||
|
||||
class Ngefilm : Gomov() {
|
||||
override var mainUrl = "https://tv3.ngefilm21.homes"
|
||||
override var mainUrl = "https://tv4.ngefilm21.homes"
|
||||
override var name = "Ngefilm"
|
||||
override val mainPage = mainPageOf(
|
||||
"/page/%d/?s&search=advanced&post_type=movie&index&orderby&genre&movieyear&country&quality=" to "Movies Terbaru",
|
||||
|
|
|
@ -6,7 +6,7 @@ import com.lagradost.cloudstream3.TvSeriesLoadResponse
|
|||
import com.lagradost.cloudstream3.*
|
||||
|
||||
class Pusatfilm : Gomov() {
|
||||
override var mainUrl = "https://pusatfilm21.vip"
|
||||
override var mainUrl = "https://pf21.vip"
|
||||
override var name = "Pusatfilm"
|
||||
override val mainPage = mainPageOf(
|
||||
"film-terbaru/page/%d/" to "Film Terbaru",
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 36
|
||||
version = 39
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 19
|
||||
version = 20
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import org.jsoup.nodes.Element
|
||||
|
||||
class LayarKacaProvider : MainAPI() {
|
||||
override var mainUrl = "https://tv7.lk21official.wiki"
|
||||
private var seriesUrl = "https://tv9.nontondrama.click"
|
||||
override var mainUrl = "https://tv10.lk21official.wiki"
|
||||
private var seriesUrl = "https://tv11.nontondrama.click"
|
||||
override var name = "LayarKaca"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
|
|
|
@ -36,12 +36,16 @@ open class Streampai : ExtractorApi() {
|
|||
val res = app.get(url, referer = referer).document
|
||||
val data = res.selectFirst("script:containsData(player =)")?.data() ?: return
|
||||
|
||||
val sources = data.substringAfter("sources: [").substringBefore("]").replace("\'", "\"")
|
||||
val sources = data.substringAfter("sources: [").substringBefore("]")
|
||||
.addMarks("src")
|
||||
.addMarks("type")
|
||||
.addMarks("size")
|
||||
.replace("\'", "\"")
|
||||
|
||||
val tracks = data.substringAfter("tracks: [").substringBefore("]")
|
||||
.replace("\'", "\"")
|
||||
|
||||
|
||||
tryParseJson<List<Responses>>("[$sources]")?.forEach {
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
|
@ -56,6 +60,15 @@ open class Streampai : ExtractorApi() {
|
|||
)
|
||||
)
|
||||
}
|
||||
|
||||
tryParseJson<List<Responses>>("[$tracks]")?.forEach {
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
fixTitle(it.label ?: return@forEach),
|
||||
fixUrl(it.src)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.addMarks(str: String): String {
|
||||
|
@ -65,6 +78,7 @@ open class Streampai : ExtractorApi() {
|
|||
data class Responses(
|
||||
@JsonProperty("src") val src: String,
|
||||
@JsonProperty("type") val type: String?,
|
||||
@JsonProperty("label") val label: String?,
|
||||
@JsonProperty("size") val size: Int?
|
||||
)
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 60
|
||||
version = 61
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -11,7 +11,7 @@ import java.net.URI
|
|||
|
||||
open class Movierulzhd : MainAPI() {
|
||||
|
||||
override var mainUrl = "https://movierulzhd.dog"
|
||||
override var mainUrl = "https://movierulzhd.party"
|
||||
var directUrl = ""
|
||||
override var name = "Movierulzhd"
|
||||
override val hasMainPage = true
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 9
|
||||
version = 11
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
package com.hexated
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty
|
||||
import com.lagradost.cloudstream3.SubtitleFile
|
||||
import com.lagradost.cloudstream3.app
|
||||
import com.lagradost.cloudstream3.utils.ExtractorApi
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.INFER_TYPE
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
|
||||
open class Mitedrive : ExtractorApi() {
|
||||
override val name = "Mitedrive"
|
||||
|
@ -79,4 +75,21 @@ open class Berkasdrive : ExtractorApi() {
|
|||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
open class Videogami : ExtractorApi() {
|
||||
override val name = "Videogami"
|
||||
override val mainUrl = "https://video.nimegami.id"
|
||||
override val requiresReferer = false
|
||||
|
||||
override suspend fun getUrl(
|
||||
url: String,
|
||||
referer: String?,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val id = base64Decode(url.substringAfter("url=")).substringAfterLast("/")
|
||||
loadExtractor("https://hxfile.co/embed-$id.html", "$mainUrl/", subtitleCallback, callback)
|
||||
}
|
||||
|
||||
}
|
|
@ -81,7 +81,7 @@ class Nimegami : MainAPI() {
|
|||
override suspend fun search(query: String): List<SearchResponse> {
|
||||
val searchResponse = mutableListOf<SearchResponse>()
|
||||
for (i in 1..2) {
|
||||
val res = app.get("$mainUrl/page/$i/?s=gintama&post_type=post").document.select("div.archive article")
|
||||
val res = app.get("$mainUrl/page/$i/?s=$query&post_type=post").document.select("div.archive article")
|
||||
.mapNotNull {
|
||||
it.toSearchResult()
|
||||
}
|
||||
|
|
|
@ -12,5 +12,6 @@ class NimegamiPlugin: Plugin() {
|
|||
registerMainAPI(Nimegami())
|
||||
registerExtractorAPI(Mitedrive())
|
||||
registerExtractorAPI(Berkasdrive())
|
||||
registerExtractorAPI(Videogami())
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 27
|
||||
version = 28
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -27,10 +27,7 @@ open class Qiwi : ExtractorApi() {
|
|||
"$mainUrl/",
|
||||
getIndexQuality(title),
|
||||
headers = mapOf(
|
||||
"Accept" to "video/webm,video/ogg,video/*;q=0.9,application/ogg;q=0.7,audio/*;q=0.6,*/*;q=0.5",
|
||||
"Range" to "bytes=0-",
|
||||
"Sec-Fetch-Dest" to "video",
|
||||
"Sec-Fetch-Mode" to "no-cors",
|
||||
)
|
||||
)
|
||||
)
|
||||
|
@ -42,39 +39,4 @@ open class Qiwi : ExtractorApi() {
|
|||
?: Qualities.Unknown.value
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
open class Mediafire : ExtractorApi() {
|
||||
override val name = "Mediafire"
|
||||
override val mainUrl = "https://www.mediafire.com"
|
||||
override val requiresReferer = true
|
||||
|
||||
override suspend fun getUrl(
|
||||
url: String,
|
||||
referer: String?,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val res = app.get(url, referer = referer).document
|
||||
val title = res.select("div.dl-btn-label").text()
|
||||
val video = res.selectFirst("a#downloadButton")?.attr("href")
|
||||
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
this.name,
|
||||
video ?: return,
|
||||
"",
|
||||
getQuality(title),
|
||||
INFER_TYPE
|
||||
)
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
private fun getQuality(str: String?): Int {
|
||||
return Regex("(\\d{3,4})[pP]").find(str ?: "")?.groupValues?.getOrNull(1)?.toIntOrNull()
|
||||
?: Qualities.Unknown.value
|
||||
}
|
||||
|
||||
}
|
|
@ -7,7 +7,7 @@ import com.lagradost.cloudstream3.utils.*
|
|||
import org.jsoup.nodes.Element
|
||||
|
||||
class OploverzProvider : MainAPI() {
|
||||
override var mainUrl = "https://oploverz.cool"
|
||||
override var mainUrl = "https://oploverz.bio"
|
||||
override var name = "Oploverz"
|
||||
override val hasMainPage = true
|
||||
override var lang = "id"
|
||||
|
|
|
@ -11,6 +11,5 @@ class OploverzProviderPlugin: Plugin() {
|
|||
// All providers should be added in this manner. Please don't edit the providers list directly.
|
||||
registerMainAPI(OploverzProvider())
|
||||
registerExtractorAPI(Qiwi())
|
||||
registerExtractorAPI(Mediafire())
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 8
|
||||
version = 9
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -3,7 +3,7 @@ package com.hexated
|
|||
import com.lagradost.cloudstream3.TvType
|
||||
|
||||
class Cgvindo : RebahinProvider() {
|
||||
override var mainUrl = "http://198.54.124.245"
|
||||
override var mainUrl = "http://cgvindo.lol"
|
||||
override var name = "Cgvindo"
|
||||
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 218
|
||||
version = 220
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
@ -9,7 +9,7 @@ android {
|
|||
properties.load(project.rootProject.file("local.properties").inputStream())
|
||||
|
||||
buildConfigField("String", "TMDB_API", "\"${properties.getProperty("TMDB_API")}\"")
|
||||
buildConfigField("String", "OMOVIES_API", "\"${properties.getProperty("OMOVIES_API")}\"")
|
||||
buildConfigField("String", "GHOSTX_API", "\"${properties.getProperty("GHOSTX_API")}\"")
|
||||
buildConfigField("String", "CINEMATV_API", "\"${properties.getProperty("CINEMATV_API")}\"")
|
||||
buildConfigField("String", "SFMOVIES_API", "\"${properties.getProperty("SFMOVIES_API")}\"")
|
||||
buildConfigField("String", "ZSHOW_API", "\"${properties.getProperty("ZSHOW_API")}\"")
|
||||
|
|
|
@ -436,9 +436,9 @@ class Streamwish : Filesim() {
|
|||
override var mainUrl = "https://streamwish.to"
|
||||
}
|
||||
|
||||
class Wishfast : Filesim() {
|
||||
override val name = "Wishfast"
|
||||
override var mainUrl = "https://wishfast.top"
|
||||
class UqloadsXyz : Filesim() {
|
||||
override val name = "Uqloads"
|
||||
override var mainUrl = "https://uqloads.xyz"
|
||||
}
|
||||
|
||||
class FilelionsTo : Filesim() {
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package com.hexated
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTime
|
||||
import com.lagradost.cloudstream3.APIHolder.unixTimeMS
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
|
@ -125,8 +124,8 @@ object SoraExtractor : SoraStream() {
|
|||
httpsify(srcrcp),
|
||||
referer = iframedoc
|
||||
).document.selectFirst("script:containsData(Playerjs)")?.data()
|
||||
val video = script?.substringAfter("file:\"#2")?.substringBefore("\"")
|
||||
?.replace(Regex("/.*?=?="), "")?.let { base64Decode(it) }
|
||||
val video = script?.substringAfter("file:\"#9")?.substringBefore("\"")
|
||||
?.replace(Regex("/@#@\\S+?=?="), "")?.let { base64Decode(it) }
|
||||
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
|
@ -136,66 +135,6 @@ object SoraExtractor : SoraStream() {
|
|||
)
|
||||
}
|
||||
|
||||
suspend fun invokeDbgo(
|
||||
id: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
|
||||
val iframeDbgo: String?
|
||||
val script = if (season == null) {
|
||||
val doc = app.get("$dbgoAPI/imdb.php?id=$id").document
|
||||
iframeDbgo = doc.select("div.myvideo iframe").attr("src")
|
||||
app.get(iframeDbgo, referer = "$dbgoAPI/").document.select("script")
|
||||
.find { it.data().contains("CDNplayerConfig =") }?.data()
|
||||
} else {
|
||||
val doc = app.get("$dbgoAPI/tv-imdb.php?id=$id&s=$season").document
|
||||
iframeDbgo = doc.select("div.myvideo iframe").attr("src")
|
||||
val token = app.get(
|
||||
iframeDbgo,
|
||||
referer = "$dbgoAPI/"
|
||||
).document.selectFirst("select#translator-name option")?.attr("data-token")
|
||||
app.get("https://voidboost.net/serial/$token/iframe?s=$season&e=$episode&h=dbgo.fun").document.select(
|
||||
"script"
|
||||
).find { it.data().contains("CDNplayerConfig =") }?.data()
|
||||
} ?: return
|
||||
|
||||
val source =
|
||||
Regex("['|\"]file['|\"]:\\s['|\"](#\\S+?)['|\"]").find(script)?.groupValues?.get(1)
|
||||
?: return
|
||||
val subtitle =
|
||||
Regex("['|\"]subtitle['|\"]:\\s['|\"](\\S+?)['|\"]").find(script)?.groupValues?.get(1)
|
||||
|
||||
val ref = getBaseUrl(iframeDbgo)
|
||||
decryptStreamUrl(source).split(",").map { links ->
|
||||
val quality = Regex("\\[(\\d*p.*?)]").find(links)?.groupValues?.getOrNull(1)?.trim()
|
||||
?: return@map null
|
||||
links.replace("[$quality]", "").split(" or ").map { it.trim() }.map { link ->
|
||||
val name = if (link.contains(".m3u8")) "Dbgo (Main)" else "Dbgo (Backup)"
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
name,
|
||||
name,
|
||||
link,
|
||||
"$ref/",
|
||||
getQuality(quality),
|
||||
isM3u8 = link.contains(".m3u8"),
|
||||
headers = mapOf("Origin" to ref)
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
subtitle?.split(",")?.map { sub ->
|
||||
val language = Regex("\\[(.*)]").find(sub)?.groupValues?.getOrNull(1) ?: return@map null
|
||||
val link = sub.replace("[$language]", "").trim()
|
||||
subtitleCallback.invoke(SubtitleFile(getDbgoLanguage(language), link))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun invokeDreamfilm(
|
||||
title: String? = null,
|
||||
season: Int? = null,
|
||||
|
@ -1788,21 +1727,21 @@ object SoraExtractor : SoraStream() {
|
|||
}
|
||||
|
||||
suspend fun invokeSmashyStream(
|
||||
imdbId: String? = null,
|
||||
tmdbId: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val url = if (season == null) {
|
||||
"$smashyStreamAPI/playere.php?imdb=$imdbId"
|
||||
"$smashyStreamAPI/playere.php?tmdb=$tmdbId"
|
||||
} else {
|
||||
"$smashyStreamAPI/playere.php?imdb=$imdbId&season=$season&episode=$episode"
|
||||
"$smashyStreamAPI/playere.php?tmdb=$tmdbId&season=$season&episode=$episode"
|
||||
}
|
||||
|
||||
app.get(
|
||||
url,
|
||||
referer = "https://smashystream.com/"
|
||||
referer = "https://smashystream.xyz/"
|
||||
).document.select("div#_default-servers a.server").map {
|
||||
it.attr("data-url") to it.text()
|
||||
}.apmap {
|
||||
|
@ -1810,9 +1749,8 @@ object SoraExtractor : SoraStream() {
|
|||
"Player F" -> {
|
||||
invokeSmashyFfix(it.second, it.first, url, subtitleCallback, callback)
|
||||
}
|
||||
|
||||
"Player D (Hindi)" -> {
|
||||
invokeSmashyD(it.first, url, callback)
|
||||
"Player SU" -> {
|
||||
invokeSmashySu(it.second, it.first, url, callback)
|
||||
}
|
||||
|
||||
else -> return@apmap
|
||||
|
@ -1821,6 +1759,52 @@ object SoraExtractor : SoraStream() {
|
|||
|
||||
}
|
||||
|
||||
suspend fun invokeMoflix(
|
||||
tmdbId: Int? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
) {
|
||||
val id = (if(season == null) {
|
||||
"tmdb|movie|$tmdbId"
|
||||
} else {
|
||||
"tmdb|series|$tmdbId"
|
||||
}).let { base64Encode(it.toByteArray()) }
|
||||
|
||||
val loaderUrl = "$moflixAPI/api/v1/titles/$id?loader=titlePage"
|
||||
val url = if(season == null) {
|
||||
loaderUrl
|
||||
} else {
|
||||
val mediaId = app.get(loaderUrl, referer = "$moflixAPI/").parsedSafe<MoflixResponse>()?.title?.id
|
||||
"$moflixAPI/api/v1/titles/$mediaId/seasons/$season/episodes/$episode?loader=episodePage"
|
||||
}
|
||||
|
||||
val res = app.get(url, referer = "$moflixAPI/").parsedSafe<MoflixResponse>()
|
||||
(res?.episode ?: res?.title)?.videos?.filter { it.category.equals("full", true) }?.apmap { iframe ->
|
||||
val response = app.get(iframe.src ?: return@apmap, referer = "$moflixAPI/")
|
||||
val host = getBaseUrl(iframe.src)
|
||||
val doc = response.document.selectFirst("script:containsData(sources:)")?.data()
|
||||
val script = if (doc.isNullOrEmpty()) {
|
||||
getAndUnpack(response.text)
|
||||
} else {
|
||||
doc
|
||||
}
|
||||
val m3u8 = Regex("file:\\s*\"(.*?m3u8.*?)\"").find(script ?: return@apmap)?.groupValues?.getOrNull(1)
|
||||
if(m3u8?.haveDub("$host/") == false) return@apmap
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Moflix",
|
||||
"Moflix [${iframe.name}]",
|
||||
m3u8 ?: return@apmap,
|
||||
"$host/",
|
||||
iframe.quality?.filter { it.isDigit() }?.toIntOrNull() ?: Qualities.Unknown.value,
|
||||
INFER_TYPE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//TODO only subs
|
||||
suspend fun invokeWatchsomuch(
|
||||
imdbId: String? = null,
|
||||
|
@ -2100,11 +2084,11 @@ object SoraExtractor : SoraStream() {
|
|||
?: return
|
||||
val ref = getBaseUrl(framesrc)
|
||||
val id = framesrc.substringAfter("id=").substringBefore("&")
|
||||
loadExtractor("https://wishfast.top/e/$id", "$ref/", subtitleCallback, callback)
|
||||
loadExtractor("https://uqloads.xyz/e/$id", "$ref/", subtitleCallback, callback)
|
||||
|
||||
}
|
||||
|
||||
suspend fun invokeOmovies(
|
||||
suspend fun invokeGhostx(
|
||||
title: String? = null,
|
||||
year: Int? = null,
|
||||
season: Int? = null,
|
||||
|
@ -2117,8 +2101,8 @@ object SoraExtractor : SoraStream() {
|
|||
season,
|
||||
episode,
|
||||
callback,
|
||||
BuildConfig.OMOVIES_API,
|
||||
"Omovies",
|
||||
BuildConfig.GHOSTX_API,
|
||||
"Ghostx",
|
||||
base64Decode("X3NtUWFtQlFzRVRi"),
|
||||
base64Decode("X3NCV2NxYlRCTWFU")
|
||||
)
|
||||
|
@ -2136,7 +2120,7 @@ object SoraExtractor : SoraStream() {
|
|||
episodeSelector: String,
|
||||
) {
|
||||
fun String.decrypt(key: String): List<GpressSources>? {
|
||||
return tryParseJson<List<GpressSources>>(base64Decode(this).decodePrimewireXor(key))
|
||||
return tryParseJson<List<GpressSources>>(base64Decode(this).xorDecrypt(key))
|
||||
}
|
||||
|
||||
val slug = getEpisodeSlug(season, episode)
|
||||
|
@ -2148,8 +2132,10 @@ object SoraExtractor : SoraStream() {
|
|||
val savedCookies = mapOf(
|
||||
base64Decode("X2lkZW50aXR5Z29tb3ZpZXM3") to base64Decode("NTJmZGM3MGIwMDhjMGIxZDg4MWRhYzBmMDFjY2E4MTllZGQ1MTJkZTAxY2M4YmJjMTIyNGVkNGFhZmI3OGI1MmElM0EyJTNBJTdCaSUzQTAlM0JzJTNBMTglM0ElMjJfaWRlbnRpdHlnb21vdmllczclMjIlM0JpJTNBMSUzQnMlM0E1MiUzQSUyMiU1QjIwNTAzNjYlMkMlMjJIblZSUkFPYlRBU09KRXI0NVl5Q004d2lIb2wwVjFrbyUyMiUyQzI1OTIwMDAlNUQlMjIlM0IlN0Q="),
|
||||
)
|
||||
val req = app.get("$api/search/$query")
|
||||
val doc = req.document
|
||||
|
||||
var res = app.get("$api/search/$query")
|
||||
val cookies = savedCookies + res.cookies
|
||||
val doc = res.document
|
||||
val media = doc.select("div.$mediaSelector").map {
|
||||
Triple(it.attr("data-filmName"), it.attr("data-year"), it.select("a").attr("href"))
|
||||
}.let { el ->
|
||||
|
@ -2172,45 +2158,38 @@ object SoraExtractor : SoraStream() {
|
|||
val iframe = if (season == null) {
|
||||
media.third
|
||||
} else {
|
||||
val res = app.get(fixUrl(media.third, api))
|
||||
res.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})")
|
||||
app.get(fixUrl(media.third, api), cookies = cookies)
|
||||
.document.selectFirst("div#$episodeSelector a:contains(Episode ${slug.second})")
|
||||
?.attr("href")
|
||||
} ?: return
|
||||
|
||||
val users = if (season == null) {
|
||||
media.third.substringAfterLast("/") to "0"
|
||||
} else {
|
||||
media.third.substringAfterLast("/") to iframe.substringAfterLast("/")
|
||||
.substringBefore("-")
|
||||
}
|
||||
val res = app.get(fixUrl(iframe, api), verify = false)
|
||||
delay(2000)
|
||||
val serverUrl = res.document.selectFirst("script:containsData(pushState)")?.data()?.let {
|
||||
""",\s*'([^']+)""".toRegex().find(it)?.groupValues?.get(1)
|
||||
} ?: return
|
||||
val cookies = savedCookies + res.cookies
|
||||
|
||||
res = app.get(fixUrl(iframe ?: return, api), cookies = cookies)
|
||||
val url = res.document.select("meta[property=og:url]").attr("content")
|
||||
val headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||
val qualities = intArrayOf(2160, 1440, 1080, 720, 480, 360)
|
||||
|
||||
val (serverId, episodeId) = if (season == null) {
|
||||
url.substringAfterLast("/") to "0"
|
||||
} else {
|
||||
url.substringBeforeLast("/").substringAfterLast("/") to url.substringAfterLast("/")
|
||||
.substringBefore("-")
|
||||
}
|
||||
val serverRes = app.get(
|
||||
"$api/user/servers/${users.first}?ep=${users.second}",
|
||||
"$api/user/servers/$serverId?ep=$episodeId",
|
||||
cookies = cookies,
|
||||
referer = url,
|
||||
headers = headers
|
||||
)
|
||||
val unpack = getAndUnpack(serverRes.text)
|
||||
val key = unpack.substringAfter("(key=").substringBefore(")")
|
||||
val key2 = unpack.substringAfter("<\"").substringBefore("\".")
|
||||
serverRes.document.select("ul li").amap { el ->
|
||||
).document
|
||||
serverRes.select("ul li").apmap { el ->
|
||||
val server = el.attr("data-value")
|
||||
val encryptedData = app.get(
|
||||
"${fixUrl(serverUrl, api)}?server=$server&_=$unixTimeMS",
|
||||
"$url?server=$server&_=$unixTimeMS",
|
||||
cookies = cookies,
|
||||
referer = url,
|
||||
headers = headers
|
||||
).text
|
||||
val links = encryptedData.decrypt(key) ?: encryptedData.decrypt(key2) ?: return@amap
|
||||
links.forEach { video ->
|
||||
val links = encryptedData.decrypt(base64Decode("MTEx"))
|
||||
links?.forEach { video ->
|
||||
qualities.filter { it <= video.max.toInt() }.forEach {
|
||||
callback(
|
||||
ExtractorLink(
|
||||
|
@ -2291,43 +2270,23 @@ object SoraExtractor : SoraStream() {
|
|||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val id = imdbId?.removePrefix("tt")
|
||||
val slug = title.createSlug()
|
||||
val url = if (season == null) {
|
||||
"$cinemaTvAPI/movies/play/$id-$slug-$year"
|
||||
val media = app.get("$cinemaTvAPI/v1/${if (season == null) "movies" else "shows"}?filters[q]=$title")
|
||||
.parsedSafe<CinemaTvResponse>()?.items?.find {
|
||||
it.imdb_id?.removePrefix("tt")
|
||||
.equals(imdbId?.removePrefix("tt")) || (it.title.equals(
|
||||
title,
|
||||
true
|
||||
) && it.year == year)
|
||||
} ?: return
|
||||
|
||||
val mediaId = if (season == null) {
|
||||
media.id_movie
|
||||
} else {
|
||||
"$cinemaTvAPI/shows/play/$id-$slug-$year"
|
||||
}
|
||||
app.get("$cinemaTvAPI/v1/shows?expand=episodes&id=${media.id_show}")
|
||||
.parsedSafe<CinemaTvResponse>()?.episodes?.find { it.episode == episode && it.season == season }?.id
|
||||
} ?: return
|
||||
|
||||
val session =
|
||||
"PHPSESSID=ngr4cudjrimdnhkth30ssohs0n; _csrf=a6ffd7bb7654083fce6df528225a238d0e85aa1fb885dc7638c1259ec1ba0d5ca%3A2%3A%7Bi%3A0%3Bs%3A5%3A%22_csrf%22%3Bi%3A1%3Bs%3A32%3A%22mTTLiDLjxohs-CpKk0bjRH3HdYMB9uBV%22%3B%7D; _ga=GA1.1.1195498587.1701871187; _ga_VZD7HJ3WK6=GS1.1.$unixTime.4.0.1.$unixTime.0.0.0"
|
||||
|
||||
val headers = mapOf(
|
||||
"Cookie" to session,
|
||||
"x-requested-with" to "com.wwcinematv",
|
||||
)
|
||||
|
||||
val doc = app.get(url, headers = headers).document
|
||||
val script = doc.selectFirst("script:containsData(hash:)")?.data()
|
||||
val hash = Regex("hash:\\s*['\"](\\S+)['\"]").find(script ?: return)?.groupValues?.get(1)
|
||||
val expires = Regex("expires:\\s*(\\d+)").find(script)?.groupValues?.get(1)
|
||||
val episodeId = (if (season == null) {
|
||||
"""id_movie:\s*(\d+)"""
|
||||
} else {
|
||||
"""episode:\s*['"]$episode['"],[\n\s]+id_episode:\s*(\d+),[\n\s]+season:\s*['"]$season['"]"""
|
||||
}).let { it.toRegex().find(script)?.groupValues?.get(1) }
|
||||
|
||||
val videoUrl = if (season == null) {
|
||||
"$cinemaTvAPI/api/v1/security/movie-access?id_movie=$episodeId&hash=$hash&expires=$expires"
|
||||
} else {
|
||||
"$cinemaTvAPI/api/v1/security/episode-access?id_episode=$episodeId&hash=$hash&expires=$expires"
|
||||
}
|
||||
|
||||
val sources = app.get(
|
||||
videoUrl,
|
||||
referer = url,
|
||||
headers = mapOf("X-Requested-With" to "XMLHttpRequest")
|
||||
).parsedSafe<CinemaTvResponse>()
|
||||
val sources = app.get("$cinemaTvAPI/v1/${if (season == null) "movies" else "episodes"}/view?expand=streams,subtitles&id=$mediaId").parsedSafe<CinemaTvResponse>()
|
||||
|
||||
sources?.streams?.mapKeys { source ->
|
||||
callback.invoke(
|
||||
|
@ -2335,19 +2294,18 @@ object SoraExtractor : SoraStream() {
|
|||
"CinemaTv",
|
||||
"CinemaTv",
|
||||
source.value,
|
||||
"$cinemaTvAPI/",
|
||||
"",
|
||||
getQualityFromName(source.key),
|
||||
true
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
sources?.subtitles?.map { sub ->
|
||||
val file = sub.file.toString()
|
||||
sources?.subtitles?.map {
|
||||
subtitleCallback.invoke(
|
||||
SubtitleFile(
|
||||
sub.language ?: return@map,
|
||||
if (file.startsWith("[")) return@map else fixUrl(file, cinemaTvAPI),
|
||||
it.language ?: return@map,
|
||||
fixUrl(it.url ?: return@map, cinemaTvAPI)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
@ -2410,37 +2368,25 @@ object SoraExtractor : SoraStream() {
|
|||
suspend fun invokeRidomovies(
|
||||
tmdbId: Int? = null,
|
||||
imdbId: String? = null,
|
||||
title: String? = null,
|
||||
season: Int? = null,
|
||||
episode: Int? = null,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val slug = if (season == null) {
|
||||
app.get("$ridomoviesAPI/core/api/search?q=$imdbId")
|
||||
.parsedSafe<RidoSearch>()?.data?.items?.find {
|
||||
it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId
|
||||
}?.slug
|
||||
} else {
|
||||
app.get("$ridomoviesAPI/tv/${title.createSlug()}/season-$season/episode-$episode").text.substringAfterLast(
|
||||
"""postid\":\""""
|
||||
).substringBefore("""\"""")
|
||||
} ?: return
|
||||
val url = if (season == null) {
|
||||
"$ridomoviesAPI/core/api/movies/$slug/videos"
|
||||
} else {
|
||||
"$ridomoviesAPI/core/api/episodes/$slug/videos"
|
||||
}
|
||||
val mediaSlug = app.get("$ridomoviesAPI/core/api/search?q=$imdbId").parsedSafe<RidoSearch>()?.data?.items?.find {
|
||||
it.contentable?.tmdbId == tmdbId || it.contentable?.imdbId == imdbId
|
||||
}?.slug ?: return
|
||||
|
||||
val id = season?.let {
|
||||
val episodeUrl = "$ridomoviesAPI/tv/$mediaSlug/season-$it/episode-$episode"
|
||||
app.get(episodeUrl).text.substringAfterLast("""postid\":\"""").substringBefore("""\""")
|
||||
} ?: mediaSlug
|
||||
|
||||
val url = "$ridomoviesAPI/core/api/${if (season == null) "movies" else "episodes"}/$id/videos"
|
||||
app.get(url).parsedSafe<RidoResponses>()?.data?.apmap { link ->
|
||||
val iframe = Jsoup.parse(link.url ?: return@apmap).select("iframe").attr("data-src")
|
||||
if (iframe.startsWith("https://closeload.top")) {
|
||||
val unpacked =
|
||||
getAndUnpack(
|
||||
app.get(
|
||||
iframe,
|
||||
referer = "$ridomoviesAPI/"
|
||||
).text
|
||||
)
|
||||
val unpacked = getAndUnpack(app.get(iframe, referer = "$ridomoviesAPI/").text)
|
||||
val video = Regex("=\"(aHR.*?)\";").find(unpacked)?.groupValues?.get(1)
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
|
|
|
@ -47,6 +47,23 @@ data class AniwaveServer(
|
|||
}
|
||||
}
|
||||
|
||||
data class MoflixResponse(
|
||||
@JsonProperty("title") val title: Episode? = null,
|
||||
@JsonProperty("episode") val episode: Episode? = null,
|
||||
) {
|
||||
data class Episode(
|
||||
@JsonProperty("id") val id: Int? = null,
|
||||
@JsonProperty("videos") val videos: ArrayList<Videos>? = arrayListOf(),
|
||||
) {
|
||||
data class Videos(
|
||||
@JsonProperty("name") val name: String? = null,
|
||||
@JsonProperty("category") val category: String? = null,
|
||||
@JsonProperty("src") val src: String? = null,
|
||||
@JsonProperty("quality") val quality: String? = null,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class AniMedia(
|
||||
@JsonProperty("id") var id: Int? = null,
|
||||
@JsonProperty("idMal") var idMal: Int? = null
|
||||
|
@ -174,15 +191,31 @@ data class JikanResponse(
|
|||
@JsonProperty("data") val data: JikanData? = null,
|
||||
)
|
||||
|
||||
data class CinemaTvSubtitles(
|
||||
@JsonProperty("language") val language: String? = null,
|
||||
@JsonProperty("file") val file: Any? = null,
|
||||
)
|
||||
|
||||
data class CinemaTvResponse(
|
||||
@JsonProperty("items") val items: ArrayList<Items>? = arrayListOf(),
|
||||
@JsonProperty("episodes") val episodes: ArrayList<Episodes>? = arrayListOf(),
|
||||
@JsonProperty("streams") val streams: HashMap<String, String>? = null,
|
||||
@JsonProperty("subtitles") val subtitles: ArrayList<CinemaTvSubtitles>? = arrayListOf(),
|
||||
)
|
||||
@JsonProperty("subtitles") val subtitles: ArrayList<Subtitles>? = arrayListOf(),
|
||||
) {
|
||||
data class Items(
|
||||
@JsonProperty("id_movie") val id_movie: Int? = null,
|
||||
@JsonProperty("id_show") val id_show: Int? = null,
|
||||
@JsonProperty("title") val title: String? = null,
|
||||
@JsonProperty("year") val year: Int? = null,
|
||||
@JsonProperty("imdb_id") val imdb_id: String? = null,
|
||||
)
|
||||
|
||||
data class Episodes(
|
||||
@JsonProperty("id") val id: Int? = null,
|
||||
@JsonProperty("season") val season: Int? = null,
|
||||
@JsonProperty("episode") val episode: Int? = null,
|
||||
)
|
||||
|
||||
data class Subtitles(
|
||||
@JsonProperty("language") val language: String? = null,
|
||||
@JsonProperty("url") val url: String? = null,
|
||||
)
|
||||
}
|
||||
|
||||
data class VidsrctoResult(
|
||||
@JsonProperty("id") val id: String? = null,
|
||||
|
@ -427,15 +460,6 @@ data class SmashySources(
|
|||
@JsonProperty("subtitleUrls") var subtitleUrls: String? = null,
|
||||
)
|
||||
|
||||
data class SmashyDSources(
|
||||
@JsonProperty("sourceUrls") var sourceUrls: ArrayList<SmashyDSourcesUrls>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class SmashyDSourcesUrls(
|
||||
@JsonProperty("file") var file: String? = null,
|
||||
@JsonProperty("title") var title: String? = null,
|
||||
)
|
||||
|
||||
data class AoneroomResponse(
|
||||
@JsonProperty("data") val data: Data? = null,
|
||||
) {
|
||||
|
|
|
@ -6,7 +6,6 @@ import com.hexated.SoraExtractor.invokeAllMovieland
|
|||
import com.hexated.SoraExtractor.invokeAnimes
|
||||
import com.hexated.SoraExtractor.invokeAoneroom
|
||||
import com.hexated.SoraExtractor.invokeBollyMaza
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeFilmxy
|
||||
import com.hexated.SoraExtractor.invokeKimcartoon
|
||||
import com.hexated.SoraExtractor.invokeVidSrc
|
||||
|
@ -36,15 +35,14 @@ import com.hexated.SoraExtractor.invokeEmovies
|
|||
import com.hexated.SoraExtractor.invokeHdmovies4u
|
||||
import com.hexated.SoraExtractor.invokeMultimovies
|
||||
import com.hexated.SoraExtractor.invokeNetmovies
|
||||
import com.hexated.SoraExtractor.invokeSFMovies
|
||||
import com.hexated.SoraExtractor.invokeShowflix
|
||||
import com.hexated.SoraExtractor.invokeTvMovies
|
||||
import com.hexated.SoraExtractor.invokeUhdmovies
|
||||
import com.hexated.SoraExtractor.invokeVegamovies
|
||||
import com.hexated.SoraExtractor.invokeVidsrcto
|
||||
import com.hexated.SoraExtractor.invokeCinemaTv
|
||||
import com.hexated.SoraExtractor.invokeMMovies
|
||||
import com.hexated.SoraExtractor.invokeOmovies
|
||||
import com.hexated.SoraExtractor.invokeMoflix
|
||||
import com.hexated.SoraExtractor.invokeGhostx
|
||||
import com.hexated.SoraExtractor.invokeWatchCartoon
|
||||
import com.hexated.SoraExtractor.invokeWatchsomuch
|
||||
import com.hexated.SoraExtractor.invokeZshow
|
||||
|
@ -119,6 +117,7 @@ open class SoraStream : TmdbProvider() {
|
|||
const val aoneroomAPI = "https://api3.aoneroom.com"
|
||||
const val mMoviesAPI = "https://multimovies.uno"
|
||||
const val watchCartoonAPI = "https://www1.watchcartoononline.bz"
|
||||
const val moflixAPI = "https://moflix-stream.xyz"
|
||||
|
||||
const val fdMoviesAPI = "https://freedrivemovie.com"
|
||||
const val uhdmoviesAPI = "https://uhdmovies.zip"
|
||||
|
@ -384,9 +383,6 @@ open class SoraStream : TmdbProvider() {
|
|||
{
|
||||
invokeVidSrc(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeAoneroom(
|
||||
res.title, res.airedYear
|
||||
|
@ -466,7 +462,7 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeOmovies(
|
||||
if (!res.isAnime) invokeGhostx(
|
||||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
|
@ -547,7 +543,7 @@ open class SoraStream : TmdbProvider() {
|
|||
},
|
||||
{
|
||||
if (!res.isAnime) invokeSmashyStream(
|
||||
res.imdbId,
|
||||
res.id,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
|
@ -587,7 +583,6 @@ open class SoraStream : TmdbProvider() {
|
|||
if (!res.isAnime) invokeRidomovies(
|
||||
res.id,
|
||||
res.imdbId,
|
||||
res.title,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
|
@ -716,13 +711,7 @@ open class SoraStream : TmdbProvider() {
|
|||
)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeSFMovies(
|
||||
res.id, res.title, res.airedYear
|
||||
?: res.year, res.season, res.episode, callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||
if (!res.isAnime) invokeMoflix(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
)
|
||||
|
||||
|
|
|
@ -4,7 +4,6 @@ import com.hexated.SoraExtractor.invoke2embed
|
|||
import com.hexated.SoraExtractor.invokeAllMovieland
|
||||
import com.hexated.SoraExtractor.invokeAnimes
|
||||
import com.hexated.SoraExtractor.invokeAoneroom
|
||||
import com.hexated.SoraExtractor.invokeDbgo
|
||||
import com.hexated.SoraExtractor.invokeDoomovies
|
||||
import com.hexated.SoraExtractor.invokeDramaday
|
||||
import com.hexated.SoraExtractor.invokeDreamfilm
|
||||
|
@ -24,13 +23,12 @@ import com.hexated.SoraExtractor.invokeDumpStream
|
|||
import com.hexated.SoraExtractor.invokeEmovies
|
||||
import com.hexated.SoraExtractor.invokeMultimovies
|
||||
import com.hexated.SoraExtractor.invokeNetmovies
|
||||
import com.hexated.SoraExtractor.invokeSFMovies
|
||||
import com.hexated.SoraExtractor.invokeShowflix
|
||||
import com.hexated.SoraExtractor.invokeVidSrc
|
||||
import com.hexated.SoraExtractor.invokeVidsrcto
|
||||
import com.hexated.SoraExtractor.invokeCinemaTv
|
||||
import com.hexated.SoraExtractor.invokeMMovies
|
||||
import com.hexated.SoraExtractor.invokeOmovies
|
||||
import com.hexated.SoraExtractor.invokeMoflix
|
||||
import com.hexated.SoraExtractor.invokeGhostx
|
||||
import com.hexated.SoraExtractor.invokeWatchCartoon
|
||||
import com.hexated.SoraExtractor.invokeWatchsomuch
|
||||
import com.hexated.SoraExtractor.invokeZshow
|
||||
|
@ -52,6 +50,9 @@ class SoraStreamLite : SoraStream() {
|
|||
val res = AppUtils.parseJson<LinkData>(data)
|
||||
|
||||
argamap(
|
||||
{
|
||||
if (!res.isAnime) invokeMoflix(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeWatchsomuch(
|
||||
res.imdbId,
|
||||
|
@ -93,9 +94,6 @@ class SoraStreamLite : SoraStream() {
|
|||
{
|
||||
invokeVidSrc(res.id, res.season, res.episode, callback)
|
||||
},
|
||||
{
|
||||
invokeDbgo(res.imdbId, res.season, res.episode, subtitleCallback, callback)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime && res.isCartoon) invokeWatchCartoon(
|
||||
res.title,
|
||||
|
@ -137,7 +135,7 @@ class SoraStreamLite : SoraStream() {
|
|||
)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeOmovies(
|
||||
if (!res.isAnime) invokeGhostx(
|
||||
res.title,
|
||||
res.year,
|
||||
res.season,
|
||||
|
@ -156,7 +154,7 @@ class SoraStreamLite : SoraStream() {
|
|||
},
|
||||
{
|
||||
if (!res.isAnime) invokeSmashyStream(
|
||||
res.imdbId,
|
||||
res.id,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
|
@ -226,7 +224,6 @@ class SoraStreamLite : SoraStream() {
|
|||
if (!res.isAnime) invokeRidomovies(
|
||||
res.id,
|
||||
res.imdbId,
|
||||
res.title,
|
||||
res.season,
|
||||
res.episode,
|
||||
subtitleCallback,
|
||||
|
@ -322,15 +319,6 @@ class SoraStreamLite : SoraStream() {
|
|||
callback
|
||||
)
|
||||
},
|
||||
{
|
||||
if (!res.isAnime) invokeSFMovies(
|
||||
res.id, res.title, res.airedYear
|
||||
?: res.year, res.season, res.episode, callback
|
||||
)
|
||||
},
|
||||
{
|
||||
invokeMMovies(res.title, res.season, res.episode, subtitleCallback, callback)
|
||||
},
|
||||
)
|
||||
|
||||
return true
|
||||
|
|
|
@ -25,7 +25,7 @@ class SoraStreamPlugin: Plugin() {
|
|||
registerExtractorAPI(Streamwish())
|
||||
registerExtractorAPI(FilelionsTo())
|
||||
registerExtractorAPI(Embedwish())
|
||||
registerExtractorAPI(Wishfast())
|
||||
registerExtractorAPI(UqloadsXyz())
|
||||
registerExtractorAPI(Uploadever())
|
||||
registerExtractorAPI(Netembed())
|
||||
registerExtractorAPI(Flaswish())
|
||||
|
|
|
@ -18,17 +18,12 @@ import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
|||
import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson
|
||||
import com.lagradost.nicehttp.NiceResponse
|
||||
import com.lagradost.nicehttp.RequestBodyTypes
|
||||
import com.lagradost.nicehttp.Requests.Companion.await
|
||||
import com.lagradost.nicehttp.requestCreator
|
||||
import kotlinx.coroutines.delay
|
||||
import okhttp3.FormBody
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.RequestBody.Companion.toRequestBody
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import java.math.BigInteger
|
||||
import java.net.*
|
||||
|
@ -38,7 +33,6 @@ import java.security.spec.PKCS8EncodedKeySpec
|
|||
import java.security.spec.X509EncodedKeySpec
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.TimeUnit
|
||||
import javax.crypto.Cipher
|
||||
import javax.crypto.spec.GCMParameterSpec
|
||||
import javax.crypto.spec.IvParameterSpec
|
||||
|
@ -427,21 +421,28 @@ suspend fun invokeSmashyFfix(
|
|||
|
||||
}
|
||||
|
||||
suspend fun invokeSmashyD(
|
||||
suspend fun invokeSmashySu(
|
||||
name: String,
|
||||
url: String,
|
||||
ref: String,
|
||||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val json = app.get(url, referer = ref, headers = mapOf("X-Requested-With" to "XMLHttpRequest"))
|
||||
.parsedSafe<SmashyDSources>()
|
||||
json?.sourceUrls?.apmap {
|
||||
M3u8Helper.generateM3u8(
|
||||
"Smashy [Player D ${it.title}]",
|
||||
it.file ?: return@apmap,
|
||||
""
|
||||
).forEach(callback)
|
||||
.parsedSafe<SmashySources>()
|
||||
json?.sourceUrls?.firstOrNull()?.removeSuffix(",")?.split(",")?.forEach { links ->
|
||||
val quality = Regex("\\[(\\S+)]").find(links)?.groupValues?.getOrNull(1) ?: return@forEach
|
||||
val trimmedLink = links.removePrefix("[$quality]").trim()
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"Smashy [$name]",
|
||||
"Smashy [$name]",
|
||||
trimmedLink,
|
||||
"",
|
||||
getQualityFromName(quality),
|
||||
INFER_TYPE
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
suspend fun getDumpIdAndType(title: String?, year: Int?, season: Int?): Pair<String?, Int?> {
|
||||
|
@ -800,6 +801,10 @@ suspend fun getCrunchyrollIdFromMalSync(aniId: String?): String? {
|
|||
?: regex.find("$crunchyroll")?.groupValues?.getOrNull(1)
|
||||
}
|
||||
|
||||
suspend fun String.haveDub(referer: String) : Boolean {
|
||||
return app.get(this,referer=referer).text.contains("TYPE=AUDIO")
|
||||
}
|
||||
|
||||
suspend fun convertTmdbToAnimeId(
|
||||
title: String?,
|
||||
date: String?,
|
||||
|
@ -1034,7 +1039,7 @@ fun decodeIndexJson(json: String): String {
|
|||
return base64Decode(slug.substring(0, slug.length - 20))
|
||||
}
|
||||
|
||||
fun String.decodePrimewireXor(key: String): String {
|
||||
fun String.xorDecrypt(key: String): String {
|
||||
val sb = StringBuilder()
|
||||
var i = 0
|
||||
while (i < this.length) {
|
||||
|
@ -1060,9 +1065,9 @@ fun vidsrctoDecrypt(text: String): String {
|
|||
}
|
||||
|
||||
fun String?.createSlug(): String? {
|
||||
return this?.replace(Regex("[^\\w\\s-]"), "")
|
||||
?.replace(" ", "-")
|
||||
?.replace(Regex("( – )|( -)|(- )|(--)"), "-")
|
||||
return this?.filter { it.isWhitespace() || it.isLetterOrDigit() }
|
||||
?.trim()
|
||||
?.replace("\\s+".toRegex(), "-")
|
||||
?.lowercase()
|
||||
}
|
||||
|
||||
|
@ -1148,14 +1153,6 @@ fun getVipLanguage(str: String): String {
|
|||
}
|
||||
}
|
||||
|
||||
fun getDbgoLanguage(str: String): String {
|
||||
return when (str) {
|
||||
"Русский" -> "Russian"
|
||||
"Українська" -> "Ukrainian"
|
||||
else -> str
|
||||
}
|
||||
}
|
||||
|
||||
fun fixCrunchyrollLang(language: String?): String? {
|
||||
return SubtitleHelper.fromTwoLettersToLanguage(language ?: return null)
|
||||
?: SubtitleHelper.fromTwoLettersToLanguage(language.substringBefore("-"))
|
||||
|
@ -1212,37 +1209,6 @@ fun base64DecodeAPI(api: String): String {
|
|||
return api.chunked(4).map { base64Decode(it) }.reversed().joinToString("")
|
||||
}
|
||||
|
||||
fun decryptStreamUrl(data: String): String {
|
||||
|
||||
fun getTrash(arr: List<String>, item: Int): List<String> {
|
||||
val trash = ArrayList<List<String>>()
|
||||
for (i in 1..item) {
|
||||
trash.add(arr)
|
||||
}
|
||||
return trash.reduce { acc, list ->
|
||||
val temp = ArrayList<String>()
|
||||
acc.forEach { ac ->
|
||||
list.forEach { li ->
|
||||
temp.add(ac.plus(li))
|
||||
}
|
||||
}
|
||||
return@reduce temp
|
||||
}
|
||||
}
|
||||
|
||||
val trashList = listOf("@", "#", "!", "^", "$")
|
||||
val trashSet = getTrash(trashList, 2) + getTrash(trashList, 3)
|
||||
var trashString = data.replace("#2", "").split("//_//").joinToString("")
|
||||
|
||||
trashSet.forEach {
|
||||
val temp = base64Encode(it.toByteArray())
|
||||
trashString = trashString.replace(temp, "")
|
||||
}
|
||||
|
||||
return base64Decode(trashString)
|
||||
|
||||
}
|
||||
|
||||
fun fixUrl(url: String, domain: String): String {
|
||||
if (url.startsWith("http")) {
|
||||
return url
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import org.jetbrains.kotlin.konan.properties.Properties
|
||||
|
||||
// use an integer for version numbers
|
||||
version = 1
|
||||
version = 3
|
||||
|
||||
android {
|
||||
defaultConfig {
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
package com.hexated
|
||||
|
||||
import com.lagradost.cloudstream3.*
|
||||
import com.lagradost.cloudstream3.mvvm.normalSafeApiCall
|
||||
import com.lagradost.cloudstream3.utils.*
|
||||
import java.net.URL
|
||||
|
||||
object Extractors : Superstream() {
|
||||
|
||||
|
@ -66,45 +68,44 @@ object Extractors : Superstream() {
|
|||
callback: (ExtractorLink) -> Unit,
|
||||
) {
|
||||
val (seasonSlug, episodeSlug) = getEpisodeSlug(season, episode)
|
||||
val shareKey = app.get(
|
||||
"$fourthAPI/index/share_link?id=${mediaId}&type=$type"
|
||||
).parsedSafe<ExternalResponse>()?.data?.link?.substringAfterLast("/")
|
||||
val shareKey = app.get("$fourthAPI/index/share_link?id=${mediaId}&type=$type")
|
||||
.parsedSafe<ExternalResponse>()?.data?.link?.substringAfterLast("/") ?: return
|
||||
|
||||
val headers = mapOf("Accept-Language" to "en")
|
||||
val shareRes = app.get(
|
||||
"$thirdAPI/file/file_share_list?share_key=${shareKey ?: return}",
|
||||
headers = headers
|
||||
).parsedSafe<ExternalResponse>()?.data
|
||||
val shareRes = app.get("$thirdAPI/file/file_share_list?share_key=$shareKey", headers = headers)
|
||||
.parsedSafe<ExternalResponse>()?.data ?: return
|
||||
|
||||
val fids = if (season == null) {
|
||||
shareRes?.file_list
|
||||
shareRes.file_list
|
||||
} else {
|
||||
val parentId =
|
||||
shareRes?.file_list?.find { it.file_name.equals("season $season", true) }?.fid
|
||||
app.get(
|
||||
"$thirdAPI/file/file_share_list?share_key=$shareKey&parent_id=$parentId&page=1",
|
||||
headers = headers
|
||||
).parsedSafe<ExternalResponse>()?.data?.file_list?.filter {
|
||||
it.file_name?.contains(
|
||||
"s${seasonSlug}e${episodeSlug}",
|
||||
true
|
||||
) == true
|
||||
}
|
||||
}
|
||||
val parentId = shareRes.file_list?.find { it.file_name.equals("season $season", true) }?.fid
|
||||
app.get("$thirdAPI/file/file_share_list?share_key=$shareKey&parent_id=$parentId&page=1", headers = headers)
|
||||
.parsedSafe<ExternalResponse>()?.data?.file_list?.filter {
|
||||
it.file_name?.contains("s${seasonSlug}e${episodeSlug}", true) == true
|
||||
}
|
||||
} ?: return
|
||||
|
||||
fids?.apmapIndexed { index, fileList ->
|
||||
fids.apmapIndexed { index, fileList ->
|
||||
val player = app.get("$thirdAPI/file/player?fid=${fileList.fid}&share_key=$shareKey").text
|
||||
val video = """"(https.*?m3u8.*?)"""".toRegex().find(player)?.groupValues?.get(1)
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"External",
|
||||
"External [Server ${index + 1}]",
|
||||
video?.replace("\\/", "/") ?: return@apmapIndexed,
|
||||
"$thirdAPI/",
|
||||
getIndexQuality(fileList.file_name),
|
||||
isM3u8 = true
|
||||
)
|
||||
)
|
||||
val sources = "sources\\s*=\\s*(.*);".toRegex().find(player)?.groupValues?.get(1)
|
||||
val qualities = "quality_list\\s*=\\s*(.*);".toRegex().find(player)?.groupValues?.get(1)
|
||||
listOf(sources, qualities).forEach {
|
||||
AppUtils.tryParseJson<ArrayList<ExternalSources>>(it)?.forEach org@{ source ->
|
||||
val format = if (source.type == "video/mp4") ExtractorLinkType.VIDEO else ExtractorLinkType.M3U8
|
||||
val label = if (format == ExtractorLinkType.M3U8) "Hls" else "Mp4"
|
||||
if(!(source.label == "AUTO" || format == ExtractorLinkType.VIDEO)) return@org
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
"External",
|
||||
"External $label [Server ${index + 1}]",
|
||||
(source.m3u8_url ?: source.file)?.replace("\\/", "/") ?: return@org,
|
||||
"",
|
||||
getIndexQuality(if (format == ExtractorLinkType.M3U8) fileList.file_name else source.label),
|
||||
type = format,
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -623,7 +623,6 @@ open class Superstream : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private data class LinkData(
|
||||
val id: Int,
|
||||
val type: Int,
|
||||
|
@ -633,7 +632,6 @@ open class Superstream : MainAPI() {
|
|||
val imdbId: String?,
|
||||
)
|
||||
|
||||
|
||||
data class LinkDataProp(
|
||||
@JsonProperty("code") val code: Int? = null,
|
||||
@JsonProperty("msg") val msg: String? = null,
|
||||
|
@ -776,6 +774,13 @@ open class Superstream : MainAPI() {
|
|||
}
|
||||
}
|
||||
|
||||
data class ExternalSources(
|
||||
@JsonProperty("m3u8_url") val m3u8_url: String? = null,
|
||||
@JsonProperty("file") val file: String? = null,
|
||||
@JsonProperty("label") val label: String? = null,
|
||||
@JsonProperty("type") val type: String? = null,
|
||||
)
|
||||
|
||||
data class WatchsomuchTorrents(
|
||||
@JsonProperty("id") val id: Int? = null,
|
||||
@JsonProperty("movieId") val movieId: Int? = null,
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// use an integer for version numbers
|
||||
version = 22
|
||||
version = 23
|
||||
|
||||
|
||||
cloudstream {
|
||||
|
|
|
@ -4,7 +4,7 @@ import com.lagradost.cloudstream3.*
|
|||
import com.lagradost.cloudstream3.utils.AppUtils
|
||||
import com.lagradost.cloudstream3.utils.AppUtils.toJson
|
||||
import com.lagradost.cloudstream3.utils.ExtractorLink
|
||||
import com.lagradost.cloudstream3.utils.M3u8Helper
|
||||
import com.lagradost.cloudstream3.utils.Qualities
|
||||
import org.jsoup.nodes.Element
|
||||
import java.net.URI
|
||||
|
||||
|
@ -14,22 +14,22 @@ class TimefourTv : MainAPI() {
|
|||
override val hasDownloadSupport = false
|
||||
override val hasMainPage = true
|
||||
override val supportedTypes = setOf(
|
||||
TvType.Live
|
||||
TvType.Live
|
||||
)
|
||||
|
||||
private val homePoster =
|
||||
"https://cdn.discordapp.com/attachments/1109266606292488297/1193060449193840681/Screenshot_2024-01-06_at_12-14-16_Logo_Maker_Used_By_2.3_Million_Startups.png"
|
||||
"https://cdn.discordapp.com/attachments/1109266606292488297/1193060449193840681/Screenshot_2024-01-06_at_12-14-16_Logo_Maker_Used_By_2.3_Million_Startups.png"
|
||||
private val detailPoster =
|
||||
"https://cdn.discordapp.com/attachments/1109266606292488297/1193060448929595454/Screenshot_2024-01-06_at_12-13-02_Logo_Maker_Used_By_2.3_Million_Startups.png"
|
||||
"https://cdn.discordapp.com/attachments/1109266606292488297/1193060448929595454/Screenshot_2024-01-06_at_12-13-02_Logo_Maker_Used_By_2.3_Million_Startups.png"
|
||||
|
||||
override val mainPage = mainPageOf(
|
||||
"$mainUrl/24-7-channels.php" to "24/7 Channels",
|
||||
"$mainUrl/schedule/schedule-generated.json" to "Schedule Channels"
|
||||
"$mainUrl/24-7-channels.php" to "24/7 Channels",
|
||||
"$mainUrl/schedule/schedule-generated.json" to "Schedule Channels"
|
||||
)
|
||||
|
||||
override suspend fun getMainPage(
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
page: Int,
|
||||
request: MainPageRequest
|
||||
): HomePageResponse {
|
||||
val items = mutableListOf<HomePageList>()
|
||||
if (request.name == "24/7 Channels") {
|
||||
|
@ -46,11 +46,11 @@ class TimefourTv : MainAPI() {
|
|||
val header = tag.key
|
||||
val channels = tag.value.mapNotNull {
|
||||
LiveSearchResponse(
|
||||
it.key,
|
||||
Item(it.key, items = it.value.toJson()).toJson(),
|
||||
this@TimefourTv.name,
|
||||
TvType.Live,
|
||||
posterUrl = homePoster,
|
||||
it.key,
|
||||
Item(it.key, items = it.value.toJson()).toJson(),
|
||||
this@TimefourTv.name,
|
||||
TvType.Live,
|
||||
posterUrl = homePoster,
|
||||
)
|
||||
}
|
||||
if (channels.isNotEmpty()) items.add(HomePageList(header, channels, true))
|
||||
|
@ -64,11 +64,11 @@ class TimefourTv : MainAPI() {
|
|||
val title = this.select("strong").text()
|
||||
val href = fixUrl(this.select("a").attr("href"))
|
||||
return LiveSearchResponse(
|
||||
title,
|
||||
Item(title, href).toJson(),
|
||||
this@TimefourTv.name,
|
||||
TvType.Live,
|
||||
posterUrl = homePoster,
|
||||
title,
|
||||
Item(title, href).toJson(),
|
||||
this@TimefourTv.name,
|
||||
TvType.Live,
|
||||
posterUrl = homePoster,
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -88,18 +88,18 @@ class TimefourTv : MainAPI() {
|
|||
val items = AppUtils.parseJson<ArrayList<Items>>(data.items)
|
||||
items.mapNotNull { eps ->
|
||||
Episode(
|
||||
data = eps.channels?.toJson() ?: return@mapNotNull null,
|
||||
name = "${eps.event} • ${eps.time}",
|
||||
description = eps.channels.map { it.channel_name }.joinToString(" • "),
|
||||
posterUrl = detailPoster,
|
||||
data = eps.channels?.toJson() ?: return@mapNotNull null,
|
||||
name = "${eps.event} • ${eps.time}",
|
||||
description = eps.channels.map { it.channel_name }.joinToString(" • "),
|
||||
posterUrl = detailPoster,
|
||||
)
|
||||
}
|
||||
}
|
||||
return newTvSeriesLoadResponse(
|
||||
data.title ?: "",
|
||||
url,
|
||||
TvType.TvSeries,
|
||||
episodes = episodes
|
||||
data.title ?: "",
|
||||
url,
|
||||
TvType.TvSeries,
|
||||
episodes = episodes
|
||||
) {
|
||||
posterUrl = homePoster
|
||||
}
|
||||
|
@ -107,29 +107,34 @@ class TimefourTv : MainAPI() {
|
|||
}
|
||||
|
||||
override suspend fun loadLinks(
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
data: String,
|
||||
isCasting: Boolean,
|
||||
subtitleCallback: (SubtitleFile) -> Unit,
|
||||
callback: (ExtractorLink) -> Unit
|
||||
): Boolean {
|
||||
|
||||
val json = AppUtils.parseJson<ArrayList<Channels>>(data)
|
||||
|
||||
json.apmap {
|
||||
val iframe = app.get(
|
||||
fixChannelUrl(
|
||||
it.channel_id ?: return@apmap
|
||||
)
|
||||
fixChannelUrl(
|
||||
it.channel_id ?: return@apmap
|
||||
)
|
||||
).document.selectFirst("iframe#thatframe")?.attr("src")
|
||||
?: throw ErrorLoadingException("No Iframe Found")
|
||||
?: throw ErrorLoadingException("No Iframe Found")
|
||||
val host = getBaseUrl(iframe)
|
||||
val video = extractVideo(iframe)
|
||||
|
||||
M3u8Helper.generateM3u8(
|
||||
callback.invoke(
|
||||
ExtractorLink(
|
||||
this.name,
|
||||
it.channel_name ?: return@apmap,
|
||||
video ?: return@apmap,
|
||||
"$host/",
|
||||
).forEach(callback)
|
||||
Qualities.Unknown.value,
|
||||
isM3u8 = true,
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
return true
|
||||
|
@ -138,13 +143,13 @@ class TimefourTv : MainAPI() {
|
|||
private suspend fun extractVideo(url: String): String? {
|
||||
val res = app.get(url, referer = mainUrl)
|
||||
return Regex("""source:['"](\S+.m3u8)['"],""").find(res.text)?.groupValues?.getOrNull(
|
||||
1
|
||||
1
|
||||
) ?: run {
|
||||
val scriptData =
|
||||
res.document.selectFirst("div#player")?.nextElementSibling()?.data()
|
||||
?.substringAfterLast("return(")?.substringBefore(".join")
|
||||
res.document.selectFirst("div#player")?.nextElementSibling()?.data()
|
||||
?.substringAfterLast("return(")?.substringBefore(".join")
|
||||
scriptData?.removeSurrounding("[", "]")?.replace("\"", "")?.split(",")
|
||||
?.joinToString("")
|
||||
?.joinToString("")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,20 +168,20 @@ class TimefourTv : MainAPI() {
|
|||
}
|
||||
|
||||
data class Item(
|
||||
val title: String? = null,
|
||||
val url: String? = null,
|
||||
val items: String? = null,
|
||||
val title: String? = null,
|
||||
val url: String? = null,
|
||||
val items: String? = null,
|
||||
)
|
||||
|
||||
data class Items(
|
||||
val time: String? = null,
|
||||
val event: String? = null,
|
||||
val channels: ArrayList<Channels>? = arrayListOf(),
|
||||
val time: String? = null,
|
||||
val event: String? = null,
|
||||
val channels: ArrayList<Channels>? = arrayListOf(),
|
||||
)
|
||||
|
||||
data class Channels(
|
||||
val channel_name: String? = null,
|
||||
val channel_id: String? = null,
|
||||
val channel_name: String? = null,
|
||||
val channel_id: String? = null,
|
||||
)
|
||||
|
||||
}
|
|
@ -77,7 +77,7 @@ subprojects {
|
|||
// https://github.com/recloudstream/cloudstream/blob/master/app/build.gradle
|
||||
|
||||
implementation(kotlin("stdlib")) // adds standard kotlin features, like listOf, mapOf etc
|
||||
implementation("com.github.Blatzar:NiceHttp:0.4.4") // http library
|
||||
implementation("com.github.Blatzar:NiceHttp:0.4.5") // http library
|
||||
implementation("org.jsoup:jsoup:1.17.2") // html parser
|
||||
implementation("com.fasterxml.jackson.module:jackson-module-kotlin:2.16.1")
|
||||
implementation("io.karn:khttp-android:0.1.2")
|
||||
|
|
Loading…
Reference in New Issue