Fixes and Updates (#1090)
This commit is contained in:
parent
f0442520cb
commit
a7c1fe3017
@ -13,8 +13,7 @@ class FembedExtractor(private val client: OkHttpClient) {
|
|||||||
client.newCall(POST(videoApi)).execute().body?.string().orEmpty()
|
client.newCall(POST(videoApi)).execute().body?.string().orEmpty()
|
||||||
}.getOrNull() ?: return emptyList<Video>()
|
}.getOrNull() ?: return emptyList<Video>()
|
||||||
|
|
||||||
val jsonResponse = Json { ignoreUnknownKeys = true }
|
val jsonResponse = try{ Json { ignoreUnknownKeys = true }.decodeFromString<FembedResponse>(body) } catch (e: Exception) { FembedResponse(false, emptyList()) }
|
||||||
.decodeFromString<FembedResponse>(body)
|
|
||||||
|
|
||||||
return if (jsonResponse.success) {
|
return if (jsonResponse.success) {
|
||||||
jsonResponse.data.map {
|
jsonResponse.data.map {
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package eu.kanade.tachiyomi.lib.streamsbextractor
|
package eu.kanade.tachiyomi.lib.streamsbextractor
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.Track
|
||||||
import eu.kanade.tachiyomi.animesource.model.Video
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import kotlinx.serialization.decodeFromString
|
import kotlinx.serialization.decodeFromString
|
||||||
@ -73,4 +74,30 @@ class StreamSBExtractor(private val client: OkHttpClient) {
|
|||||||
emptyList<Video>()
|
emptyList<Video>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun videosFromDecryptedUrl(realUrl: String, headers: Headers, prefix: String = "", suffix: String = ""): List<Video> {
|
||||||
|
return try {
|
||||||
|
val json = Json.decodeFromString<JsonObject>(client.newCall(GET(realUrl, headers)).execute().body!!.string())
|
||||||
|
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
|
||||||
|
val masterPlaylist = client.newCall(GET(masterUrl, headers)).execute().body!!.string()
|
||||||
|
val separator = "#EXT-X-STREAM-INF"
|
||||||
|
masterPlaylist.substringAfter(separator).split(separator).map {
|
||||||
|
val resolution = it.substringAfter("RESOLUTION=")
|
||||||
|
.substringBefore("\n")
|
||||||
|
.substringAfter("x")
|
||||||
|
.substringBefore(",") + "p"
|
||||||
|
val quality = ("StreamSB:$resolution").let {
|
||||||
|
if(prefix.isNotBlank()) "$prefix $it"
|
||||||
|
else it
|
||||||
|
}.let {
|
||||||
|
if(suffix.isNotBlank()) "$it $suffix"
|
||||||
|
else it
|
||||||
|
}
|
||||||
|
val videoUrl = it.substringAfter("\n").substringBefore("\n")
|
||||||
|
Video(videoUrl, quality, videoUrl, headers = headers)
|
||||||
|
}
|
||||||
|
} catch (e: Exception) {
|
||||||
|
emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,15 +6,13 @@ import eu.kanade.tachiyomi.util.asJsoup
|
|||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
|
||||||
class VoeExtractor(private val client: OkHttpClient) {
|
class VoeExtractor(private val client: OkHttpClient) {
|
||||||
|
|
||||||
fun videoFromUrl(url: String, quality: String? = null): Video? {
|
fun videoFromUrl(url: String, quality: String? = null): Video? {
|
||||||
val document = client.newCall(GET(url)).execute().asJsoup()
|
val document = client.newCall(GET(url)).execute().asJsoup()
|
||||||
val script = document.selectFirst("script:containsData(const sources)")
|
val script = document.selectFirst("script:containsData(const sources)")
|
||||||
?.data()
|
?.data()
|
||||||
?: return null
|
?: return null
|
||||||
val videoUrl = script.substringAfter("hls': '").substringBefore("'")
|
val videoUrl = script.substringAfter("hls': '").substringBefore("'")
|
||||||
val resolution = script.substringAfter("video_height': ")
|
val resolution = script.substringAfter("video_height': ").substringBefore(",")
|
||||||
.substringBefore(",")
|
|
||||||
val qualityStr = quality ?: "VoeCDN(${resolution}p)"
|
val qualityStr = quality ?: "VoeCDN(${resolution}p)"
|
||||||
return Video(url, qualityStr, videoUrl)
|
return Video(url, qualityStr, videoUrl)
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ ext {
|
|||||||
extName = 'AnimeFLV'
|
extName = 'AnimeFLV'
|
||||||
pkgNameSuffix = 'es.animeflv'
|
pkgNameSuffix = 'es.animeflv'
|
||||||
extClass = '.AnimeFlv'
|
extClass = '.AnimeFlv'
|
||||||
extVersionCode = 31
|
extVersionCode = 32
|
||||||
libVersion = '13'
|
libVersion = '13'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.animeextension.es.animeflv
|
|||||||
|
|
||||||
import android.app.Application
|
import android.app.Application
|
||||||
import android.content.SharedPreferences
|
import android.content.SharedPreferences
|
||||||
|
import android.util.Log
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.animeextension.es.animeflv.extractors.YourUploadExtractor
|
import eu.kanade.tachiyomi.animeextension.es.animeflv.extractors.YourUploadExtractor
|
||||||
@ -33,7 +34,7 @@ import org.jsoup.nodes.Element
|
|||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
import uy.kohesive.injekt.injectLazy
|
||||||
import java.lang.Exception
|
import kotlin.Exception
|
||||||
|
|
||||||
class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
|
|
||||||
@ -116,31 +117,43 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
val quality = json!!["title"]!!.jsonPrimitive!!.content
|
val quality = json!!["title"]!!.jsonPrimitive!!.content
|
||||||
var url = json!!["code"]!!.jsonPrimitive!!.content
|
var url = json!!["code"]!!.jsonPrimitive!!.content
|
||||||
if (quality == "SB") {
|
if (quality == "SB") {
|
||||||
videoList.addAll(
|
try {
|
||||||
StreamSBExtractor(client).videosFromUrl(url, headers)
|
videoList.addAll(
|
||||||
)
|
StreamSBExtractor(client).videosFromUrl(url, headers)
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
if (quality == "Fembed") {
|
if (quality == "Fembed") {
|
||||||
videoList.addAll(
|
try {
|
||||||
FembedExtractor(client).videosFromUrl(url)
|
videoList.addAll(
|
||||||
)
|
FembedExtractor(client).videosFromUrl(url)
|
||||||
|
)
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
if (quality == "Stape") {
|
if (quality == "Stape") {
|
||||||
val url1 = json!!["url"]!!.jsonPrimitive!!.content
|
try {
|
||||||
val video = StreamTapeExtractor(client).videoFromUrl(url1)
|
val url1 = json!!["url"]!!.jsonPrimitive!!.content
|
||||||
if (video != null) videoList.add(video)
|
val video = StreamTapeExtractor(client).videoFromUrl(url1)
|
||||||
|
if (video != null) videoList.add(video)
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
if (quality == "Doodstream") {
|
if (quality == "Doodstream") {
|
||||||
val video = DoodExtractor(client).videoFromUrl(url, "DoodStream", false)
|
try {
|
||||||
if (video != null) videoList.add(video)
|
val video = DoodExtractor(client).videoFromUrl(url, "DoodStream", false)
|
||||||
|
if (video != null) videoList.add(video)
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
if (quality == "Okru") {
|
if (quality == "Okru") {
|
||||||
val videos = OkruExtractor(client).videosFromUrl(url)
|
try {
|
||||||
videoList.addAll(videos)
|
val videos = OkruExtractor(client).videosFromUrl(url)
|
||||||
|
videoList.addAll(videos)
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
if (quality == "YourUpload") {
|
if (quality == "YourUpload") {
|
||||||
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
|
try {
|
||||||
YourUploadExtractor(client).videoFromUrl(url, headers = headers).map { videoList.add(it) }
|
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
|
||||||
|
YourUploadExtractor(client).videoFromUrl(url, headers = headers).map { videoList.add(it) }
|
||||||
|
} catch (_: Exception) {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,23 +191,35 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||||
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||||
|
val stateFilter = filterList.find { it is StateFilter } as StateFilter
|
||||||
|
val typeFilter = filterList.find { it is TypeFilter } as TypeFilter
|
||||||
|
val orderByFilter = filterList.find { it is OrderByFilter } as OrderByFilter
|
||||||
|
var uri = "$baseUrl/browse?"
|
||||||
|
uri += if (query.isNotBlank()) "&q=$query" else ""
|
||||||
|
uri += if (genreFilter.state != 0) "&genre[]=${genreFilter.toUriPart()}" else ""
|
||||||
|
uri += if (stateFilter.state != 0) "&status[]=${stateFilter.toUriPart()}" else ""
|
||||||
|
uri += if (typeFilter.state != 0) "&type[]=${typeFilter.toUriPart()}" else ""
|
||||||
|
uri += "&order=${orderByFilter.toUriPart()}"
|
||||||
|
uri += "&page=$page"
|
||||||
return when {
|
return when {
|
||||||
query.isNotBlank() -> GET("$baseUrl/browse?q=$query&order=rating&page=$page")
|
query.isNotBlank() || genreFilter.state != 0 || stateFilter.state != 0 || orderByFilter.state != 0 || typeFilter.state != 0 -> GET(uri)
|
||||||
genreFilter.state != 0 -> GET("$baseUrl/browse?genre[]=${genreFilter.toUriPart()}&order=rating&page=$page")
|
|
||||||
else -> GET("$baseUrl/browse?page=$page&order=rating")
|
else -> GET("$baseUrl/browse?page=$page&order=rating")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||||
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
|
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
|
||||||
GenreFilter()
|
GenreFilter(),
|
||||||
|
StateFilter(),
|
||||||
|
TypeFilter(),
|
||||||
|
OrderByFilter()
|
||||||
)
|
)
|
||||||
|
|
||||||
private class GenreFilter : UriPartFilter(
|
private class GenreFilter : UriPartFilter(
|
||||||
"Géneros",
|
"Géneros",
|
||||||
arrayOf(
|
arrayOf(
|
||||||
Pair("<Selecionar>", "all"),
|
Pair("<Selecionar>", "all"),
|
||||||
|
Pair("Todo", "all"),
|
||||||
Pair("Acción", "accion"),
|
Pair("Acción", "accion"),
|
||||||
Pair("Artes Marciales", "artes_marciales"),
|
Pair("Artes Marciales", "artes_marciales"),
|
||||||
Pair("Aventuras", "aventura"),
|
Pair("Aventuras", "aventura"),
|
||||||
@ -238,6 +263,38 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private class StateFilter : UriPartFilter(
|
||||||
|
"Estado",
|
||||||
|
arrayOf(
|
||||||
|
Pair("<Seleccionar>", ""),
|
||||||
|
Pair("En emisión", "1"),
|
||||||
|
Pair("Finalizado", "2"),
|
||||||
|
Pair("Próximamente", "3")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private class TypeFilter : UriPartFilter(
|
||||||
|
"Tipo",
|
||||||
|
arrayOf(
|
||||||
|
Pair("<Seleccionar>", ""),
|
||||||
|
Pair("TV", "tv"),
|
||||||
|
Pair("Película", "movie"),
|
||||||
|
Pair("Especial", "special"),
|
||||||
|
Pair("OVA", "ova")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
private class OrderByFilter : UriPartFilter(
|
||||||
|
"Ordenar Por",
|
||||||
|
arrayOf(
|
||||||
|
Pair("Por defecto", "default"),
|
||||||
|
Pair("Recientemente Actualizados", "updated"),
|
||||||
|
Pair("Recientemente Agregados", "added"),
|
||||||
|
Pair("Nombre A-Z", "title"),
|
||||||
|
Pair("Calificación", "rating")
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||||
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||||
fun toUriPart() = vals[state].second
|
fun toUriPart() = vals[state].second
|
||||||
|
@ -5,7 +5,7 @@ ext {
|
|||||||
extName = 'AnimeLatinoHD'
|
extName = 'AnimeLatinoHD'
|
||||||
pkgNameSuffix = 'es.animelatinohd'
|
pkgNameSuffix = 'es.animelatinohd'
|
||||||
extClass = '.AnimeLatinoHD'
|
extClass = '.AnimeLatinoHD'
|
||||||
extVersionCode = 9
|
extVersionCode = 10
|
||||||
libVersion = '13'
|
libVersion = '13'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,6 +143,12 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
return list
|
return list
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun fetchUrls(text: String?): List<String> {
|
||||||
|
if (text.isNullOrEmpty()) return listOf()
|
||||||
|
val linkRegex = "(https?://(www\\.)?[-a-zA-Z0-9@:%._+~#=]{1,256}\\.[a-zA-Z0-9()]{1,6}\\b([-a-zA-Z0-9()@:%_+.~#?&/=]*))".toRegex()
|
||||||
|
return linkRegex.findAll(text).map { it.value.trim().removeSurrounding("\"") }.toList()
|
||||||
|
}
|
||||||
|
|
||||||
override fun videoListParse(response: Response): List<Video> {
|
override fun videoListParse(response: Response): List<Video> {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val videoList = mutableListOf<Video>()
|
val videoList = mutableListOf<Video>()
|
||||||
@ -158,45 +164,82 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
val servers = player!!.jsonArray
|
val servers = player!!.jsonArray
|
||||||
servers.forEach { server ->
|
servers.forEach { server ->
|
||||||
val item = server!!.jsonObject
|
val item = server!!.jsonObject
|
||||||
val url = item["code"]!!.jsonPrimitive!!.content
|
val request = client.newCall(
|
||||||
val language = if (item["languaje"]!!.jsonPrimitive!!.content == "1") "[Lat] " else "[Sub] "
|
GET(
|
||||||
if (url.lowercase().contains("streamsb")) {
|
url = "https://api.animelatinohd.com/stream/${item["id"]!!.jsonPrimitive.content}",
|
||||||
val videos = StreamSBExtractor(client).videosFromUrl(url, headers, language)
|
headers = headers.newBuilder().add("Referer", "https://www.animelatinohd.com/").build()
|
||||||
videoList.addAll(videos)
|
)
|
||||||
}
|
).execute()
|
||||||
if (url.lowercase().contains("www.fembed.com")) {
|
val locationsDdh = request!!.networkResponse.toString()
|
||||||
val videos = FembedExtractor(client).videosFromUrl(url, language)
|
fetchUrls(locationsDdh).map { url ->
|
||||||
videoList.addAll(videos)
|
val language = if (item["languaje"]!!.jsonPrimitive!!.content == "1") "[Lat] " else "[Sub] "
|
||||||
}
|
val embedUrl = url.lowercase()
|
||||||
if (url.lowercase().contains("streamtape")) {
|
if (embedUrl.contains("sbembed.com") || embedUrl.contains("sbembed1.com") || embedUrl.contains("sbplay.org") ||
|
||||||
val video = StreamTapeExtractor(client).videoFromUrl(url, language + "Streamtape")
|
embedUrl.contains("sbvideo.net") || embedUrl.contains("streamsb.net") || embedUrl.contains("sbplay.one") ||
|
||||||
if (video != null) {
|
embedUrl.contains("cloudemb.com") || embedUrl.contains("playersb.com") || embedUrl.contains("tubesb.com") ||
|
||||||
videoList.add(video)
|
embedUrl.contains("sbplay1.com") || embedUrl.contains("embedsb.com") || embedUrl.contains("watchsb.com") ||
|
||||||
|
embedUrl.contains("sbplay2.com") || embedUrl.contains("japopav.tv") || embedUrl.contains("viewsb.com") ||
|
||||||
|
embedUrl.contains("sbfast") || embedUrl.contains("sbfull.com") || embedUrl.contains("javplaya.com") ||
|
||||||
|
embedUrl.contains("ssbstream.net") || embedUrl.contains("p1ayerjavseen.com") || embedUrl.contains("sbthe.com") ||
|
||||||
|
embedUrl.contains("vidmovie.xyz") || embedUrl.contains("sbspeed.com") || embedUrl.contains("streamsss.net") ||
|
||||||
|
embedUrl.contains("sblanh.com")
|
||||||
|
) {
|
||||||
|
val videos = StreamSBExtractor(client).videosFromUrl(url, headers, language)
|
||||||
|
videoList.addAll(videos)
|
||||||
}
|
}
|
||||||
}
|
if (embedUrl.contains("fembed") || embedUrl.contains("anime789.com") || embedUrl.contains("24hd.club") ||
|
||||||
if (url.lowercase().contains("doodstream")) {
|
embedUrl.contains("fembad.org") || embedUrl.contains("vcdn.io") || embedUrl.contains("sharinglink.club") ||
|
||||||
val video = try {
|
embedUrl.contains("moviemaniac.org") || embedUrl.contains("votrefiles.club") || embedUrl.contains("femoload.xyz") ||
|
||||||
DoodExtractor(client).videoFromUrl(url, language + "DoodStream")
|
embedUrl.contains("albavido.xyz") || embedUrl.contains("feurl.com") || embedUrl.contains("dailyplanet.pw") ||
|
||||||
} catch (e: Exception) {
|
embedUrl.contains("ncdnstm.com") || embedUrl.contains("jplayer.net") || embedUrl.contains("xstreamcdn.com") ||
|
||||||
null
|
embedUrl.contains("fembed-hd.com") || embedUrl.contains("gcloud.live") || embedUrl.contains("vcdnplay.com") ||
|
||||||
|
embedUrl.contains("superplayxyz.club") || embedUrl.contains("vidohd.com") || embedUrl.contains("vidsource.me") ||
|
||||||
|
embedUrl.contains("cinegrabber.com") || embedUrl.contains("votrefile.xyz") || embedUrl.contains("zidiplay.com") ||
|
||||||
|
embedUrl.contains("ndrama.xyz") || embedUrl.contains("fcdn.stream") || embedUrl.contains("mediashore.org") ||
|
||||||
|
embedUrl.contains("suzihaza.com") || embedUrl.contains("there.to") || embedUrl.contains("femax20.com") ||
|
||||||
|
embedUrl.contains("javstream.top") || embedUrl.contains("viplayer.cc") || embedUrl.contains("sexhd.co") ||
|
||||||
|
embedUrl.contains("fembed.net") || embedUrl.contains("mrdhan.com") || embedUrl.contains("votrefilms.xyz") ||
|
||||||
|
embedUrl.contains("embedsito.com") || embedUrl.contains("dutrag.com") || embedUrl.contains("youvideos.ru") ||
|
||||||
|
embedUrl.contains("streamm4u.club") || embedUrl.contains("moviepl.xyz") || embedUrl.contains("asianclub.tv") ||
|
||||||
|
embedUrl.contains("vidcloud.fun") || embedUrl.contains("fplayer.info") || embedUrl.contains("diasfem.com") ||
|
||||||
|
embedUrl.contains("javpoll.com") || embedUrl.contains("reeoov.tube") || embedUrl.contains("suzihaza.com") ||
|
||||||
|
embedUrl.contains("ezsubz.com") || embedUrl.contains("vidsrc.xyz") || embedUrl.contains("diampokusy.com") ||
|
||||||
|
embedUrl.contains("diampokusy.com") || embedUrl.contains("i18n.pw") || embedUrl.contains("vanfem.com") ||
|
||||||
|
embedUrl.contains("fembed9hd.com") || embedUrl.contains("votrefilms.xyz") || embedUrl.contains("watchjavnow.xyz")
|
||||||
|
) {
|
||||||
|
val videos = FembedExtractor(client).videosFromUrl(url, language)
|
||||||
|
videoList.addAll(videos)
|
||||||
}
|
}
|
||||||
if (video != null) {
|
if (url.lowercase().contains("streamtape")) {
|
||||||
videoList.add(video)
|
val video = StreamTapeExtractor(client).videoFromUrl(url, language + "Streamtape")
|
||||||
|
if (video != null) {
|
||||||
|
videoList.add(video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (url.lowercase().contains("dood")) {
|
||||||
|
val video = try {
|
||||||
|
DoodExtractor(client).videoFromUrl(url, language + "DoodStream")
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
if (video != null) {
|
||||||
|
videoList.add(video)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (url.lowercase().contains("okru")) {
|
||||||
|
val videos = OkruExtractor(client).videosFromUrl(url, language)
|
||||||
|
videoList.addAll(videos)
|
||||||
|
}
|
||||||
|
if (url.lowercase().contains("www.solidfiles.com")) {
|
||||||
|
val videos = SolidFilesExtractor(client).videosFromUrl(url, language)
|
||||||
|
videoList.addAll(videos)
|
||||||
|
}
|
||||||
|
if (url.lowercase().contains("od.lk")) {
|
||||||
|
videoList.add(Video(url, language + "Od.lk", url))
|
||||||
|
}
|
||||||
|
if (url.lowercase().contains("cldup.com")) {
|
||||||
|
videoList.add(Video(url, language + "CldUp", url))
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (url.lowercase().contains("okru")) {
|
|
||||||
val videos = OkruExtractor(client).videosFromUrl(url, language)
|
|
||||||
videoList.addAll(videos)
|
|
||||||
}
|
|
||||||
if (url.lowercase().contains("www.solidfiles.com")) {
|
|
||||||
val videos = SolidFilesExtractor(client).videosFromUrl(url, language)
|
|
||||||
videoList.addAll(videos)
|
|
||||||
}
|
|
||||||
if (url.lowercase().contains("od.lk")) {
|
|
||||||
videoList.add(Video(url, language + "Od.lk", url))
|
|
||||||
}
|
|
||||||
if (url.lowercase().contains("cldup.com")) {
|
|
||||||
videoList.add(Video(url, language + "CldUp", url))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,7 @@ ext {
|
|||||||
extName = 'Pelisplushd'
|
extName = 'Pelisplushd'
|
||||||
pkgNameSuffix = 'es.pelisplushd'
|
pkgNameSuffix = 'es.pelisplushd'
|
||||||
extClass = '.Pelisplushd'
|
extClass = '.Pelisplushd'
|
||||||
extVersionCode = 21
|
extVersionCode = 22
|
||||||
libVersion = '13'
|
libVersion = '13'
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -14,6 +14,7 @@ dependencies {
|
|||||||
implementation(project(':lib-streamtape-extractor'))
|
implementation(project(':lib-streamtape-extractor'))
|
||||||
implementation(project(':lib-streamsb-extractor'))
|
implementation(project(':lib-streamsb-extractor'))
|
||||||
implementation(project(':lib-dood-extractor'))
|
implementation(project(':lib-dood-extractor'))
|
||||||
|
implementation(project(':lib-voe-extractor'))
|
||||||
}
|
}
|
||||||
|
|
||||||
apply from: "$rootDir/common.gradle"
|
apply from: "$rootDir/common.gradle"
|
||||||
|
@ -5,6 +5,7 @@ import android.content.SharedPreferences
|
|||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
import androidx.preference.ListPreference
|
import androidx.preference.ListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
|
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.StreamlareExtractor
|
||||||
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.YourUploadExtractor
|
import eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors.YourUploadExtractor
|
||||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||||
@ -17,13 +18,9 @@ import eu.kanade.tachiyomi.lib.doodextractor.DoodExtractor
|
|||||||
import eu.kanade.tachiyomi.lib.fembedextractor.FembedExtractor
|
import eu.kanade.tachiyomi.lib.fembedextractor.FembedExtractor
|
||||||
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
|
import eu.kanade.tachiyomi.lib.streamsbextractor.StreamSBExtractor
|
||||||
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
|
||||||
|
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.POST
|
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import kotlinx.serialization.decodeFromString
|
|
||||||
import kotlinx.serialization.json.Json
|
|
||||||
import kotlinx.serialization.json.JsonObject
|
|
||||||
import kotlinx.serialization.json.jsonObject
|
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
@ -31,8 +28,6 @@ import org.jsoup.nodes.Document
|
|||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import uy.kohesive.injekt.injectLazy
|
|
||||||
import kotlin.Exception
|
|
||||||
|
|
||||||
class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||||
|
|
||||||
@ -44,8 +39,6 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
|
|
||||||
override val supportsLatest = false
|
override val supportsLatest = false
|
||||||
|
|
||||||
private val json: Json by injectLazy()
|
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient
|
override val client: OkHttpClient = network.cloudflareClient
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
private val preferences: SharedPreferences by lazy {
|
||||||
@ -75,7 +68,7 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
val episode = SEpisode.create().apply {
|
val episode = SEpisode.create().apply {
|
||||||
val epnum = 1
|
val epnum = 1
|
||||||
episode_number = epnum.toFloat()
|
episode_number = epnum.toFloat()
|
||||||
name = "PELICULA"
|
name = "PELÍCULA"
|
||||||
}
|
}
|
||||||
episode.setUrlWithoutDomain(response.request.url.toString())
|
episode.setUrlWithoutDomain(response.request.url.toString())
|
||||||
episodes.add(episode)
|
episodes.add(episode)
|
||||||
@ -110,7 +103,7 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
encryptedList.forEach {
|
encryptedList.forEach {
|
||||||
val url = String(Base64.decode(it.attr("data-r"), Base64.DEFAULT))
|
val url = String(Base64.decode(it.attr("data-r"), Base64.DEFAULT))
|
||||||
val server = it.select("span").text()
|
val server = it.select("span").text()
|
||||||
serverVideoResolver(url, server.toString()).forEach { video -> videoList.add(video) }
|
serverVideoResolver(url, server.toString())?.forEach { video -> videoList.add(video) }
|
||||||
}
|
}
|
||||||
decryptedList.forEach {
|
decryptedList.forEach {
|
||||||
val url = it.attr("onclick")
|
val url = it.attr("onclick")
|
||||||
@ -120,9 +113,10 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
.substringBefore("?poster")
|
.substringBefore("?poster")
|
||||||
.substringBefore("#poster=")
|
.substringBefore("#poster=")
|
||||||
val server = it.select("span").text()
|
val server = it.select("span").text()
|
||||||
serverVideoResolver(url, server.toString()).forEach { video -> videoList.add(video) }
|
serverVideoResolver(url, server.toString())?.forEach { video -> videoList.add(video) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifier for old series
|
// verifier for old series
|
||||||
if (!apiUrl.contains("/video/") || alternativeServers.any()) {
|
if (!apiUrl.contains("/video/") || alternativeServers.any()) {
|
||||||
document.select("ul.TbVideoNv.nav.nav-tabs li").forEach { id ->
|
document.select("ul.TbVideoNv.nav.nav-tabs li").forEach { id ->
|
||||||
@ -138,88 +132,74 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
"upload" -> { serverUrl = "https://uqload.com/embed-$urlId.html" }
|
"upload" -> { serverUrl = "https://uqload.com/embed-$urlId.html" }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
serverVideoResolver(serverUrl, serverName.toString()).forEach { video -> videoList.add(video) }
|
serverVideoResolver(serverUrl, serverName.toString())?.forEach { video -> videoList.add(video) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return videoList
|
return videoList
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun serverVideoResolver(url: String, server: String): List<Video> {
|
private fun bytesToHex(bytes: ByteArray): String {
|
||||||
val videoList = mutableListOf<Video>()
|
val hexArray = "0123456789ABCDEF".toCharArray()
|
||||||
|
val hexChars = CharArray(bytes.size * 2)
|
||||||
when (server.lowercase()) {
|
for (j in bytes.indices) {
|
||||||
"sbfast" -> {
|
val v = bytes[j].toInt() and 0xFF
|
||||||
runCatching {
|
hexChars[j * 2] = hexArray[v ushr 4]
|
||||||
StreamSBExtractor(client).videosFromUrl(url, headers)
|
hexChars[j * 2 + 1] = hexArray[v and 0x0F]
|
||||||
}.getOrNull()?.let { videoList.addAll(it) }
|
|
||||||
}
|
|
||||||
"plusto" -> {
|
|
||||||
val videos = FembedExtractor(client).videosFromUrl(url)
|
|
||||||
videoList.addAll(videos)
|
|
||||||
}
|
|
||||||
"stp" -> {
|
|
||||||
val videos = StreamTapeExtractor(client).videoFromUrl(url, "StreamTape")
|
|
||||||
if (videos != null) {
|
|
||||||
videoList.add(videos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"uwu" -> {
|
|
||||||
try {
|
|
||||||
if (!url.contains("disable")) {
|
|
||||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
|
||||||
if (body.select("script:containsData(var shareId)").toString()
|
|
||||||
.isNotBlank()
|
|
||||||
) {
|
|
||||||
val shareId =
|
|
||||||
body.selectFirst("script:containsData(var shareId)").data()
|
|
||||||
.substringAfter("shareId = \"").substringBefore("\"")
|
|
||||||
val amazonApiJson =
|
|
||||||
client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
|
||||||
.execute().asJsoup()
|
|
||||||
val epId = amazonApiJson.toString().substringAfter("\"id\":\"")
|
|
||||||
.substringBefore("\"")
|
|
||||||
val amazonApi =
|
|
||||||
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
|
||||||
.execute().asJsoup()
|
|
||||||
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":")
|
|
||||||
.substringAfter("tempLink\":\"").substringBefore("\"")
|
|
||||||
videoList.add(Video(videoUrl, "Amazon", videoUrl))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {}
|
|
||||||
}
|
|
||||||
"voex" -> {
|
|
||||||
try {
|
|
||||||
val body = client.newCall(GET(url)).execute().asJsoup()
|
|
||||||
val data1 = body.selectFirst("script:containsData(const sources = {)").data()
|
|
||||||
val video = data1.substringAfter("hls\": \"").substringBefore("\"")
|
|
||||||
videoList.add(Video(video, "Voex", video))
|
|
||||||
} catch (e: Exception) {}
|
|
||||||
}
|
|
||||||
"streamlare" -> {
|
|
||||||
try {
|
|
||||||
val id = url.substringAfter("/e/").substringBefore("?poster")
|
|
||||||
val videoUrlResponse = client.newCall(POST("https://slwatch.co/api/video/stream/get?id=$id")).execute().asJsoup()
|
|
||||||
json.decodeFromString<JsonObject>(videoUrlResponse.select("body").text())["result"]?.jsonObject?.forEach { quality ->
|
|
||||||
val resolution = quality.toString().substringAfter("\"label\":\"").substringBefore("\"")
|
|
||||||
val videoUrl = quality.toString().substringAfter("\"file\":\"").substringBefore("\"")
|
|
||||||
videoList.add(Video(videoUrl, "Streamlare:$resolution", videoUrl))
|
|
||||||
}
|
|
||||||
} catch (e: Exception) {}
|
|
||||||
}
|
|
||||||
"doodstream" -> {
|
|
||||||
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
|
||||||
val video = DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)
|
|
||||||
if (video != null) {
|
|
||||||
videoList.add(video)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
"upload" -> {
|
|
||||||
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
|
|
||||||
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
|
|
||||||
if (videos.isNotEmpty()) videoList.addAll(videos)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return String(hexChars)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun fixUrl(url: String): String {
|
||||||
|
val sbUrl = url.substringBefore("/e/")
|
||||||
|
val id = url.substringAfter("/e/").substringBefore("?").substringBefore(".html")
|
||||||
|
val hexBytes = bytesToHex(id.toByteArray())
|
||||||
|
return "$sbUrl/sources49/316751675854774a53316b777c7c${hexBytes}7c7c744548764f5a666a315547577c7c73747265616d7362"
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun serverVideoResolver(url: String, server: String): List<Video>? {
|
||||||
|
val videoList = mutableListOf<Video>()
|
||||||
|
try {
|
||||||
|
if (server.lowercase() == "sbfast") {
|
||||||
|
val newHeaders = headers.newBuilder().set("referer", url).set("watchsb", "sbstream").set("authority", url.substringBefore("/e/")).build()
|
||||||
|
return StreamSBExtractor(client).videosFromDecryptedUrl(fixUrl(url), headers = newHeaders)
|
||||||
|
} else if (server.lowercase() == "plusto") {
|
||||||
|
return FembedExtractor(client).videosFromUrl(url)
|
||||||
|
} else if (server.lowercase() == "stp") {
|
||||||
|
StreamTapeExtractor(client).videoFromUrl(url, "StreamTape")?.let { videoList.add(it) }
|
||||||
|
} else if (server.lowercase() == "uwu") {
|
||||||
|
if (!url.contains("disable")) {
|
||||||
|
val body = client.newCall(GET(url)).execute().asJsoup()
|
||||||
|
if (body.select("script:containsData(var shareId)").toString()
|
||||||
|
.isNotBlank()
|
||||||
|
) {
|
||||||
|
val shareId =
|
||||||
|
body.selectFirst("script:containsData(var shareId)").data()
|
||||||
|
.substringAfter("shareId = \"").substringBefore("\"")
|
||||||
|
val amazonApiJson =
|
||||||
|
client.newCall(GET("https://www.amazon.com/drive/v1/shares/$shareId?resourceVersion=V2&ContentType=JSON&asset=ALL"))
|
||||||
|
.execute().asJsoup()
|
||||||
|
val epId = amazonApiJson.toString().substringAfter("\"id\":\"")
|
||||||
|
.substringBefore("\"")
|
||||||
|
val amazonApi =
|
||||||
|
client.newCall(GET("https://www.amazon.com/drive/v1/nodes/$epId/children?resourceVersion=V2&ContentType=JSON&limit=200&sort=%5B%22kind+DESC%22%2C+%22modifiedDate+DESC%22%5D&asset=ALL&tempLink=true&shareId=$shareId"))
|
||||||
|
.execute().asJsoup()
|
||||||
|
val videoUrl = amazonApi.toString().substringAfter("\"FOLDER\":")
|
||||||
|
.substringAfter("tempLink\":\"").substringBefore("\"")
|
||||||
|
videoList.add(Video(videoUrl, "Amazon", videoUrl))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (server.lowercase() == "voex") {
|
||||||
|
VoeExtractor(client).videoFromUrl(url, "Voex")?.let { videoList.add(it) }
|
||||||
|
} else if (server.lowercase() == "streamlare") {
|
||||||
|
StreamlareExtractor(client).videosFromUrl(url)?.let { videoList.add(it) }
|
||||||
|
} else if (server.lowercase() == "doodstream") {
|
||||||
|
val url2 = url.replace("https://doodstream.com/e/", "https://dood.to/e/")
|
||||||
|
DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)?.let { videoList.add(it) }
|
||||||
|
} else if (server.lowercase() == "upload") {
|
||||||
|
val headers = headers.newBuilder().add("referer", "https://www.yourupload.com/").build()
|
||||||
|
return YourUploadExtractor(client).videoFromUrl(url, headers = headers)
|
||||||
|
}
|
||||||
|
} catch (_: Exception) {}
|
||||||
return videoList
|
return videoList
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,11 +233,13 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
|
||||||
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
val filterList = if (filters.isEmpty()) getFilterList() else filters
|
||||||
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
|
||||||
|
val tagFilter = filters.find { it is Tags } as Tags
|
||||||
|
|
||||||
return when {
|
return when {
|
||||||
query.isNotBlank() -> GET("$baseUrl/search?s=$query&page=$page", headers)
|
query.isNotBlank() -> GET("$baseUrl/search?s=$query&page=$page", headers)
|
||||||
genreFilter.state != 0 -> GET("$baseUrl/${genreFilter.toUriPart()}?page=$page")
|
genreFilter.state != 0 -> GET("$baseUrl/${genreFilter.toUriPart()}?page=$page")
|
||||||
else -> GET("$baseUrl/peliculas?page=$page ")
|
tagFilter.state.isNotBlank() -> GET("$baseUrl/year/${tagFilter.state}?page=$page")
|
||||||
|
else -> GET("$baseUrl/peliculas?page=$page")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
override fun searchAnimeFromElement(element: Element): SAnime {
|
override fun searchAnimeFromElement(element: Element): SAnime {
|
||||||
@ -288,8 +270,10 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
override fun latestUpdatesSelector() = throw Exception("not used")
|
override fun latestUpdatesSelector() = throw Exception("not used")
|
||||||
|
|
||||||
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
|
||||||
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
|
AnimeFilter.Header("La busqueda por texto ignora el filtro de año"),
|
||||||
GenreFilter()
|
GenreFilter(),
|
||||||
|
AnimeFilter.Header("Busqueda por año"),
|
||||||
|
Tags("Año")
|
||||||
)
|
)
|
||||||
|
|
||||||
private class GenreFilter : UriPartFilter(
|
private class GenreFilter : UriPartFilter(
|
||||||
@ -321,6 +305,8 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
private class Tags(name: String) : AnimeFilter.Text(name)
|
||||||
|
|
||||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||||
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||||
fun toUriPart() = vals[state].second
|
fun toUriPart() = vals[state].second
|
||||||
|
@ -0,0 +1,56 @@
|
|||||||
|
package eu.kanade.tachiyomi.animeextension.es.pelisplushd.extractors
|
||||||
|
|
||||||
|
import eu.kanade.tachiyomi.animesource.model.Video
|
||||||
|
import eu.kanade.tachiyomi.network.POST
|
||||||
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
|
import kotlinx.serialization.decodeFromString
|
||||||
|
import kotlinx.serialization.json.Json
|
||||||
|
import kotlinx.serialization.json.JsonObject
|
||||||
|
import kotlinx.serialization.json.jsonObject
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import uy.kohesive.injekt.injectLazy
|
||||||
|
|
||||||
|
class StreamlareExtractor(private val client: OkHttpClient) {
|
||||||
|
private val json: Json by injectLazy()
|
||||||
|
fun videosFromUrl(url: String): Video? {
|
||||||
|
val id = url.substringAfter("/e/").substringBefore("?poster")
|
||||||
|
val videoUrlResponse =
|
||||||
|
client.newCall(POST("https://slwatch.co/api/video/stream/get?id=$id")).execute()
|
||||||
|
.asJsoup()
|
||||||
|
json.decodeFromString<JsonObject>(
|
||||||
|
videoUrlResponse.select("body").text()
|
||||||
|
)["result"]?.jsonObject?.forEach { quality ->
|
||||||
|
if (quality.toString().contains("file=\"")) {
|
||||||
|
val videoUrl = quality.toString().substringAfter("file=\"").substringBefore("\"").trim()
|
||||||
|
val type = if (videoUrl.contains(".m3u8")) "HSL" else "MP4"
|
||||||
|
val headers = Headers.Builder()
|
||||||
|
.add("authority", videoUrl.substringBefore("/hls").substringBefore("/mp4"))
|
||||||
|
.add("origin", "https://slwatch.co")
|
||||||
|
.add("referer", "https://slwatch.co/e/" + url.substringAfter("/e/"))
|
||||||
|
.add(
|
||||||
|
"sec-ch-ua",
|
||||||
|
"\"Not?A_Brand\";v=\"8\", \"Chromium\";v=\"108\", \"Google Chrome\";v=\"108\""
|
||||||
|
)
|
||||||
|
.add("sec-ch-ua-mobile", "?0")
|
||||||
|
.add("sec-ch-ua-platform", "\"Windows\"")
|
||||||
|
.add("sec-fetch-dest", "empty")
|
||||||
|
.add("sec-fetch-mode", "cors")
|
||||||
|
.add("sec-fetch-site", "cross-site")
|
||||||
|
.add(
|
||||||
|
"user-agent",
|
||||||
|
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/),108.0.0.0 Safari/537.36"
|
||||||
|
)
|
||||||
|
.add("Accept-Encoding", "gzip, deflate, br")
|
||||||
|
.add("accept", "*/*")
|
||||||
|
.add(
|
||||||
|
"accept-language",
|
||||||
|
"es-MX,es-419;q=0.9,es;q=0.8,en;q=0.7,zh-TW;q=0.6,zh-CN;q=0.5,zh;q=0.4"
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
return Video(videoUrl, "Streamlare:$type", videoUrl, headers = headers)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user