[Komga] add filters by library (#1638)

* add filters by library

* add custom User-Agent, Komga server can log it to identify clients

* use BuildConfig for version name in User-Agent

* add file size to chapter name
This commit is contained in:
Gauthier 2019-11-05 11:03:19 +08:00 committed by arkon
parent 374915a989
commit 3152424782
3 changed files with 73 additions and 16 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: Komga' appName = 'Tachiyomi: Komga'
pkgNameSuffix = 'all.komga' pkgNameSuffix = 'all.komga'
extClass = '.Komga' extClass = '.Komga'
extVersionCode = 2 extVersionCode = 3
libVersion = '1.2' libVersion = '1.2'
} }
@ -14,6 +14,8 @@ dependencies {
compileOnly 'com.google.code.gson:gson:2.8.5' compileOnly 'com.google.code.gson:gson:2.8.5'
compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0' compileOnly 'com.github.salomonbrys.kotson:kotson:2.5.0'
compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440' compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
implementation 'io.reactivex:rxandroid:1.2.1'
implementation 'io.reactivex:rxjava:1.3.6'
} }
apply from: "$rootDir/common.gradle" apply from: "$rootDir/common.gradle"

View File

@ -7,15 +7,16 @@ import android.support.v7.preference.PreferenceScreen
import android.widget.Toast import android.widget.Toast
import com.github.salomonbrys.kotson.fromJson import com.github.salomonbrys.kotson.fromJson
import com.google.gson.Gson import com.google.gson.Gson
import eu.kanade.tachiyomi.extension.all.komga.dto.BookDto import eu.kanade.tachiyomi.extension.BuildConfig
import eu.kanade.tachiyomi.extension.all.komga.dto.PageDto import eu.kanade.tachiyomi.extension.all.komga.dto.*
import eu.kanade.tachiyomi.extension.all.komga.dto.PageWrapperDto
import eu.kanade.tachiyomi.extension.all.komga.dto.SerieDto
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.ConfigurableSource import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.model.*
import eu.kanade.tachiyomi.source.online.HttpSource import eu.kanade.tachiyomi.source.online.HttpSource
import okhttp3.* import okhttp3.*
import rx.Single
import rx.android.schedulers.AndroidSchedulers
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
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -35,8 +36,27 @@ open class Komga : ConfigurableSource, HttpSource() {
override fun latestUpdatesParse(response: Response): MangasPage = override fun latestUpdatesParse(response: Response): MangasPage =
processSeriePage(response) processSeriePage(response)
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
GET("$baseUrl/api/v1/series?search=$query&page=${page - 1}", headers) val url = HttpUrl.parse("$baseUrl/api/v1/series?search=$query&page=${page - 1}")!!.newBuilder()
filters.forEach { filter ->
when (filter) {
is LibraryGroup -> {
val libraryToInclude = mutableListOf<Long>()
filter.state.forEach { content ->
if (content.state) {
libraryToInclude.add(content.id)
}
}
if (libraryToInclude.isNotEmpty()) {
url.addQueryParameter("library_id", libraryToInclude.joinToString(","))
}
}
}
}
return GET(url.toString(), headers)
}
override fun searchMangaParse(response: Response): MangasPage = override fun searchMangaParse(response: Response): MangasPage =
processSeriePage(response) processSeriePage(response)
@ -45,8 +65,8 @@ open class Komga : ConfigurableSource, HttpSource() {
GET(baseUrl + manga.url, headers) GET(baseUrl + manga.url, headers)
override fun mangaDetailsParse(response: Response): SManga { override fun mangaDetailsParse(response: Response): SManga {
val serie = gson.fromJson<SerieDto>(response.body()?.charStream()!!) val series = gson.fromJson<SeriesDto>(response.body()?.charStream()!!)
return serie.toSManga() return series.toSManga()
} }
override fun chapterListRequest(manga: SManga): Request = override fun chapterListRequest(manga: SManga): Request =
@ -60,7 +80,7 @@ open class Komga : ConfigurableSource, HttpSource() {
return page.content.mapIndexed { i, book -> return page.content.mapIndexed { i, book ->
SChapter.create().apply { SChapter.create().apply {
chapter_number = (i + 1).toFloat() chapter_number = (i + 1).toFloat()
name = book.name name = "${book.name} (${book.size})"
url = "$chapterListUrl/${book.id}" url = "$chapterListUrl/${book.id}"
date_upload = parseDate(book.lastModified) date_upload = parseDate(book.lastModified)
} }
@ -87,14 +107,14 @@ open class Komga : ConfigurableSource, HttpSource() {
} }
private fun processSeriePage(response: Response): MangasPage { private fun processSeriePage(response: Response): MangasPage {
val page = gson.fromJson<PageWrapperDto<SerieDto>>(response.body()?.charStream()!!) val page = gson.fromJson<PageWrapperDto<SeriesDto>>(response.body()?.charStream()!!)
val mangas = page.content.map { val mangas = page.content.map {
it.toSManga() it.toSManga()
} }
return MangasPage(mangas, !page.last) return MangasPage(mangas, !page.last)
} }
private fun SerieDto.toSManga(): SManga = private fun SeriesDto.toSManga(): SManga =
SManga.create().apply { SManga.create().apply {
title = this@toSManga.name title = this@toSManga.name
url = "/api/v1/series/${this@toSManga.id}" url = "/api/v1/series/${this@toSManga.id}"
@ -119,19 +139,47 @@ open class Komga : ConfigurableSource, HttpSource() {
override fun imageUrlParse(response: Response): String = "" override fun imageUrlParse(response: Response): String = ""
override val name = "Komga" private class LibraryFilter(val id: Long, name: String) : Filter.CheckBox(name, false)
override val lang = "en" private class LibraryGroup(libraries: List<LibraryFilter>) : Filter.Group<LibraryFilter>("Libraries", libraries)
override fun getFilterList(): FilterList =
FilterList(
LibraryGroup(libraries.map { LibraryFilter(it.id, it.name) }.sortedBy { it.name })
)
private var libraries = emptyList<LibraryDto>()
override val name = "Komga"
override val lang = "en"
override val supportsLatest = true override val supportsLatest = true
override val baseUrl by lazy { getPrefBaseUrl() } override val baseUrl by lazy { getPrefBaseUrl() }
private val username by lazy { getPrefUsername() } private val username by lazy { getPrefUsername() }
private val password by lazy { getPrefPassword() } private val password by lazy { getPrefPassword() }
private val gson by lazy { Gson() } private val gson by lazy { Gson() }
init {
Single.fromCallable {
client.newCall(GET("$baseUrl/api/v1/libraries", headers)).execute()
}
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe({
libraries = try {
gson.fromJson(it.body()?.charStream()!!)
} catch (e: Exception) {
emptyList()
}
}, {})
}
override fun headersBuilder(): Headers.Builder = override fun headersBuilder(): Headers.Builder =
Headers.Builder() Headers.Builder()
.add("Authorization", Credentials.basic(username, password)) .add("Authorization", Credentials.basic(username, password))
.add("User-Agent", "Tachiyomi Komga v${BuildConfig.VERSION_NAME}")
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000) Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)

View File

@ -1,6 +1,11 @@
package eu.kanade.tachiyomi.extension.all.komga.dto package eu.kanade.tachiyomi.extension.all.komga.dto
data class SerieDto( data class LibraryDto(
val id: Long,
val name: String
)
data class SeriesDto(
val id: Long, val id: Long,
val name: String, val name: String,
val lastModified: String? val lastModified: String?
@ -10,6 +15,8 @@ data class BookDto(
val id: Long, val id: Long,
val name: String, val name: String,
val lastModified: String?, val lastModified: String?,
val sizeBytes: Long,
val size: String,
val metadata: BookMetadataDto val metadata: BookMetadataDto
) )