feat(hi/animesaga): New extension (#1892)

This commit is contained in:
Secozzi
2023-07-12 10:33:28 +02:00
committed by GitHub
parent 33a00d63e3
commit 2a8ca3c52e
11 changed files with 562 additions and 24 deletions

View File

@ -680,13 +680,12 @@ Public License instead of this License. But first, please read
package eu.kanade.tachiyomi.lib.chillxextractor
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Track
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.Serializable
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
@ -698,7 +697,7 @@ import javax.crypto.spec.SecretKeySpec
class ChillxExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videoFromUrl(url: String, referer: String): List<Video>? {
fun videoFromUrl(url: String, referer: String, prefix: String = "Chillx - "): List<Video> {
val videoList = mutableListOf<Video>()
val mainUrl = "https://${url.toHttpUrl().host}"
@ -707,16 +706,12 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
).execute().asJsoup().html()
val master = Regex("""MasterJS\s*=\s*'([^']+)""").find(document)?.groupValues?.get(1)
val aesJson = Json.decodeFromString<CryptoInfo>(base64Decode(master ?: return null).toString(Charsets.UTF_8))
val aesJson = Json.decodeFromString<CryptoInfo>(base64Decode(master ?: return emptyList()).toString(Charsets.UTF_8))
val decrypt = cryptoAESHandler(aesJson, KEY)
val decrypt = cryptoAESHandler(aesJson ?: return null, KEY)
val playlistUrl = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1) ?: return null
val tracks = Regex("""tracks:\s*\[(.+)]""").find(decrypt)?.groupValues?.get(1)
// TODO: Add subtitle support when a site is found that uses it
val trackJson = Json.decodeFromString<SubtitleTrack>(tracks ?: return null)
val masterUrl = Regex("""sources:\s*\[\{"file":"([^"]+)""").find(decrypt)?.groupValues?.get(1)
?: Regex("""file: ?"([^"]+)"""").find(decrypt)?.groupValues?.get(1)
?: return emptyList()
val masterHeaders = Headers.headersOf(
"Accept", "*/*",
@ -728,23 +723,57 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
"Referer", "$mainUrl/",
)
val response = client.newCall(GET(playlistUrl, headers = masterHeaders)).execute()
val response = client.newCall(GET(masterUrl, headers = masterHeaders)).execute()
val masterPlaylist = response.body.string()
val masterBase = "https://${masterUrl.toHttpUrl().host}${masterUrl.toHttpUrl().encodedPath}"
.substringBeforeLast("/") + "/"
val audioRegex = Regex("""#EXT-X-MEDIA:TYPE=AUDIO.*?NAME="(.*?)".*?URI="(.*?)"""")
val audioList: List<Track> = audioRegex.findAll(masterPlaylist)
.map {
var audioUrl = it.groupValues[2]
if (audioUrl.startsWith("https").not()) {
audioUrl = masterBase + audioUrl
}
Track(
audioUrl, // Url
it.groupValues[1], // Name
)
}.toList()
val subtitleList = mutableListOf<Track>()
if (decrypt.contains("subtitle: ")) {
val subtitleStr = decrypt.substringAfter("subtitle: ").substringBefore("\n")
val subtitleRegex = Regex("""\[(.*?)\](.*?)"?\,""")
subtitleRegex.findAll(subtitleStr).forEach {
subtitleList.add(
Track(
it.groupValues[2],
it.groupValues[1],
)
)
}
}
masterPlaylist.substringAfter("#EXT-X-STREAM-INF:")
.split("#EXT-X-STREAM-INF:").map {
.split("#EXT-X-STREAM-INF:").map {
val quality = it.substringAfter("RESOLUTION=").split(",")[0].split("\n")[0].substringAfter("x") + "p"
var videoUrl = it.substringAfter("\n").substringBefore("\n")
if (videoUrl.startsWith("https").not()) {
val plUrl = playlistUrl.toHttpUrl()
videoUrl = "https://${plUrl.host}${plUrl.encodedPath.substringBeforeLast("/")}/$videoUrl"
videoUrl = masterBase + videoUrl
}
val videoHeaders = headers.newBuilder()
.addAll(masterHeaders)
.build()
videoList.add(Video(videoUrl, quality, videoUrl, headers = videoHeaders))
if (audioList.isEmpty()) {
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders, subtitleTracks = subtitleList))
} else {
videoList.add(Video(videoUrl, prefix + quality, videoUrl, headers = videoHeaders, audioTracks = audioList, subtitleTracks = subtitleList))
}
}
return videoList
}
@ -790,13 +819,6 @@ class ChillxExtractor(private val client: OkHttpClient, private val headers: Hea
.toByteArray()
}
@Serializable
data class SubtitleTrack(
val file: String? = null,
val label: String? = null,
val kind: String? = null,
)
companion object {
private const val KEY = "11x&W5UBrcqn\$9Yl"
}