Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(src/es): Fix video extraction and fix json parsing #3140

Merged
merged 8 commits into from
Apr 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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