Add extension for LANraragi (#1383)
* Add extension for LANraragi LANraragi project page: https://github.com/Difegue/LANraragi * Drop tag exclusion support and improve tag search perfomance a bit * LANraragi: API fixes as of 0.6.7 Image routing was 404ing in Mojolicious due to preceding / resulting in //api/page Manga parsing was failing with "no fun mode" due to wrong URL parameter for key * Update to newer API * Fix strange bug on last page * Increment version code * Reset increment back to 1 & Instantiate Gson once only Co-authored-by: RePod <RePod@users.noreply.github.com>
This commit is contained in:
parent
731df4ccdd
commit
0f3f79eebd
|
@ -0,0 +1,21 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: LANraragi'
|
||||
pkgNameSuffix = 'all.lanraragi'
|
||||
extClass = '.LANraragi'
|
||||
extVersionCode = 1
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compileOnly project(':preference-stub')
|
||||
|
||||
compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
|
||||
|
||||
compileOnly 'com.google.code.gson:gson:2.8.2'
|
||||
compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
Binary file not shown.
After Width: | Height: | Size: 3.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.4 KiB |
Binary file not shown.
After Width: | Height: | Size: 7.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
Binary file not shown.
After Width: | Height: | Size: 59 KiB |
|
@ -0,0 +1,257 @@
|
|||
package eu.kanade.tachiyomi.extension.all.lanraragi
|
||||
|
||||
import android.app.Application
|
||||
import android.content.SharedPreferences
|
||||
import android.net.Uri
|
||||
import android.support.v7.preference.EditTextPreference
|
||||
import android.support.v7.preference.PreferenceScreen
|
||||
import com.github.salomonbrys.kotson.fromJson
|
||||
import com.google.gson.Gson
|
||||
import eu.kanade.tachiyomi.extension.all.lanraragi.model.ArchivePage
|
||||
import eu.kanade.tachiyomi.extension.all.lanraragi.model.ArchiveSearchResult
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
open class LANraragi : ConfigurableSource, HttpSource() {
|
||||
|
||||
override val baseUrl: String
|
||||
get() = preferences.getString("hostname", "http://127.0.0.1:3000")!!
|
||||
|
||||
override val lang = "all"
|
||||
|
||||
override val name = "LANraragi"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
private val apiKey: String
|
||||
get() = preferences.getString("apiKey", "")!!
|
||||
|
||||
private val gson: Gson = Gson()
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val id = getId(response)
|
||||
|
||||
return SManga.create().apply {
|
||||
thumbnail_url = getThumbnailUri(id)
|
||||
}
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val id = getId(response)
|
||||
|
||||
val uri = getApiUriBuilder("/api/extract")
|
||||
uri.appendQueryParameter("id", id)
|
||||
|
||||
return listOf(
|
||||
SChapter.create().apply {
|
||||
val uriBuild = uri.build()
|
||||
|
||||
url = "${uriBuild.encodedPath}?${uriBuild.encodedQuery}"
|
||||
chapter_number = 1F
|
||||
name = "Chapter"
|
||||
})
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val archivePage = gson.fromJson<ArchivePage>(response.body()!!.string())
|
||||
|
||||
return archivePage.pages.mapIndexed { index, url ->
|
||||
val uri = Uri.parse("${baseUrl}${url.trimStart('.')}")
|
||||
Page(index, uri.toString(), uri.toString(), uri)
|
||||
}
|
||||
}
|
||||
|
||||
override fun imageUrlParse(response: Response) = throw UnsupportedOperationException("imageUrlParse is unused")
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return searchMangaRequest(page, "", FilterList())
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
return searchMangaParse(response)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return searchMangaRequest(page, "", FilterList())
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
return searchMangaParse(response)
|
||||
}
|
||||
|
||||
private var lastResultCount: Int = 100
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val uri = getApiUriBuilder("/api/search")
|
||||
uri.appendQueryParameter("start", ((page - 1) * lastResultCount).toString())
|
||||
|
||||
if (query.isNotEmpty()) {
|
||||
uri.appendQueryParameter("filter", query)
|
||||
}
|
||||
|
||||
return GET(uri.toString())
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
val jsonResult = gson.fromJson<ArchiveSearchResult>(response.body()!!.string())
|
||||
val currentStart = getStart(response)
|
||||
|
||||
lastResultCount = jsonResult.data.size
|
||||
|
||||
return MangasPage(
|
||||
jsonResult.data.map {
|
||||
SManga.create().apply {
|
||||
url = "/reader?id=${it.arcid}"
|
||||
title = it.title
|
||||
thumbnail_url = getThumbnailUri(it.arcid)
|
||||
genre = it.tags
|
||||
artist = getArtist(it.tags)
|
||||
author = artist
|
||||
}
|
||||
}, currentStart + jsonResult.data.size < jsonResult.recordsFiltered)
|
||||
}
|
||||
|
||||
// Preferences
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val hostnamePref = EditTextPreference(screen.context).apply {
|
||||
key = "Hostname"
|
||||
title = "Hostname"
|
||||
text = baseUrl
|
||||
summary = baseUrl
|
||||
dialogTitle = "Hostname"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
var hostname = newValue as String
|
||||
if (!hostname.startsWith("http://") && !hostname.startsWith("https://")) {
|
||||
hostname = "http://$hostname"
|
||||
}
|
||||
|
||||
this.apply {
|
||||
text = hostname
|
||||
summary = hostname
|
||||
}
|
||||
|
||||
preferences.edit().putString("hostname", hostname).commit()
|
||||
}
|
||||
}
|
||||
|
||||
val apiKeyPref = EditTextPreference(screen.context).apply {
|
||||
key = "API Key"
|
||||
title = "API Key"
|
||||
text = apiKey
|
||||
summary = apiKey
|
||||
dialogTitle = "API Key"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val apiKey = newValue as String
|
||||
|
||||
this.apply {
|
||||
text = apiKey
|
||||
summary = apiKey
|
||||
}
|
||||
|
||||
preferences.edit().putString("apiKey", newValue).commit()
|
||||
}
|
||||
}
|
||||
|
||||
screen.addPreference(hostnamePref)
|
||||
screen.addPreference(apiKeyPref)
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
||||
val hostnamePref = androidx.preference.EditTextPreference(screen.context).apply {
|
||||
key = "Hostname"
|
||||
title = "Hostname"
|
||||
text = baseUrl
|
||||
summary = baseUrl
|
||||
dialogTitle = "Hostname"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
var hostname = newValue as String
|
||||
if (!hostname.startsWith("http://") && !hostname.startsWith("https://")) {
|
||||
hostname = "http://$hostname"
|
||||
}
|
||||
|
||||
this.apply {
|
||||
text = hostname
|
||||
summary = hostname
|
||||
}
|
||||
|
||||
preferences.edit().putString("hostname", hostname).commit()
|
||||
}
|
||||
}
|
||||
|
||||
val apiKeyPref = androidx.preference.EditTextPreference(screen.context).apply {
|
||||
key = "API Key"
|
||||
title = "API Key"
|
||||
text = apiKey
|
||||
summary = apiKey
|
||||
dialogTitle = "API Key"
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
val apiKey = newValue as String
|
||||
|
||||
this.apply {
|
||||
text = apiKey
|
||||
summary = apiKey
|
||||
}
|
||||
|
||||
preferences.edit().putString("apiKey", newValue).commit()
|
||||
}
|
||||
}
|
||||
|
||||
screen.addPreference(hostnamePref)
|
||||
screen.addPreference(apiKeyPref)
|
||||
}
|
||||
|
||||
// Helper
|
||||
private fun getApiUriBuilder(path: String): Uri.Builder {
|
||||
val uri = Uri.parse("$baseUrl$path").buildUpon()
|
||||
if (apiKey.isNotEmpty()) {
|
||||
uri.appendQueryParameter("key", apiKey)
|
||||
}
|
||||
|
||||
return uri
|
||||
}
|
||||
|
||||
private fun getThumbnailUri(id: String): String {
|
||||
val uri = getApiUriBuilder("/api/thumbnail")
|
||||
uri.appendQueryParameter("id", id)
|
||||
|
||||
return uri.toString()
|
||||
}
|
||||
|
||||
private fun getTopResponse(response: Response): Response {
|
||||
return if (response.priorResponse() == null) response else getTopResponse(response.priorResponse()!!)
|
||||
}
|
||||
|
||||
private fun getId(response: Response): String {
|
||||
return getTopResponse(response).request().url().queryParameter("id").toString()
|
||||
}
|
||||
|
||||
private fun getStart(response: Response): Int {
|
||||
return getTopResponse(response).request().url().queryParameter("start")!!.toInt()
|
||||
}
|
||||
|
||||
private fun getArtist(tags: String): String {
|
||||
tags.split(',').forEach {
|
||||
if (it.contains(':')) {
|
||||
val temp = it.trim().split(':')
|
||||
|
||||
if (temp[0].equals("artist", true)) return temp[1]
|
||||
}
|
||||
}
|
||||
|
||||
return "N/A"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
package eu.kanade.tachiyomi.extension.all.lanraragi.model
|
||||
|
||||
data class Archive(
|
||||
val arcid: String,
|
||||
val isnew: String,
|
||||
val tags: String,
|
||||
val title: String
|
||||
)
|
|
@ -0,0 +1,5 @@
|
|||
package eu.kanade.tachiyomi.extension.all.lanraragi.model
|
||||
|
||||
data class ArchivePage(
|
||||
val pages: List<String>
|
||||
)
|
|
@ -0,0 +1,8 @@
|
|||
package eu.kanade.tachiyomi.extension.all.lanraragi.model
|
||||
|
||||
data class ArchiveSearchResult(
|
||||
val data: List<Archive>,
|
||||
val draw: Int,
|
||||
val recordsFiltered: Int,
|
||||
val recordsTotal: Int
|
||||
)
|
Loading…
Reference in New Issue