GoogleDriveIndex: Fix/add stuff (#1450)

* Fix/add stuff

* Throw exception for people misusing the extension
This commit is contained in:
Secozzi
2023-03-30 13:57:25 +02:00
committed by GitHub
parent 0d9fd56807
commit a82204f80b
2 changed files with 79 additions and 16 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'GoogleDriveIndex' extName = 'GoogleDriveIndex'
pkgNameSuffix = 'all.googledriveindex' pkgNameSuffix = 'all.googledriveindex'
extClass = '.GoogleDriveIndex' extClass = '.GoogleDriveIndex'
extVersionCode = 1 extVersionCode = 2
libVersion = '13' libVersion = '13'
} }

View File

@ -17,10 +17,13 @@ import eu.kanade.tachiyomi.animesource.model.Video
import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource import eu.kanade.tachiyomi.animesource.online.AnimeHttpSource
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.util.asJsoup import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import okhttp3.Credentials
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -31,6 +34,7 @@ import rx.Observable
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() { class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
@ -52,7 +56,30 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
} }
override val client: OkHttpClient = network.cloudflareClient override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addInterceptor { chain ->
var request = chain.request()
if (request.url.username.isNotBlank() && request.url.password.isNotBlank()) {
val credential = Credentials.basic(request.url.username, request.url.password)
request = request.newBuilder()
.header("Authorization", credential)
.build()
val newUrl = request.url.newBuilder()
.username("")
.password("")
.build()
request = request.newBuilder()
.url(newUrl)
.build()
}
chain.proceed(request)
}
.build()
// ============================== Popular =============================== // ============================== Popular ===============================
@ -61,13 +88,17 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
throw Exception("Enter drive path(s) in extension settings.") throw Exception("Enter drive path(s) in extension settings.")
} }
if (baseUrl.toHttpUrl().host == "drive.google.com") {
throw Exception("This extension is only for Google Drive Index sites, not drive.google.com folders.")
}
if (page == 1) pageToken = "" if (page == 1) pageToken = ""
val popHeaders = headers.newBuilder() val popHeaders = headers.newBuilder()
.add("Accept", "*/*") .add("Accept", "*/*")
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", baseUrl.toHttpUrl().host) .add("Host", baseUrl.toHttpUrl().host)
.add("Origin", "https://${baseUrl.toHttpUrl().host}") .add("Origin", "https://${baseUrl.toHttpUrl().host}")
.add("Referer", baseUrl) .add("Referer", URLEncoder.encode(baseUrl, "UTF-8"))
.add("X-Requested-With", "XMLHttpRequest") .add("X-Requested-With", "XMLHttpRequest")
.build() .build()
@ -88,6 +119,28 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
// =============================== Search =============================== // =============================== Search ===============================
override fun searchAnimeParse(response: Response): AnimesPage = throw Exception("Not used")
override fun fetchSearchAnime(
page: Int,
query: String,
filters: AnimeFilterList,
): Observable<AnimesPage> {
val req = searchAnimeRequest(page, query, filters)
return Observable.defer {
try {
client.newCall(req).asObservableSuccess()
} catch (e: NoClassDefFoundError) {
// RxJava doesn't handle Errors, which tends to happen during global searches
// if an old extension using non-existent classes is still around
throw RuntimeException(e)
}
}
.map { response ->
searchAnimeParse(response, req.url.toString())
}
}
override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request { override fun searchAnimeRequest(page: Int, query: String, filters: AnimeFilterList): Request {
if (baseUrl.isEmpty()) { if (baseUrl.isEmpty()) {
throw Exception("Enter drive path(s) in extension settings.") throw Exception("Enter drive path(s) in extension settings.")
@ -97,6 +150,10 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
val serverFilter = filterList.find { it is ServerFilter } as ServerFilter val serverFilter = filterList.find { it is ServerFilter } as ServerFilter
val serverUrl = serverFilter.toUriPart() val serverUrl = serverFilter.toUriPart()
if (serverUrl.toHttpUrl().host == "drive.google.com") {
throw Exception("This extension is only for Google Drive Index sites, not drive.google.com folders.")
}
if (page == 1) pageToken = "" if (page == 1) pageToken = ""
val searchHeaders = headers.newBuilder() val searchHeaders = headers.newBuilder()
.add("Accept", "*/*") .add("Accept", "*/*")
@ -110,11 +167,12 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
POST( POST(
serverUrl, serverUrl,
body = popBody, body = popBody,
headers = searchHeaders.add("Referer", serverUrl).build(), headers = searchHeaders.add("Referer", URLEncoder.encode(serverUrl, "UTF-8")).build(),
) )
} else { } else {
val cleanQuery = query.replace(" ", "+") val cleanQuery = query.replace(" ", "+")
val searchUrl = "https://${serverUrl.toHttpUrl().host}/${serverUrl.toHttpUrl().pathSegments[0]}search"
val searchUrl = "https://${serverUrl.toHttpUrl().hostAndCred()}/${serverUrl.toHttpUrl().pathSegments[0]}search"
val popBody = "q=$cleanQuery&page_token=$pageToken&page_index=${page - 1}".toRequestBody("application/x-www-form-urlencoded".toMediaType()) val popBody = "q=$cleanQuery&page_token=$pageToken&page_index=${page - 1}".toRequestBody("application/x-www-form-urlencoded".toMediaType())
@ -126,8 +184,8 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
} }
} }
override fun searchAnimeParse(response: Response): AnimesPage { private fun searchAnimeParse(response: Response, url: String): AnimesPage {
return parsePage(response, response.request.url.toString()) return parsePage(response, url)
} }
// ============================== FILTERS =============================== // ============================== FILTERS ===============================
@ -177,7 +235,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", idParsed.url.toHttpUrl().host) .add("Host", idParsed.url.toHttpUrl().host)
.add("Origin", "https://${idParsed.url.toHttpUrl().host}") .add("Origin", "https://${idParsed.url.toHttpUrl().host}")
.add("Referer", idParsed.referer) .add("Referer", URLEncoder.encode(idParsed.referer, "UTF-8"))
.add("X-Requested-With", "XMLHttpRequest") .add("X-Requested-With", "XMLHttpRequest")
.build() .build()
@ -219,7 +277,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8") .add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", url.toHttpUrl().host) .add("Host", url.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}") .add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", url) .add("Referer", URLEncoder.encode(url, "UTF-8"))
.add("X-Requested-With", "XMLHttpRequest") .add("X-Requested-With", "XMLHttpRequest")
.build() .build()
@ -259,11 +317,6 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
} else { } else {
"" ""
} }
val seasonText = if (season.isBlank()) {
""
} else {
"[${season.trimInfo()}] "
}
// Get other info // Get other info
val extraInfo = if (paths.size > basePathCounter) { val extraInfo = if (paths.size > basePathCounter) {
@ -273,7 +326,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
} }
val size = item.size?.toLongOrNull()?.let { formatFileSize(it) } val size = item.size?.toLongOrNull()?.let { formatFileSize(it) }
episode.name = "$seasonText${item.name.trimInfo()}${if (size == null) "" else " - $size"}" episode.name = "${item.name.trimInfo()}${if (size == null) "" else " - $size"}"
episode.url = epUrl episode.url = epUrl
episode.scanlator = seasonInfo + extraInfo episode.scanlator = seasonInfo + extraInfo
episode.episode_number = counter.toFloat() episode.episode_number = counter.toFloat()
@ -319,6 +372,14 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================= Utilities ============================== // ============================= Utilities ==============================
private fun HttpUrl.hostAndCred(): String {
return if (this.password.isNotBlank() && this.username.isNotBlank()) {
"${this.username}:${this.password}@${this.host}"
} else {
this.host
}
}
private fun joinUrl(path1: String, path2: String): String { private fun joinUrl(path1: String, path2: String): String {
return path1.removeSuffix("/") + "/" + path2.removePrefix("/") return path1.removeSuffix("/") + "/" + path2.removePrefix("/")
} }
@ -446,7 +507,9 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
""".trimMargin() """.trimMargin()
this.setDefaultValue("") this.setDefaultValue("")
dialogTitle = "Path list" dialogTitle = "Path list"
dialogMessage = "Separate paths with a comma" dialogMessage = """Separate paths with a comma. For password protected sites,
|format as: "https://username:password@example.worker.dev/0:/"
""".trimMargin()
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
try { try {