Update video extraction (#1591)
This commit is contained in:
parent
8f19319f4c
commit
bb678e9562
@ -6,7 +6,7 @@ ext {
|
||||
extName = 'HolaMovies'
|
||||
pkgNameSuffix = 'en.holamovies'
|
||||
extClass = '.HolaMovies'
|
||||
extVersionCode = 1
|
||||
extVersionCode = 2
|
||||
libVersion = '13'
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user