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'
pkgNameSuffix = 'all.googledriveindex'
extClass = '.GoogleDriveIndex'
extVersionCode = 1
extVersionCode = 2
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.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import okhttp3.Credentials
import okhttp3.HttpUrl
import okhttp3.HttpUrl.Companion.toHttpUrl
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.OkHttpClient
@ -31,6 +34,7 @@ import rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import uy.kohesive.injekt.injectLazy
import java.net.URLEncoder
class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
@ -52,7 +56,30 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
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 ===============================
@ -61,13 +88,17 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
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 = ""
val popHeaders = headers.newBuilder()
.add("Accept", "*/*")
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", baseUrl.toHttpUrl().host)
.add("Origin", "https://${baseUrl.toHttpUrl().host}")
.add("Referer", baseUrl)
.add("Referer", URLEncoder.encode(baseUrl, "UTF-8"))
.add("X-Requested-With", "XMLHttpRequest")
.build()
@ -88,6 +119,28 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
// =============================== 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 {
if (baseUrl.isEmpty()) {
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 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 = ""
val searchHeaders = headers.newBuilder()
.add("Accept", "*/*")
@ -110,11 +167,12 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
POST(
serverUrl,
body = popBody,
headers = searchHeaders.add("Referer", serverUrl).build(),
headers = searchHeaders.add("Referer", URLEncoder.encode(serverUrl, "UTF-8")).build(),
)
} else {
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())
@ -126,8 +184,8 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
}
}
override fun searchAnimeParse(response: Response): AnimesPage {
return parsePage(response, response.request.url.toString())
private fun searchAnimeParse(response: Response, url: String): AnimesPage {
return parsePage(response, url)
}
// ============================== FILTERS ===============================
@ -177,7 +235,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", 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")
.build()
@ -219,7 +277,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
.add("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
.add("Host", url.toHttpUrl().host)
.add("Origin", "https://${url.toHttpUrl().host}")
.add("Referer", url)
.add("Referer", URLEncoder.encode(url, "UTF-8"))
.add("X-Requested-With", "XMLHttpRequest")
.build()
@ -259,11 +317,6 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
} else {
""
}
val seasonText = if (season.isBlank()) {
""
} else {
"[${season.trimInfo()}] "
}
// Get other info
val extraInfo = if (paths.size > basePathCounter) {
@ -273,7 +326,7 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
}
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.scanlator = seasonInfo + extraInfo
episode.episode_number = counter.toFloat()
@ -319,6 +372,14 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
// ============================= 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 {
return path1.removeSuffix("/") + "/" + path2.removePrefix("/")
}
@ -446,7 +507,9 @@ class GoogleDriveIndex : ConfigurableAnimeSource, AnimeHttpSource() {
""".trimMargin()
this.setDefaultValue("")
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 ->
try {