mirror of
https://github.com/recloudstream/cloudstream.git
synced 2024-08-15 01:53:11 +00:00
added Vidmoly & Voe (extractor) (#147)
This commit is contained in:
parent
b3ff3ec086
commit
98ef6a3f16
3 changed files with 127 additions and 4 deletions
|
@ -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<Source>(videoData)?.file?.let { m3uLink ->
|
||||||
|
M3u8Helper.generateM3u8(
|
||||||
|
name,
|
||||||
|
m3uLink,
|
||||||
|
"$mainUrl/"
|
||||||
|
).forEach(callback)
|
||||||
|
}
|
||||||
|
|
||||||
|
tryParseJson<List<SubSource>>("[${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,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
|
@ -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)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,7 @@
|
||||||
package com.lagradost.cloudstream3.utils
|
package com.lagradost.cloudstream3.utils
|
||||||
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import com.lagradost.cloudstream3.SubtitleFile
|
import com.lagradost.cloudstream3.*
|
||||||
import com.lagradost.cloudstream3.TvType
|
|
||||||
import com.lagradost.cloudstream3.USER_AGENT
|
|
||||||
import com.lagradost.cloudstream3.app
|
|
||||||
import com.lagradost.cloudstream3.mvvm.logError
|
import com.lagradost.cloudstream3.mvvm.logError
|
||||||
import com.lagradost.cloudstream3.extractors.*
|
import com.lagradost.cloudstream3.extractors.*
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
|
@ -323,6 +320,9 @@ val extractorApis: MutableList<ExtractorApi> = arrayListOf(
|
||||||
Embedgram(),
|
Embedgram(),
|
||||||
Mvidoo(),
|
Mvidoo(),
|
||||||
Streamplay(),
|
Streamplay(),
|
||||||
|
Vidmoly(),
|
||||||
|
Vidmolyme(),
|
||||||
|
Voe(),
|
||||||
|
|
||||||
Gdriveplayerapi(),
|
Gdriveplayerapi(),
|
||||||
Gdriveplayerapp(),
|
Gdriveplayerapp(),
|
||||||
|
@ -399,6 +399,28 @@ suspend fun getPostForm(requestUrl: String, html: String): String? {
|
||||||
).text
|
).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 class ExtractorApi {
|
||||||
abstract val name: String
|
abstract val name: String
|
||||||
abstract val mainUrl: String
|
abstract val mainUrl: String
|
||||||
|
|
Loading…
Reference in a new issue