Fix Toonitalia + extractors (#1331)
* Update extractors * Add more streamsb links * StreamSB fix
This commit is contained in:
parent
6a191b0638
commit
5dc5646302
@ -8,6 +8,7 @@ import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class StreamSBExtractor(private val client: OkHttpClient) {
|
||||
@ -26,11 +27,13 @@ class StreamSBExtractor(private val client: OkHttpClient) {
|
||||
|
||||
// animension, asianload and dramacool uses "common = false"
|
||||
private fun fixUrl(url: String, common: Boolean): String {
|
||||
val sbUrl = url.substringBefore("/e/").substringBefore("/embed-")
|
||||
val id = url.substringAfter("/e/")
|
||||
val sbUrl = "https://${url.toHttpUrl().host}"
|
||||
val id = url.substringAfter("${url.toHttpUrl().host}")
|
||||
.substringAfter("/e/")
|
||||
.substringAfter("/embed-")
|
||||
.substringBefore("?")
|
||||
.substringBefore(".html")
|
||||
.substringAfter("/")
|
||||
return if (common) {
|
||||
val hexBytes = bytesToHex(id.toByteArray())
|
||||
"$sbUrl/sources51/625a364258615242766475327c7c${hexBytes}7c7c4761574550654f7461566d347c7c73747265616d7362"
|
||||
|
@ -8,7 +8,7 @@ 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)")
|
||||
val script = document.selectFirst("script:containsData(const sources),script:containsData(var sources)")
|
||||
?.data()
|
||||
?: return null
|
||||
val videoUrl = script.substringAfter("hls': '").substringBefore("'")
|
||||
|
@ -5,12 +5,13 @@ ext {
|
||||
extName = 'Toonitalia'
|
||||
pkgNameSuffix = 'it.toonitalia'
|
||||
extClass = '.Toonitalia'
|
||||
extVersionCode = 2
|
||||
extVersionCode = 3
|
||||
libVersion = '13'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(project(':lib-voe-extractor'))
|
||||
implementation(project(':lib-streamsb-extractor'))
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
@ -4,7 +4,6 @@ import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.animeextension.it.toonitalia.extractors.StreamSBExtractor
|
||||
import eu.kanade.tachiyomi.animeextension.it.toonitalia.extractors.StreamZExtractor
|
||||
import eu.kanade.tachiyomi.animesource.ConfigurableAnimeSource
|
||||
import eu.kanade.tachiyomi.animesource.model.AnimeFilter
|
||||
@ -14,6 +13,7 @@ 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.streamsbextractor.StreamSBExtractor
|
||||
import eu.kanade.tachiyomi.lib.voeextractor.VoeExtractor
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
@ -345,7 +345,8 @@ class Toonitalia : ConfigurableAnimeSource, ParsedAnimeHttpSource() {
|
||||
url.contains("sbfast") || url.contains("sbfull.com") || url.contains("javplaya.com") ||
|
||||
url.contains("ssbstream.net") || url.contains("p1ayerjavseen.com") || url.contains("sbthe.com") ||
|
||||
url.contains("sbchill.com") || url.contains("sblongvu.com") || url.contains("sbanh.com") ||
|
||||
url.contains("sblanh.com")
|
||||
url.contains("sblanh.com") || url.contains("sbhight.com") || url.contains("sbbrisk.com") ||
|
||||
url.contains("sbspeed.com")
|
||||
-> {
|
||||
val videos = StreamSBExtractor(client).videosFromUrl(url, headers, suffix = name, common = false)
|
||||
videos
|
||||
|
@ -1,141 +0,0 @@
|
||||
package eu.kanade.tachiyomi.animeextension.it.toonitalia.extractors
|
||||
|
||||
import eu.kanade.tachiyomi.animesource.model.Video
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import okhttp3.Headers
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
|
||||
class StreamSBExtractor(private val client: OkHttpClient) {
|
||||
|
||||
protected 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)
|
||||
}
|
||||
|
||||
// animension, asianload and dramacool uses "common = false"
|
||||
private fun fixUrl(url: String, common: Boolean): String {
|
||||
val sbUrl = url.substringBefore("/e/")
|
||||
val id = url.substringAfter("/e/")
|
||||
.substringBefore("?")
|
||||
.substringBefore(".html")
|
||||
return if (common) {
|
||||
val hexBytes = bytesToHex(id.toByteArray())
|
||||
"$sbUrl/sources48/625a364258615242766475327c7c${hexBytes}7c7c4761574550654f7461566d347c7c73747265616d7362"
|
||||
} else {
|
||||
"$sbUrl/sources48/${bytesToHex("||$id||||streamsb".toByteArray())}/"
|
||||
}
|
||||
}
|
||||
|
||||
private fun asciiToHex(asciiValue: String): String? {
|
||||
val chars = asciiValue.toCharArray()
|
||||
val hex = StringBuffer()
|
||||
for (i in chars.indices) {
|
||||
hex.append(Integer.toHexString(chars[i].code))
|
||||
}
|
||||
return hex.toString()
|
||||
}
|
||||
|
||||
private fun newFixUrl(url: String): String {
|
||||
val sbUrl = url.substringBefore("/e/")
|
||||
val id = url.substringAfter("/e/")
|
||||
.substringBefore("?")
|
||||
.substringBefore(".html")
|
||||
val hexBytes = asciiToHex(id.toHttpUrl().encodedPath.substringAfter("/"))
|
||||
return "$sbUrl/sources50/63556a6137557a4c5a3752427c7c${hexBytes}7c7c644a4c7356504f4d577949537c7c73747265616d7362"
|
||||
}
|
||||
|
||||
fun videosFromUrl(url: String, headers: Headers, prefix: String = "", suffix: String = "", common: Boolean = true): List<Video> {
|
||||
val newHeaders = headers.newBuilder()
|
||||
.set("referer", url)
|
||||
.set("watchsb", "sbstream")
|
||||
.set("authority", "embedsb.com")
|
||||
.build()
|
||||
return try {
|
||||
val newUrl = client.newCall(GET(url, headers = headers)).execute().request.url
|
||||
|
||||
val json = if (newUrl.host != url.toHttpUrl().host) {
|
||||
val master = newFixUrl(newUrl.toString()).replace(
|
||||
"""/(\w+)\.html""".toRegex(), ""
|
||||
)
|
||||
|
||||
val newHeaders = headers.newBuilder()
|
||||
.set("referer", newUrl.toString())
|
||||
.set("watchsb", "sbstream")
|
||||
.set("authority", "embedsb.com")
|
||||
.build()
|
||||
|
||||
Json.decodeFromString<JsonObject>(
|
||||
client.newCall(GET(master, newHeaders))
|
||||
.execute().body!!.string()
|
||||
)
|
||||
} else {
|
||||
val master = fixUrl(url, common)
|
||||
Json.decodeFromString<JsonObject>(
|
||||
client.newCall(GET(master, newHeaders))
|
||||
.execute().body!!.string()
|
||||
)
|
||||
}
|
||||
|
||||
val masterUrl = json["stream_data"]!!.jsonObject["file"].toString().trim('"')
|
||||
val masterPlaylist = client.newCall(GET(masterUrl, newHeaders))
|
||||
.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 = newHeaders)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
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()
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user