Update video extraction (#1591)

This commit is contained in:
Secozzi 2023-05-09 12:38:12 +02:00 committed by GitHub
parent 8f19319f4c
commit bb678e9562
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 83 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'HolaMovies'
pkgNameSuffix = 'en.holamovies'
extClass = '.HolaMovies'
extVersionCode = 1
extVersionCode = 2
libVersion = '13'
}

View File

@ -3,6 +3,10 @@ package eu.kanade.tachiyomi.animeextension.en.holamovies.extractors
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.OkHttpClient
@ -24,18 +28,29 @@ class GDBotExtractor(private val client: OkHttpClient, private val headers: Head
GET("$botUrl/file/$fileId", headers = docHeaders),
).execute().asJsoup()
document.select("li.py-6 > a[href]").forEach {
val url = it.attr("href")
videoList.addAll(
document.select("li.py-6 > a[href]").parallelMap { server ->
runCatching {
val url = server.attr("href")
when {
url.toHttpUrl().host.contains("gdflix") -> {
videoList.addAll(GDFlixExtractor(client, headers).videosFromUrl(url))
GDFlixExtractor(client, headers).videosFromUrl(url)
}
// url.toHttpUrl().host.contains("gdtot") -> {
// videoList.addAll(GDTotExtractor(client, headers).videosFromUrl(url))
// }
url.toHttpUrl().host.contains("gdtot") -> {
GDTotExtractor(client, headers).videosFromUrl(url)
}
else -> null
}
}.getOrNull()
}.filterNotNull().flatten(),
)
return videoList
}
// From Dopebox
private fun <A, B> Iterable<A>.parallelMap(f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
}

View File

@ -1,10 +1,13 @@
package eu.kanade.tachiyomi.animeextension.en.holamovies.extractors
import android.util.Base64
import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.Serializable
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
@ -20,78 +23,37 @@ class GDFlixExtractor(private val client: OkHttpClient, private val headers: Hea
fun videosFromUrl(serverUrl: String): List<Video> {
val videoList = mutableListOf<Video>()
val failedMediaUrl = mutableListOf<Pair<String, String>>()
if (serverUrl.toHttpUrl().encodedPath != "/404") {
val (videos, mediaUrl) = extractVideo(EpUrl("Video", serverUrl, "Video"))
if (videos.isEmpty()) failedMediaUrl.add(Pair(mediaUrl, "Video"))
videoList.addAll(videos)
videoList.addAll(
listOf("direct", "drivebot").parallelMap { type ->
runCatching {
when (type) {
"direct" -> {
extractGDriveLink(serverUrl)
}
"drivebot" -> {
extractDriveBotLink(serverUrl)
}
else -> null
}
videoList.addAll(
failedMediaUrl.mapNotNull { (url, quality) ->
runCatching {
extractGDriveLink(url, quality)
}.getOrNull()
}.flatten(),
)
videoList.addAll(
failedMediaUrl.mapNotNull { (url, quality) ->
runCatching {
extractDriveBotLink(url)
}.getOrNull()
}.flatten(),
}.filterNotNull().flatten(),
)
return videoList
}
private fun extractVideo(epUrl: EpUrl): Pair<List<Video>, String> {
val videoList = mutableListOf<Video>()
val qualityRegex = """(\d+)p""".toRegex()
val matchResult = qualityRegex.find(epUrl.name)
val quality = if (matchResult == null) {
epUrl.quality
} else {
matchResult.groupValues[1]
// From Dopebox
private fun <A, B> Iterable<A>.parallelMap(f: suspend (A) -> B): List<B> =
runBlocking {
map { async(Dispatchers.Default) { f(it) } }.awaitAll()
}
for (type in 1..3) {
videoList.addAll(
extractWorkerLinks(epUrl.url, quality, type),
)
}
return Pair(videoList, epUrl.url)
}
private val sizeRegex = "\\[((?:.(?!\\[))+)][ ]*\$".toRegex(RegexOption.IGNORE_CASE)
private fun extractWorkerLinks(mediaUrl: String, quality: String, type: Int): List<Video> {
val reqLink = mediaUrl.replace("/file/", "/wfile/") + "?type=$type"
val resp = client.newCall(GET(reqLink)).execute().asJsoup()
val sizeMatch = sizeRegex.find(resp.select("div.card-header").text().trim())
val size = sizeMatch?.groups?.get(1)?.value?.let { " - $it" } ?: ""
return resp.select("div.card-body div.mb-4 > a").mapIndexed { index, linkElement ->
val link = linkElement.attr("href")
val decodedLink = if (link.contains("workers.dev")) {
link
} else {
String(Base64.decode(link.substringAfter("download?url="), Base64.DEFAULT))
}
Video(
url = decodedLink,
quality = "$quality - CF $type Worker ${index + 1}$size",
videoUrl = decodedLink,
)
}
}
private fun extractGDriveLink(mediaUrl: String, quality: String): List<Video> {
private fun extractGDriveLink(mediaUrl: String): List<Video> {
val tokenClient = client.newBuilder().addInterceptor(TokenInterceptor()).build()
val response = tokenClient.newCall(GET(mediaUrl)).execute().asJsoup()
val gdBtn = response.selectFirst("div.card-body a.btn")!!
val gdLink = gdBtn.attr("href")
@ -160,13 +122,6 @@ class GDFlixExtractor(private val client: OkHttpClient, private val headers: Hea
)
}
@Serializable
data class EpUrl(
val quality: String,
val url: String,
val name: String,
)
@Serializable
data class DriveBotResp(
val url: String,

View File

@ -9,8 +9,6 @@ import okhttp3.OkHttpClient
class GDTotExtractor(private val client: OkHttpClient, private val headers: Headers) {
fun videosFromUrl(serverUrl: String): List<Video> {
val videoList = mutableListOf<Video>()
val docHeaders = headers.newBuilder()
.add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8")
.add("Host", serverUrl.toHttpUrl().host)
@ -34,8 +32,8 @@ class GDTotExtractor(private val client: OkHttpClient, private val headers: Head
GET(ddlUrl, headers = ddlHeaders),
).execute().asJsoup()
// TODO - Finish it
val btn = document.selectFirst("button[onclick~=drive.google.com]")?.attr("onclick") ?: return emptyList()
return videoList
return GoogleDriveExtractor(client, headers).videosFromUrl(btn.substringAfter("myDl('").substringBefore("'"), "GDToT")
}
}