From 98ef6a3f160d73f66095643892858a24f4ed43ce Mon Sep 17 00:00:00 2001 From: Hexated <37908684+hexated@users.noreply.github.com> Date: Tue, 11 Oct 2022 02:43:56 +0700 Subject: [PATCH] added Vidmoly & Voe (extractor) (#147) --- .../cloudstream3/extractors/Vidmoly.kt | 69 +++++++++++++++++++ .../lagradost/cloudstream3/extractors/Voe.kt | 32 +++++++++ .../cloudstream3/utils/ExtractorApi.kt | 30 ++++++-- 3 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt create mode 100644 app/src/main/java/com/lagradost/cloudstream3/extractors/Voe.kt diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt new file mode 100644 index 00000000..615cfd74 --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Vidmoly.kt @@ -0,0 +1,69 @@ +package com.lagradost.cloudstream3.extractors + +import com.fasterxml.jackson.annotation.JsonProperty +import com.lagradost.cloudstream3.SubtitleFile +import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.utils.* +import com.lagradost.cloudstream3.utils.AppUtils.tryParseJson + +class Vidmolyme : Vidmoly() { + override val mainUrl = "https://vidmoly.me" +} + +open class Vidmoly : ExtractorApi() { + override val name = "Vidmoly" + override val mainUrl = "https://vidmoly.to" + override val requiresReferer = true + + private fun String.addMarks(str: String): String { + return this.replace(Regex("\"?$str\"?"), "\"$str\"") + } + + override suspend fun getUrl( + url: String, + referer: String?, + subtitleCallback: (SubtitleFile) -> Unit, + callback: (ExtractorLink) -> Unit + ) { + + val script = app.get( + url, + referer = referer, + ).document.select("script") + .find { it.data().contains("sources:") }?.data() + val videoData = script?.substringAfter("sources: [") + ?.substringBefore("],")?.addMarks("file") + val subData = script?.substringAfter("tracks: [")?.substringBefore("]")?.addMarks("file") + ?.addMarks("label")?.addMarks("kind") + + tryParseJson(videoData)?.file?.let { m3uLink -> + M3u8Helper.generateM3u8( + name, + m3uLink, + "$mainUrl/" + ).forEach(callback) + } + + tryParseJson>("[${subData}]") + ?.filter { it.kind == "captions" }?.map { + subtitleCallback.invoke( + SubtitleFile( + it.label.toString(), + fixUrl(it.file.toString()) + ) + ) + } + + } + + private data class Source( + @JsonProperty("file") val file: String? = null, + ) + + private data class SubSource( + @JsonProperty("file") val file: String? = null, + @JsonProperty("label") val label: String? = null, + @JsonProperty("kind") val kind: String? = null, + ) + +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/extractors/Voe.kt b/app/src/main/java/com/lagradost/cloudstream3/extractors/Voe.kt new file mode 100644 index 00000000..12a76a9b --- /dev/null +++ b/app/src/main/java/com/lagradost/cloudstream3/extractors/Voe.kt @@ -0,0 +1,32 @@ +package com.lagradost.cloudstream3.extractors + +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.M3u8Helper + +open class Voe : ExtractorApi() { + override val name = "Voe" + override val mainUrl = "https://voe.sx" + 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 link = res.select("script").find { it.data().contains("const sources") }?.data() + ?.substringAfter("\"hls\": \"")?.substringBefore("\",") + + M3u8Helper.generateM3u8( + name, + link ?: return, + "$mainUrl/", + headers = mapOf("Origin" to "$mainUrl/") + ).forEach(callback) + + } +} \ No newline at end of file diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt index 199f0398..ebaaa12b 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ExtractorApi.kt @@ -1,10 +1,7 @@ package com.lagradost.cloudstream3.utils import android.net.Uri -import com.lagradost.cloudstream3.SubtitleFile -import com.lagradost.cloudstream3.TvType -import com.lagradost.cloudstream3.USER_AGENT -import com.lagradost.cloudstream3.app +import com.lagradost.cloudstream3.* import com.lagradost.cloudstream3.mvvm.logError import com.lagradost.cloudstream3.extractors.* import kotlinx.coroutines.delay @@ -323,6 +320,9 @@ val extractorApis: MutableList = arrayListOf( Embedgram(), Mvidoo(), Streamplay(), + Vidmoly(), + Vidmolyme(), + Voe(), Gdriveplayerapi(), Gdriveplayerapp(), @@ -399,6 +399,28 @@ suspend fun getPostForm(requestUrl: String, html: String): String? { ).text } +fun ExtractorApi.fixUrl(url: String): String { + if (url.startsWith("http") || + // Do not fix JSON objects when passed as urls. + url.startsWith("{\"") + ) { + return url + } + if (url.isEmpty()) { + return "" + } + + val startsWithNoHttp = url.startsWith("//") + if (startsWithNoHttp) { + return "https:$url" + } else { + if (url.startsWith('/')) { + return mainUrl + url + } + return "$mainUrl/$url" + } +} + abstract class ExtractorApi { abstract val name: String abstract val mainUrl: String