From a942bdc87a001583359757d813fdc495bbe8a930 Mon Sep 17 00:00:00 2001 From: RePod Date: Thu, 1 Apr 2021 08:42:50 -0400 Subject: [PATCH] LANraragi: Category, Random, and DNS fixes (#6379) * LANraragi: Category to own function and observe on io Move category retrieval to own function for init and refreshing when FilterList is reset (for the next one...) to maintain sync without restarting. Observe on io instead of mainThread to avoid exception for "large" requests. Also considered: callbacks. * LANraragi: Clean up getArtist and getDateAdded * LANraragi: Safer getRandomID * LANraragi: Improve Random item visibility Previously a server with a dirty DB would have conflicting numbers and need to run a clean to fix them. That's still the case but that's not the extension's problem and those numbers are no longer considered. Switched to a querySize check to remain only on the initial Browse page. Remove previous Latest query smuggling due to above. * LANraragi: Ignore DNS over HTTPS Fixes #6341 Similarly not act without a configured server. I miss you, return early... * LANraragi: Init random ID observe on io Drop mainThread entirely. --- src/all/lanraragi/build.gradle | 2 +- .../extension/all/lanraragi/LANraragi.kt | 91 +++++++++---------- 2 files changed, 44 insertions(+), 49 deletions(-) diff --git a/src/all/lanraragi/build.gradle b/src/all/lanraragi/build.gradle index 819307dcc..9201f365c 100644 --- a/src/all/lanraragi/build.gradle +++ b/src/all/lanraragi/build.gradle @@ -5,7 +5,7 @@ ext { extName = 'LANraragi' pkgNameSuffix = 'all.lanraragi' extClass = '.LANraragi' - extVersionCode = 5 + extVersionCode = 6 libVersion = '1.2' } diff --git a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt index fd6823d69..ab824428b 100644 --- a/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt +++ b/src/all/lanraragi/src/eu/kanade/tachiyomi/extension/all/lanraragi/LANraragi.kt @@ -25,13 +25,13 @@ import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.online.HttpSource import okhttp3.CacheControl +import okhttp3.Dns import okhttp3.Headers import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response import rx.Observable import rx.Single -import rx.android.schedulers.AndroidSchedulers import rx.schedulers.Schedulers import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -146,8 +146,6 @@ open class LANraragi : ConfigurableSource, HttpSource() { val filters = mutableListOf>() val prefNewOnly = preferences.getBoolean("latestNewOnly", false) - filters.add(LatestView()) - if (prefNewOnly) filters.add(NewArchivesOnly(true)) if (latestNamespacePref.isNotBlank()) { @@ -173,7 +171,6 @@ open class LANraragi : ConfigurableSource, HttpSource() { filters.forEach { filter -> when (filter) { - is LatestView -> if (filter.state) uri.appendQueryParameter("latest", "latest") is StartingPage -> { startPageOffset = filter.state.toIntOrNull() ?: 1 @@ -229,12 +226,12 @@ open class LANraragi : ConfigurableSource, HttpSource() { } private fun canShowRandom(response: Response): Boolean { - // Server has archives, no meaningful filtering, not paginating, and not Latest + // Server has archives, not paginating, no meaningful filtering. querySize check would have + // to be broken intentionally as it goes through searchMangaRequest. Likely for an API change. return ( totalRecords > 0 && - lastRecordsFiltered == totalRecords && getStart(response) == 0 && - response.request().url().queryParameter("latest") == null + response.request().url().querySize() == 1 // ?start= ) } @@ -255,7 +252,6 @@ open class LANraragi : ConfigurableSource, HttpSource() { } } - private class LatestView() : Filter.CheckBox("", true) private class DescendingOrder(overrideState: Boolean = false) : Filter.CheckBox("Descending Order", overrideState) private class NewArchivesOnly(overrideState: Boolean = false) : Filter.CheckBox("New Archives Only", overrideState) private class UntaggedArchivesOnly : Filter.CheckBox("Untagged Archives Only", false) @@ -438,9 +434,7 @@ open class LANraragi : ConfigurableSource, HttpSource() { // Helper private fun getRandomID(response: Response): String { - return response.let { - it.headers("Location").first() - }.split("=").last() + return response.headers("Location").firstOrNull()?.split("=")?.last() ?: "" } private fun getRandomIDResponse(): Response { @@ -454,12 +448,34 @@ open class LANraragi : ConfigurableSource, HttpSource() { fun toUriPart() = vals[state].first } + private fun getCategories() { + Single.fromCallable { + client.newCall(GET("$baseUrl/api/categories", headers)).execute() + } + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe( + { + categories = try { + gson.fromJson(it.body()?.charStream()!!) + } catch (e: Exception) { + emptyList() + } + }, + {} + ) + } + private fun getCategoryPairs(categories: List): Array> { // Empty pair to disable. Sort by pinned status then name for convenience. // Web client sort is pinned > last_used but reflects between page changes. val pin = "\uD83D\uDCCC " + // Maintain categories sync for next FilterList reset. If there's demand for it, it's now + // possible to sort by last_used similar to the web client. Maybe an option toggle? + getCategories() + return listOf(Pair("", "")) .plus( categories @@ -519,53 +535,32 @@ open class LANraragi : ConfigurableSource, HttpSource() { return null } - private fun getArtist(tags: String?): String { - getNSTag(tags, "artist")?.let { - return it[1] - } - - return "N/A" - } + private fun getArtist(tags: String?): String = getNSTag(tags, "artist")?.get(1) ?: "N/A" private fun getDateAdded(tags: String?): String { - getNSTag(tags, "date_added")?.let { - // Pad Date Added NS to milliseconds - return it[1].padEnd(13, '0') - } - - return "" + // Pad Date Added NS to milliseconds + return getNSTag(tags, "date_added")?.get(1)?.padEnd(13, '0') ?: "" } // Headers (currently auth) are done in headersBuilder - override val client: OkHttpClient = network.client.newBuilder().build() + override val client: OkHttpClient = network.client.newBuilder().dns(Dns.SYSTEM).build() // Specifically for /random to grab IDs without triggering a server-side extract - private val clientNoFollow: OkHttpClient = client.newBuilder().followRedirects(false).build() + private val clientNoFollow: OkHttpClient = client.newBuilder().dns(Dns.SYSTEM).followRedirects(false).build() init { - // Save users a Random refresh in the extension and from Library - Single.fromCallable { getRandomIDResponse() } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - { randomArchiveID = getRandomID(it) }, - {} - ) + if (baseUrl.isNotBlank()) { + // Save a FilterList reset + getCategories() - Single.fromCallable { - client.newCall(GET("$baseUrl/api/categories", headers)).execute() + // Save users a Random refresh in the extension and from Library + Single.fromCallable { getRandomIDResponse() } + .subscribeOn(Schedulers.io()) + .observeOn(Schedulers.io()) + .subscribe( + { randomArchiveID = getRandomID(it) }, + {} + ) } - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe( - { response -> - categories = try { - gson.fromJson(response.body()?.charStream()!!) - } catch (e: Exception) { - emptyList() - } - }, - {} - ) } companion object {