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'
pkgNameSuffix = 'all.lanraragi'
extClass = '.LANraragi'
extVersionCode = 5
extVersionCode = 6
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.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<Filter<*>>()
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<Category>): Array<Pair<String?, String>> {
// 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 {