Skip to content

Commit

Permalink
fix(src/es): Fix video extraction and fix json parsing (#3140)
Browse files Browse the repository at this point in the history
  • Loading branch information
imper1aldev authored Apr 16, 2024
1 parent 0c552ed commit 36b7d06
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 144 deletions.
2 changes: 1 addition & 1 deletion src/es/doramasflix/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'Doramasflix'
extClass = '.Doramasflix'
extVersionCode = 18
extVersionCode = 19
}

apply from: "$rootDir/common.gradle"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package eu.kanade.tachiyomi.animeextension.es.doramasflix

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.JsonObject

// -----------------------Season models------------------------//
@Serializable
Expand All @@ -27,7 +26,6 @@ data class ListSeason(
@SerialName("serie_name")
val serieName: String?,
val poster: String?,
val backdrop: String?,
@SerialName("__typename")
val typename: String,
)
Expand All @@ -53,50 +51,17 @@ data class ListEpisode(
val serieName: String?,
@SerialName("serie_name_es")
val serieNameEs: String?,
@SerialName("serie_id")
val serieId: String?,
@SerialName("still_path")
val stillPath: String?,
@SerialName("air_date")
val airDate: String?,
@SerialName("season_number")
val seasonNumber: Long?,
@SerialName("episode_number")
val episodeNumber: Long?,
// val languages: List<Any?>,
val poster: String?,
val backdrop: String?,
@SerialName("__typename")
val typename: String,
)

// -----------------------Details Model------------------------//

data class DetailsModel(
val props: Props,
val page: String,
val query: Query,
val buildId: String,
val isFallback: Boolean,
val gip: Boolean,
)

data class Props(
val pageProps: PageProps,
)

data class PageProps(
val deviceType: String,
val slug: String,
// val apolloClient: Any?,
val apolloState: HashMap<String, HashMap<String, JsonObject>>,
val ssrComplete: Boolean,
)

data class Query(
val slug: String,
)

// -----------------------Pagination Model------------------------//

@Serializable
Expand Down Expand Up @@ -136,67 +101,16 @@ data class Item(
@SerialName("name_es")
val nameEs: String?,
val slug: String,
val cast: List<Cast> = emptyList(),
val names: String?,
val overview: String?,
val languages: List<String> = emptyList(),
@SerialName("created_by")
val createdBy: List<CreatedBy> = emptyList(),
val popularity: Double?,
@SerialName("poster_path")
val posterPath: String?,
@SerialName("backdrop_path")
val backdropPath: String?,
@SerialName("first_air_date")
val firstAirDate: String?,
@SerialName("isTVShow")
val isTvshow: Boolean?,
val poster: String?,
val backdrop: String?,
val genres: List<Genre> = emptyList(),
val networks: List<Network> = emptyList(),
@SerialName("__typename")
val typename: String,
)

@Serializable
data class Cast(
val adult: Boolean?,
val gender: Long?,
val id: Long?,
@SerialName("known_for_department")
val knownForDepartment: String?,
val name: String?,
@SerialName("original_name")
val originalName: String?,
val popularity: Double?,
@SerialName("profile_path")
val profilePath: String?,
val character: String?,
@SerialName("credit_id")
val creditId: String?,
val order: Long?,
)

@Serializable
data class CreatedBy(
val adult: Boolean?,
val gender: Long?,
val id: Long?,
@SerialName("known_for_department")
val knownForDepartment: String?,
val name: String?,
@SerialName("original_name")
val originalName: String?,
val popularity: Double?,
@SerialName("profile_path")
val profilePath: String?,
@SerialName("credit_id")
val creditId: String?,
val department: String?,
val job: String?,
)

@Serializable
data class Genre(
val name: String?,
Expand All @@ -205,14 +119,6 @@ data class Genre(
val typename: String?,
)

@Serializable
data class Network(
val name: String?,
val slug: String?,
@SerialName("__typename")
val typename: String?,
)

// -----------------------Search Model------------------------//
@Serializable
data class SearchModel(
Expand Down Expand Up @@ -241,18 +147,6 @@ data class SearchDorama(
)

// -------------------------------------------------------
@Serializable
data class VideoModel(
val json: JsonVideo = JsonVideo(),
)

@Serializable
data class JsonVideo(
val lang: String? = "",
val page: String? = "",
val link: String? = "",
val server: String? = "",
)

@Serializable
data class VideoToken(
Expand All @@ -274,7 +168,6 @@ data class TokenModel(
val isFallback: Boolean? = false,
val isExperimentalCompile: Boolean? = false,
val gssp: Boolean? = false,
// val scriptLoader: List<Any?>,
)

@Serializable
Expand Down
6 changes: 5 additions & 1 deletion src/es/jkanime/build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
ext {
extName = 'Jkanime'
extClass = '.Jkanime'
extVersionCode = 19
extVersionCode = 20
}

apply from: "$rootDir/common.gradle"
Expand All @@ -10,4 +10,8 @@ dependencies {
implementation(project(':lib:okru-extractor'))
implementation(project(':lib:mixdrop-extractor'))
implementation(project(':lib:streamwish-extractor'))
implementation(project(':lib:mp4upload-extractor'))
implementation(project(':lib:filemoon-extractor'))
implementation(project(':lib:streamtape-extractor'))
implementation(project(':lib:voe-extractor'))
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package eu.kanade.tachiyomi.animeextension.es.jkanime

import android.app.Application
import android.content.SharedPreferences
import android.util.Base64
import androidx.preference.ListPreference
import androidx.preference.PreferenceScreen
import eu.kanade.tachiyomi.animeextension.es.jkanime.extractors.JkanimeExtractor
Expand All @@ -13,11 +14,18 @@ import eu.kanade.tachiyomi.animesource.model.SAnime
import eu.kanade.tachiyomi.animesource.model.SEpisode
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.ParsedAnimeHttpSource
import eu.kanade.tachiyomi.lib.filemoonextractor.FilemoonExtractor
import eu.kanade.tachiyomi.lib.mixdropextractor.MixDropExtractor
import eu.kanade.tachiyomi.lib.mp4uploadextractor.Mp4uploadExtractor
import eu.kanade.tachiyomi.lib.okruextractor.OkruExtractor
import eu.kanade.tachiyomi.lib.streamtapeextractor.StreamTapeExtractor
import eu.kanade.tachiyomi.lib.streamwishextractor.StreamWishExtractor
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import eu.kanade.tachiyomi.util.parallelCatchingFlatMapBlocking
import eu.kanade.tachiyomi.util.parseAs
import kotlinx.serialization.Serializable
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
Expand Down Expand Up @@ -49,13 +57,15 @@ class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
private val QUALITY_LIST = arrayOf("1080", "720", "480", "360")

private const val PREF_SERVER_KEY = "preferred_server"
private const val PREF_SERVER_DEFAULT = "Nozomi"
private const val PREF_SERVER_DEFAULT = "Voe"
private val SERVER_LIST = arrayOf(
"Okru",
"Mixdrop",
"StreamWish",
"Xtreme S",
"HentaiJk",
"Filemoon",
"Mp4Upload",
"StreamTape",
"Desuka",
"Nozomi",
"Desu",
)
Expand Down Expand Up @@ -114,33 +124,74 @@ class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {

override fun episodeFromElement(element: Element) = throw UnsupportedOperationException()

override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
val videos = mutableListOf<Video>()
document.select("div.col-lg-12.rounded.bg-servers.text-white.p-3.mt-2 a").forEach { it ->
private val languages = arrayOf(
Pair("1", "[JAP]"),
Pair("3", "[LAT]"),
Pair("4", "[CHIN]"),
)

private fun String.getLang(): String {
return languages.firstOrNull { it.first == this }?.second ?: ""
}

private fun getVideoLinks(document: Document): List<Pair<String, String>> {
val servers = mutableListOf<Pair<String, String>>()
val scriptServers = document.selectFirst("script:containsData(var video = [];)")?.data() ?: return emptyList()

val jsServer = scriptServers.substringAfter("var remote = '").substringBefore("'")
val jsPath = scriptServers.substringAfter("= remote+'").substringBefore("'")
if (jsServer.isNotEmpty() && jsPath.isNotEmpty()) {
val jsLinks = client.newCall(GET(jsServer + jsPath)).execute().body.string()
.substringAfter("var servers = ").parseAs<Array<JsLinks>>().map {
Pair(String(Base64.decode(it.remote, Base64.DEFAULT)), "${it.lang}".getLang())
}
servers.addAll(jsLinks)
}

val htmlLinks = document.select("div.col-lg-12.rounded.bg-servers.text-white.p-3.mt-2 a").map {
val serverId = it.attr("data-id")
val langClass = it.attr("class")
val lang = if (langClass.contains("lg_3")) "[LAT]" else if (langClass.contains("lg_1")) "[JAP]" else ""
val scriptServers = document.selectFirst("script:containsData(var video = [];)")!!
val url = scriptServers.data().substringAfter("video[$serverId] = '<iframe class=\"player_conte\" src=\"")
val lang = it.attr("class").substringAfter("lg_").substringBefore(" ").getLang()
val url = scriptServers
.substringAfter("video[$serverId] = '<iframe class=\"player_conte\" src=\"")
.substringBefore("\"")
.replace("/jkokru.php?u=", "http://ok.ru/videoembed/")
.replace("/jkvmixdrop.php?u=", "https://mixdrop.ag/e/")
.replace("/jksw.php?u=", "https://sfastwish.com/e/")
.replace("/jk.php?u=", "$baseUrl/")
Pair(if (url.contains("um2.php") || url.contains("um.php")) baseUrl + url else url, lang)
}
servers.addAll(htmlLinks)
return servers
}

try {
when {
"ok" in url -> OkruExtractor(client).videosFromUrl(url, "$lang ").forEach { videos.add(it) }
"mixdrop" in url -> MixDropExtractor(client).videosFromUrl(url, prefix = "$lang ").forEach { videos.add(it) }
"sfastwish" in url -> StreamWishExtractor(client, headers).videosFromUrl(url, prefix = "$lang StreamWish").forEach { videos.add(it) }
"stream/jkmedia" in url -> videos.add(Video(url, "$lang Xtreme S", url))
"um2.php" in url -> JkanimeExtractor(client).getNozomiFromUrl(baseUrl + url, "$lang ").let { if (it != null) videos.add(it) }
"um.php" in url -> JkanimeExtractor(client).getDesuFromUrl(baseUrl + url, "$lang ").let { if (it != null) videos.add(it) }
}
} catch (_: Exception) {}
/*--------------------------------Video extractors------------------------------------*/
private val okruExtractor by lazy { OkruExtractor(client) }
private val voeExtractor by lazy { VoeExtractor(client) }
private val filemoonExtractor by lazy { FilemoonExtractor(client) }
private val streamTapeExtractor by lazy { StreamTapeExtractor(client) }
private val mp4uploadExtractor by lazy { Mp4uploadExtractor(client) }
private val mixDropExtractor by lazy { MixDropExtractor(client) }
private val streamWishExtractor by lazy { StreamWishExtractor(client, headers) }
private val jkanimeExtractor by lazy { JkanimeExtractor(client) }

override fun videoListParse(response: Response): List<Video> {
val document = response.asJsoup()
return getVideoLinks(document).parallelCatchingFlatMapBlocking { (url, lang) ->
when {
"ok" in url -> okruExtractor.videosFromUrl(url, "$lang ")
"voe" in url -> voeExtractor.videosFromUrl(url, "$lang ")
"filemoon" in url || "moonplayer" in url -> filemoonExtractor.videosFromUrl(url, "$lang Filemoon:")
"streamtape" in url || "stp" in url || "stape" in url -> listOf(streamTapeExtractor.videoFromUrl(url, quality = "$lang StreamTape")!!)
"mp4upload" in url -> mp4uploadExtractor.videosFromUrl(url, prefix = "$lang ", headers = headers)
"mixdrop" in url || "mdbekjwqa" in url -> mixDropExtractor.videosFromUrl(url, prefix = "$lang ")
"sfastwish" in url || "wishembed" in url || "streamwish" in url || "strwish" in url || "wish" in url
-> streamWishExtractor.videosFromUrl(url, videoNameGen = { "$lang StreamWish:$it" })
"stream/jkmedia" in url -> jkanimeExtractor.getDesukaFromUrl(url, "$lang ")
"um2.php" in url -> jkanimeExtractor.getNozomiFromUrl(url, "$lang ")
"um.php" in url -> jkanimeExtractor.getDesuFromUrl(url, "$lang ")
else -> emptyList()
}
}
return videos
}

override fun videoListSelector() = throw UnsupportedOperationException()
Expand Down Expand Up @@ -462,4 +513,12 @@ class Jkanime : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
}
}.also(screen::addPreference)
}

@Serializable
data class JsLinks(
val remote: String? = null,
val server: String? = null,
val lang: Long? = null,
val slug: String? = null,
)
}
Loading

0 comments on commit 36b7d06

Please sign in to comment.