LANraragi: 0.8.2 support and fixes (#9905)

* LANraragi: Mark status as Completed

* LANraragi: Use API for Random (first pass)

No longer need a unique client.
No header shenanigans, straight from source.

* LANraragi: Fix tag display

API response no longer spaces them out.

* LANraragi: Warn on 401

* LANraragi: Use API for Random (second pass)

Unify the Random helper functions.
Inline what was canShowRandom().
Use new /files (GET) endpoint as /extract (POST) is now deprecated.
Remove 404 handling from fetchMangaDetails() (as the 401 handling should cover it).
Include headers for isnew DELETE.

* LANraragi: Update icons

* LANraragi: IOException on 401 instead
This commit is contained in:
RePod 2021-11-23 08:31:40 -05:00 committed by GitHub
parent 8d66d91299
commit 41994b164a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 36 additions and 46 deletions

View File

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.9 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 134 KiB

View File

@ -5,14 +5,15 @@ import android.content.SharedPreferences
import android.net.Uri
import android.util.Base64
import com.github.salomonbrys.kotson.fromJson
import com.github.salomonbrys.kotson.get
import com.google.gson.Gson
import com.google.gson.JsonObject
import eu.kanade.tachiyomi.extension.all.lanraragi.model.Archive
import eu.kanade.tachiyomi.extension.all.lanraragi.model.ArchivePage
import eu.kanade.tachiyomi.extension.all.lanraragi.model.ArchiveSearchResult
import eu.kanade.tachiyomi.extension.all.lanraragi.model.Category
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
@ -32,6 +33,7 @@ import rx.Single
import rx.schedulers.Schedulers
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
open class LANraragi : ConfigurableSource, HttpSource() {
@ -55,20 +57,21 @@ open class LANraragi : ConfigurableSource, HttpSource() {
private var randomArchiveID: String = ""
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
val id = if (manga.url == "/random") randomArchiveID else getReaderId(manga.url)
val id = if (manga.url.startsWith("/api/search/random")) randomArchiveID else getReaderId(manga.url)
val uri = getApiUriBuilder("/api/archives/$id/metadata").build()
if (manga.url == "/random") randomArchiveID = getRandomID(getRandomIDResponse())
if (manga.url.startsWith("/api/search/random")) {
val randQuery = Uri.parse(manga.url).encodedQuery.toString()
randomArchiveID = getRandomID(randQuery)
}
return client.newCall(GET(uri.toString(), headers))
.asObservable().doOnNext {
if (!it.isSuccessful && it.code == 404) error("Log in with WebView then try again.")
}
.asObservableSuccess()
.map { mangaDetailsParse(it).apply { initialized = true } }
}
override fun mangaDetailsRequest(manga: SManga): Request {
// Catch-all that includes /random's ID via thumbnail
// Catch-all that includes random's ID via thumbnail
val id = getThumbnailId(manga.thumbnail_url!!)
return GET("$baseUrl/reader?id=$id", headers)
@ -81,7 +84,7 @@ open class LANraragi : ConfigurableSource, HttpSource() {
}
override fun chapterListRequest(manga: SManga): Request {
val id = if (manga.url == "/random") randomArchiveID else getReaderId(manga.url)
val id = if (manga.url.startsWith("/api/search/random")) randomArchiveID else getReaderId(manga.url)
val uri = getApiUriBuilder("/api/archives/$id/metadata").build()
return GET(uri.toString(), headers)
@ -89,12 +92,13 @@ open class LANraragi : ConfigurableSource, HttpSource() {
override fun chapterListParse(response: Response): List<SChapter> {
val archive = gson.fromJson<Archive>(response.body!!.string())
val uri = getApiUriBuilder("/api/archives/${archive.arcid}/extract")
val uri = getApiUriBuilder("/api/archives/${archive.arcid}/files")
// Replicate old behavior and unset "isnew" for the archive.
if (archive.isnew == "true") {
val clearNew = Request.Builder()
.url("$baseUrl/api/archives/${archive.arcid}/isnew")
.headers(headers)
.delete()
.build()
@ -117,7 +121,7 @@ open class LANraragi : ConfigurableSource, HttpSource() {
}
override fun pageListRequest(chapter: SChapter): Request {
return POST(chapter.url, headers)
return GET(chapter.url, headers)
}
override fun pageListParse(response: Response): List<Page> {
@ -203,14 +207,16 @@ open class LANraragi : ConfigurableSource, HttpSource() {
lastRecordsFiltered = jsonResult.recordsFiltered
totalRecords = jsonResult.recordsTotal
if (canShowRandom(response)) {
if (lastResultCount > 1 && currentStart == 0) {
val randQuery = response.request.url.encodedQuery.toString()
randomArchiveID = getRandomID(randQuery)
archives.add(
SManga.create().apply {
url = "/random"
url = "/api/search/random?count=1&$randQuery"
title = "Random"
description = "Refresh for a random archive."
// Get the server's "noThumb" thumbnail by default
thumbnail_url = getThumbnailUri("tachiyomi")
thumbnail_url = getThumbnailUri("tachiyomi") // noThumb
}
)
}
@ -222,24 +228,15 @@ open class LANraragi : ConfigurableSource, HttpSource() {
return MangasPage(archives, currentStart + jsonResult.data.size < jsonResult.recordsFiltered)
}
private fun canShowRandom(response: Response): Boolean {
// 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 &&
getStart(response) == 0 &&
response.request.url.querySize == 1 // ?start=
)
}
private fun archiveToSManga(archive: Archive) = SManga.create().apply {
url = "/reader?id=${archive.arcid}"
title = archive.title
description = archive.title
thumbnail_url = getThumbnailUri(archive.arcid)
genre = archive.tags
genre = archive.tags.replace(",", ", ")
artist = getArtist(archive.tags)
author = artist
status = SManga.COMPLETED
}
override fun headersBuilder() = Headers.Builder().apply {
@ -352,14 +349,11 @@ open class LANraragi : ConfigurableSource, HttpSource() {
}
// Helper
private fun getRandomID(response: Response): String {
return response.headers("Location").firstOrNull()?.split("=")?.last() ?: ""
}
private fun getRandomID(query: String): String {
val searchRandom = client.newCall(GET("$baseUrl/api/search/random?$query", headers)).execute()
val data = gson.fromJson<JsonObject>(searchRandom.body!!.string())["data"]
private fun getRandomIDResponse(): Response {
// Separate function for init and Library
// /random 301's to the ID so the request is over as quickly as it starts
return clientNoFollow.newCall(GET("$baseUrl/random", headers)).execute()
return data.asJsonArray.firstOrNull()?.get("id")?.asString ?: ""
}
protected open class UriPartFilter(displayName: String, val vals: Array<Pair<String?, String>>) :
@ -462,23 +456,19 @@ open class LANraragi : ConfigurableSource, HttpSource() {
}
// Headers (currently auth) are done in headersBuilder
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().dns(Dns.SYSTEM).followRedirects(false).build()
override val client: OkHttpClient = network.client.newBuilder()
.dns(Dns.SYSTEM)
.addInterceptor { chain ->
val response = chain.proceed(chain.request())
if (response.code == 401) throw IOException("If the server is in No-Fun Mode make sure the extension's API Key is correct.")
response
}
.build()
init {
if (baseUrl.isNotBlank()) {
// Save a FilterList reset
getCategories()
// Save users a Random refresh in the extension and from Library
Single.fromCallable { getRandomIDResponse() }
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(
{ randomArchiveID = getRandomID(it) },
{}
)
}
}