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.
This commit is contained in:
RePod 2021-04-01 08:42:50 -04:00 committed by GitHub
parent 8c60f17913
commit a942bdc87a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 44 additions and 49 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'LANraragi' extName = 'LANraragi'
pkgNameSuffix = 'all.lanraragi' pkgNameSuffix = 'all.lanraragi'
extClass = '.LANraragi' extClass = '.LANraragi'
extVersionCode = 5 extVersionCode = 6
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -25,13 +25,13 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.Dns
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import rx.Observable import rx.Observable
import rx.Single import rx.Single
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
@ -146,8 +146,6 @@ open class LANraragi : ConfigurableSource, HttpSource() {
val filters = mutableListOf<Filter<*>>() val filters = mutableListOf<Filter<*>>()
val prefNewOnly = preferences.getBoolean("latestNewOnly", false) val prefNewOnly = preferences.getBoolean("latestNewOnly", false)
filters.add(LatestView())
if (prefNewOnly) filters.add(NewArchivesOnly(true)) if (prefNewOnly) filters.add(NewArchivesOnly(true))
if (latestNamespacePref.isNotBlank()) { if (latestNamespacePref.isNotBlank()) {
@ -173,7 +171,6 @@ open class LANraragi : ConfigurableSource, HttpSource() {
filters.forEach { filter -> filters.forEach { filter ->
when (filter) { when (filter) {
is LatestView -> if (filter.state) uri.appendQueryParameter("latest", "latest")
is StartingPage -> { is StartingPage -> {
startPageOffset = filter.state.toIntOrNull() ?: 1 startPageOffset = filter.state.toIntOrNull() ?: 1
@ -229,12 +226,12 @@ open class LANraragi : ConfigurableSource, HttpSource() {
} }
private fun canShowRandom(response: Response): Boolean { 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 ( return (
totalRecords > 0 && totalRecords > 0 &&
lastRecordsFiltered == totalRecords &&
getStart(response) == 0 && 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 DescendingOrder(overrideState: Boolean = false) : Filter.CheckBox("Descending Order", overrideState)
private class NewArchivesOnly(overrideState: Boolean = false) : Filter.CheckBox("New Archives Only", overrideState) private class NewArchivesOnly(overrideState: Boolean = false) : Filter.CheckBox("New Archives Only", overrideState)
private class UntaggedArchivesOnly : Filter.CheckBox("Untagged Archives Only", false) private class UntaggedArchivesOnly : Filter.CheckBox("Untagged Archives Only", false)
@ -438,9 +434,7 @@ open class LANraragi : ConfigurableSource, HttpSource() {
// Helper // Helper
private fun getRandomID(response: Response): String { private fun getRandomID(response: Response): String {
return response.let { return response.headers("Location").firstOrNull()?.split("=")?.last() ?: ""
it.headers("Location").first()
}.split("=").last()
} }
private fun getRandomIDResponse(): Response { private fun getRandomIDResponse(): Response {
@ -454,12 +448,34 @@ open class LANraragi : ConfigurableSource, HttpSource() {
fun toUriPart() = vals[state].first 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<Category>): Array<Pair<String?, String>> { private fun getCategoryPairs(categories: List<Category>): Array<Pair<String?, String>> {
// Empty pair to disable. Sort by pinned status then name for convenience. // Empty pair to disable. Sort by pinned status then name for convenience.
// Web client sort is pinned > last_used but reflects between page changes. // Web client sort is pinned > last_used but reflects between page changes.
val pin = "\uD83D\uDCCC " 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("", "")) return listOf(Pair("", ""))
.plus( .plus(
categories categories
@ -519,53 +535,32 @@ open class LANraragi : ConfigurableSource, HttpSource() {
return null return null
} }
private fun getArtist(tags: String?): String { private fun getArtist(tags: String?): String = getNSTag(tags, "artist")?.get(1) ?: "N/A"
getNSTag(tags, "artist")?.let {
return it[1]
}
return "N/A"
}
private fun getDateAdded(tags: String?): String { private fun getDateAdded(tags: String?): String {
getNSTag(tags, "date_added")?.let { // Pad Date Added NS to milliseconds
// Pad Date Added NS to milliseconds return getNSTag(tags, "date_added")?.get(1)?.padEnd(13, '0') ?: ""
return it[1].padEnd(13, '0')
}
return ""
} }
// Headers (currently auth) are done in headersBuilder // 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 // 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 { init {
// Save users a Random refresh in the extension and from Library if (baseUrl.isNotBlank()) {
Single.fromCallable { getRandomIDResponse() } // Save a FilterList reset
.subscribeOn(Schedulers.io()) getCategories()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(
{ randomArchiveID = getRandomID(it) },
{}
)
Single.fromCallable { // Save users a Random refresh in the extension and from Library
client.newCall(GET("$baseUrl/api/categories", headers)).execute() 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 { companion object {