Fixes and Updates (#1090)

This commit is contained in:
miguelantonioe 2022-12-20 01:07:23 -06:00 committed by GitHub
parent f0442520cb
commit a7c1fe3017
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 322 additions and 155 deletions

View File

@ -13,8 +13,7 @@ class FembedExtractor(private val client: OkHttpClient) {
client.newCall(POST(videoApi)).execute().body?.string().orEmpty()
}.getOrNull() ?: return emptyList<Video>()
val jsonResponse = Json { ignoreUnknownKeys = true }
.decodeFromString<FembedResponse>(body)
val jsonResponse = try{ Json { ignoreUnknownKeys = true }.decodeFromString<FembedResponse>(body) } catch (e: Exception) { FembedResponse(false, emptyList()) }
return if (jsonResponse.success) {
jsonResponse.data.map {

View File

@ -1,5 +1,6 @@
package eu.kanade.tachiyomi.lib.streamsbextractor
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import kotlinx.serialization.decodeFromString
@ -73,4 +74,30 @@ class StreamSBExtractor(private val client: OkHttpClient) {
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()
}
}
}

View File

@ -6,15 +6,13 @@ import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
class VoeExtractor(private val client: OkHttpClient) {
fun videoFromUrl(url: String, quality: String? = null): Video? {
val document = client.newCall(GET(url)).execute().asJsoup()
val script = document.selectFirst("script:containsData(const sources)")
?.data()
?: return null
val videoUrl = script.substringAfter("hls': '").substringBefore("'")
val resolution = script.substringAfter("video_height': ")
.substringBefore(",")
val resolution = script.substringAfter("video_height': ").substringBefore(",")
val qualityStr = quality ?: "VoeCDN(${resolution}p)"
return Video(url, qualityStr, videoUrl)
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeFLV'
pkgNameSuffix = 'es.animeflv'
extClass = '.AnimeFlv'
extVersionCode = 31
extVersionCode = 32
libVersion = '13'
}

View File

@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.animeextension.es.animeflv
import android.app.Application
import android.content.SharedPreferences
import android.util.Log
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
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.api.get
import uy.kohesive.injekt.injectLazy
import java.lang.Exception
import kotlin.Exception
class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -116,31 +117,43 @@ class AnimeFlv : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val quality = json!!["title"]!!.jsonPrimitive!!.content
var url = json!!["code"]!!.jsonPrimitive!!.content
if (quality == "SB") {
try {
videoList.addAll(
StreamSBExtractor(client).videosFromUrl(url, headers)
)
} catch (_: Exception) {}
}
if (quality == "Fembed") {
try {
videoList.addAll(
FembedExtractor(client).videosFromUrl(url)
)
} catch (_: Exception) {}
}
if (quality == "Stape") {
try {
val url1 = json!!["url"]!!.jsonPrimitive!!.content
val video = StreamTapeExtractor(client).videoFromUrl(url1)
if (video != null) videoList.add(video)
} catch (_: Exception) {}
}
if (quality == "Doodstream") {
try {
val video = DoodExtractor(client).videoFromUrl(url, "DoodStream", false)
if (video != null) videoList.add(video)
} catch (_: Exception) {}
}
if (quality == "Okru") {
try {
val videos = OkruExtractor(client).videosFromUrl(url)
videoList.addAll(videos)
} catch (_: Exception) {}
}
if (quality == "YourUpload") {
try {
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 {
val filterList = if (filters.isEmpty()) getFilterList() else filters
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 {
query.isNotBlank() -> GET("$baseUrl/browse?q=$query&order=rating&page=$page")
genreFilter.state != 0 -> GET("$baseUrl/browse?genre[]=${genreFilter.toUriPart()}&order=rating&page=$page")
query.isNotBlank() || genreFilter.state != 0 || stateFilter.state != 0 || orderByFilter.state != 0 || typeFilter.state != 0 -> GET(uri)
else -> GET("$baseUrl/browse?page=$page&order=rating")
}
}
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
GenreFilter()
GenreFilter(),
StateFilter(),
TypeFilter(),
OrderByFilter()
)
private class GenreFilter : UriPartFilter(
"Géneros",
arrayOf(
Pair("<Selecionar>", "all"),
Pair("Todo", "all"),
Pair("Acción", "accion"),
Pair("Artes Marciales", "artes_marciales"),
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>>) :
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second

View File

@ -5,7 +5,7 @@ ext {
extName = 'AnimeLatinoHD'
pkgNameSuffix = 'es.animelatinohd'
extClass = '.AnimeLatinoHD'
extVersionCode = 9
extVersionCode = 10
libVersion = '13'
}

View File

@ -143,6 +143,12 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
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> {
val document = response.asJsoup()
val videoList = mutableListOf<Video>()
@ -158,13 +164,49 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val servers = player!!.jsonArray
servers.forEach { server ->
val item = server!!.jsonObject
val url = item["code"]!!.jsonPrimitive!!.content
val request = client.newCall(
GET(
url = "https://api.animelatinohd.com/stream/${item["id"]!!.jsonPrimitive.content}",
headers = headers.newBuilder().add("Referer", "https://www.animelatinohd.com/").build()
)
).execute()
val locationsDdh = request!!.networkResponse.toString()
fetchUrls(locationsDdh).map { url ->
val language = if (item["languaje"]!!.jsonPrimitive!!.content == "1") "[Lat] " else "[Sub] "
if (url.lowercase().contains("streamsb")) {
val embedUrl = url.lowercase()
if (embedUrl.contains("sbembed.com") || embedUrl.contains("sbembed1.com") || embedUrl.contains("sbplay.org") ||
embedUrl.contains("sbvideo.net") || embedUrl.contains("streamsb.net") || embedUrl.contains("sbplay.one") ||
embedUrl.contains("cloudemb.com") || embedUrl.contains("playersb.com") || embedUrl.contains("tubesb.com") ||
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 (url.lowercase().contains("www.fembed.com")) {
if (embedUrl.contains("fembed") || embedUrl.contains("anime789.com") || embedUrl.contains("24hd.club") ||
embedUrl.contains("fembad.org") || embedUrl.contains("vcdn.io") || embedUrl.contains("sharinglink.club") ||
embedUrl.contains("moviemaniac.org") || embedUrl.contains("votrefiles.club") || embedUrl.contains("femoload.xyz") ||
embedUrl.contains("albavido.xyz") || embedUrl.contains("feurl.com") || embedUrl.contains("dailyplanet.pw") ||
embedUrl.contains("ncdnstm.com") || embedUrl.contains("jplayer.net") || embedUrl.contains("xstreamcdn.com") ||
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)
}
@ -174,7 +216,7 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
videoList.add(video)
}
}
if (url.lowercase().contains("doodstream")) {
if (url.lowercase().contains("dood")) {
val video = try {
DoodExtractor(client).videoFromUrl(url, language + "DoodStream")
} catch (e: Exception) {
@ -202,6 +244,7 @@ class AnimeLatinoHD : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
}
}
}
return videoList
}

View File

@ -5,7 +5,7 @@ ext {
extName = 'Pelisplushd'
pkgNameSuffix = 'es.pelisplushd'
extClass = '.Pelisplushd'
extVersionCode = 21
extVersionCode = 22
libVersion = '13'
}
@ -14,6 +14,7 @@ dependencies {
implementation(project(':lib-streamtape-extractor'))
implementation(project(':lib-streamsb-extractor'))
implementation(project(':lib-dood-extractor'))
implementation(project(':lib-voe-extractor'))
}
apply from: "$rootDir/common.gradle"

View File

@ -5,6 +5,7 @@ import android.content.SharedPreferences
import android.util.Base64
import androidx.preference.ListPreference
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.animesource.ConfigurableAnimeSource
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.streamsbextractor.StreamSBExtractor
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.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.OkHttpClient
import okhttp3.Request
import okhttp3.Response
@ -31,8 +28,6 @@ import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import kotlin.Exception
class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
@ -44,8 +39,6 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override val supportsLatest = false
private val json: Json by injectLazy()
override val client: OkHttpClient = network.cloudflareClient
private val preferences: SharedPreferences by lazy {
@ -75,7 +68,7 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
val episode = SEpisode.create().apply {
val epnum = 1
episode_number = epnum.toFloat()
name = "PELICULA"
name = "PELÍCULA"
}
episode.setUrlWithoutDomain(response.request.url.toString())
episodes.add(episode)
@ -110,7 +103,7 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
encryptedList.forEach {
val url = String(Base64.decode(it.attr("data-r"), Base64.DEFAULT))
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 {
val url = it.attr("onclick")
@ -120,9 +113,10 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
.substringBefore("?poster")
.substringBefore("#poster=")
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
if (!apiUrl.contains("/video/") || alternativeServers.any()) {
document.select("ul.TbVideoNv.nav.nav-tabs li").forEach { id ->
@ -138,33 +132,41 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
"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
}
private fun serverVideoResolver(url: String, server: String): List<Video> {
val videoList = mutableListOf<Video>()
private fun bytesToHex(bytes: ByteArray): String {
val hexArray = "0123456789ABCDEF".toCharArray()
val hexChars = CharArray(bytes.size * 2)
for (j in bytes.indices) {
val v = bytes[j].toInt() and 0xFF
hexChars[j * 2] = hexArray[v ushr 4]
hexChars[j * 2 + 1] = hexArray[v and 0x0F]
}
return String(hexChars)
}
when (server.lowercase()) {
"sbfast" -> {
runCatching {
StreamSBExtractor(client).videosFromUrl(url, headers)
}.getOrNull()?.let { videoList.addAll(it) }
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"
}
"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" -> {
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()
@ -186,40 +188,18 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
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" -> {
} 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/")
val video = DoodExtractor(client).videoFromUrl(url2, "DoodStream", false)
if (video != null) {
videoList.add(video)
}
}
"upload" -> {
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()
val videos = YourUploadExtractor(client).videoFromUrl(url, headers = headers)
if (videos.isNotEmpty()) videoList.addAll(videos)
}
return YourUploadExtractor(client).videoFromUrl(url, headers = headers)
}
} catch (_: Exception) {}
return videoList
}
@ -253,11 +233,13 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
val filterList = if (filters.isEmpty()) getFilterList() else filters
val genreFilter = filterList.find { it is GenreFilter } as GenreFilter
val tagFilter = filters.find { it is Tags } as Tags
return when {
query.isNotBlank() -> GET("$baseUrl/search?s=$query&page=$page", headers)
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 {
@ -288,8 +270,10 @@ class Pelisplushd : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
override fun latestUpdatesSelector() = throw Exception("not used")
override fun getFilterList(): AnimeFilterList = AnimeFilterList(
AnimeFilter.Header("La busqueda por texto ignora el filtro"),
GenreFilter()
AnimeFilter.Header("La busqueda por texto ignora el filtro de año"),
GenreFilter(),
AnimeFilter.Header("Busqueda por año"),
Tags("Año")
)
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>>) :
AnimeFilter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
fun toUriPart() = vals[state].second

View File

@ -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
}
}