|
|
@ -15,6 +15,7 @@ import eu.kanade.tachiyomi.extension.all.komga.dto.CollectionDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.LibraryDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.LibraryDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.PageDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.PageDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.PageWrapperDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.PageWrapperDto
|
|
|
|
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.ReadListDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.SeriesDto
|
|
|
|
import eu.kanade.tachiyomi.extension.all.komga.dto.SeriesDto
|
|
|
|
import eu.kanade.tachiyomi.network.GET
|
|
|
|
import eu.kanade.tachiyomi.network.GET
|
|
|
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
|
|
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
|
|
@ -54,7 +55,17 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
processSeriesPage(response)
|
|
|
|
processSeriesPage(response)
|
|
|
|
|
|
|
|
|
|
|
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
|
|
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
|
|
|
val url = HttpUrl.parse("$baseUrl/api/v1/series?search=$query&page=${page - 1}")!!.newBuilder()
|
|
|
|
val collectionId = (filters.find { it is CollectionSelect } as? CollectionSelect)?.let {
|
|
|
|
|
|
|
|
it.values[it.state].id
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val type = when {
|
|
|
|
|
|
|
|
collectionId != null -> "collections/$collectionId/series"
|
|
|
|
|
|
|
|
filters.find { it is TypeSelect }?.state == 1 -> "readlists"
|
|
|
|
|
|
|
|
else -> "series"
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
val url = HttpUrl.parse("$baseUrl/api/v1/$type?search=$query&page=${page - 1}")!!.newBuilder()
|
|
|
|
|
|
|
|
|
|
|
|
filters.forEach { filter ->
|
|
|
|
filters.forEach { filter ->
|
|
|
|
when (filter) {
|
|
|
|
when (filter) {
|
|
|
@ -74,17 +85,6 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
url.addQueryParameter("library_id", libraryToInclude.joinToString(","))
|
|
|
|
url.addQueryParameter("library_id", libraryToInclude.joinToString(","))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
is CollectionGroup -> {
|
|
|
|
|
|
|
|
val collectionToInclude = mutableListOf<String>()
|
|
|
|
|
|
|
|
filter.state.forEach { content ->
|
|
|
|
|
|
|
|
if (content.state) {
|
|
|
|
|
|
|
|
collectionToInclude.add(content.id)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (collectionToInclude.isNotEmpty()) {
|
|
|
|
|
|
|
|
url.addQueryParameter("collection_id", collectionToInclude.joinToString(","))
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
is StatusGroup -> {
|
|
|
|
is StatusGroup -> {
|
|
|
|
val statusToInclude = mutableListOf<String>()
|
|
|
|
val statusToInclude = mutableListOf<String>()
|
|
|
|
filter.state.forEach { content ->
|
|
|
|
filter.state.forEach { content ->
|
|
|
@ -164,9 +164,13 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
override fun mangaDetailsRequest(manga: SManga): Request =
|
|
|
|
override fun mangaDetailsRequest(manga: SManga): Request =
|
|
|
|
GET(baseUrl + manga.url, headers)
|
|
|
|
GET(baseUrl + manga.url, headers)
|
|
|
|
|
|
|
|
|
|
|
|
override fun mangaDetailsParse(response: Response): SManga {
|
|
|
|
override fun mangaDetailsParse(response: Response): SManga =
|
|
|
|
|
|
|
|
if (response.fromReadList()) {
|
|
|
|
|
|
|
|
val readList = gson.fromJson<ReadListDto>(response.body()?.charStream()!!)
|
|
|
|
|
|
|
|
readList.toSManga()
|
|
|
|
|
|
|
|
} else {
|
|
|
|
val series = gson.fromJson<SeriesDto>(response.body()?.charStream()!!)
|
|
|
|
val series = gson.fromJson<SeriesDto>(response.body()?.charStream()!!)
|
|
|
|
return series.toSManga()
|
|
|
|
series.toSManga()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun chapterListRequest(manga: SManga): Request =
|
|
|
|
override fun chapterListRequest(manga: SManga): Request =
|
|
|
@ -175,15 +179,16 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
override fun chapterListParse(response: Response): List<SChapter> {
|
|
|
|
override fun chapterListParse(response: Response): List<SChapter> {
|
|
|
|
val page = gson.fromJson<PageWrapperDto<BookDto>>(response.body()?.charStream()!!).content
|
|
|
|
val page = gson.fromJson<PageWrapperDto<BookDto>>(response.body()?.charStream()!!).content
|
|
|
|
|
|
|
|
|
|
|
|
return page.map { book ->
|
|
|
|
val r = page.map { book ->
|
|
|
|
SChapter.create().apply {
|
|
|
|
SChapter.create().apply {
|
|
|
|
chapter_number = book.metadata.numberSort
|
|
|
|
chapter_number = book.metadata.numberSort
|
|
|
|
name = "${book.metadata.number} - ${book.metadata.title} (${book.size})"
|
|
|
|
name = "${if (!response.fromReadList()) "${book.metadata.number} - " else ""}${book.metadata.title} (${book.size})"
|
|
|
|
url = "$baseUrl/api/v1/books/${book.id}"
|
|
|
|
url = "$baseUrl/api/v1/books/${book.id}"
|
|
|
|
date_upload = book.metadata.releaseDate?.let { parseDate(it) }
|
|
|
|
date_upload = book.metadata.releaseDate?.let { parseDate(it) }
|
|
|
|
?: parseDateTime(book.fileLastModified)
|
|
|
|
?: parseDateTime(book.fileLastModified)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}.sortedByDescending { it.chapter_number }
|
|
|
|
}
|
|
|
|
|
|
|
|
return if (!response.fromReadList()) r.sortedByDescending { it.chapter_number } else r.reversed()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun pageListRequest(chapter: SChapter): Request =
|
|
|
|
override fun pageListRequest(chapter: SChapter): Request =
|
|
|
@ -206,15 +211,15 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun processSeriesPage(response: Response): MangasPage {
|
|
|
|
private fun processSeriesPage(response: Response): MangasPage {
|
|
|
|
var lastPage: Boolean
|
|
|
|
if (response.fromReadList()) {
|
|
|
|
val page = with(gson.fromJson<PageWrapperDto<SeriesDto>>(response.body()?.charStream()!!)) {
|
|
|
|
with(gson.fromJson<PageWrapperDto<ReadListDto>>(response.body()?.charStream()!!)) {
|
|
|
|
lastPage = last
|
|
|
|
return MangasPage(content.map { it.toSManga() }, !last)
|
|
|
|
content
|
|
|
|
}
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
with(gson.fromJson<PageWrapperDto<SeriesDto>>(response.body()?.charStream()!!)) {
|
|
|
|
|
|
|
|
return MangasPage(content.map { it.toSManga() }, !last)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
val mangas = page.map {
|
|
|
|
|
|
|
|
it.toSManga()
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return MangasPage(mangas, !lastPage)
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
private fun SeriesDto.toSManga(): SManga =
|
|
|
|
private fun SeriesDto.toSManga(): SManga =
|
|
|
@ -229,12 +234,22 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
genre = (metadata.genres + metadata.tags).joinToString(", ")
|
|
|
|
genre = (metadata.genres + metadata.tags).joinToString(", ")
|
|
|
|
description = metadata.summary.ifBlank { booksMetadata.summary }
|
|
|
|
description = metadata.summary.ifBlank { booksMetadata.summary }
|
|
|
|
booksMetadata.authors.groupBy { it.role }.let {
|
|
|
|
booksMetadata.authors.groupBy { it.role }.let { map ->
|
|
|
|
author = it["writer"]?.map { it.name }?.distinct()?.joinToString()
|
|
|
|
author = map["writer"]?.map { it.name }?.distinct()?.joinToString()
|
|
|
|
artist = it["penciller"]?.map { it.name }?.distinct()?.joinToString()
|
|
|
|
artist = map["penciller"]?.map { it.name }?.distinct()?.joinToString()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun ReadListDto.toSManga(): SManga =
|
|
|
|
|
|
|
|
SManga.create().apply {
|
|
|
|
|
|
|
|
title = name
|
|
|
|
|
|
|
|
url = "/api/v1/readlists/$id"
|
|
|
|
|
|
|
|
thumbnail_url = "$baseUrl/api/v1/readlists/$id/thumbnail"
|
|
|
|
|
|
|
|
status = SManga.UNKNOWN
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private fun Response.fromReadList() = request().url().toString().contains("/api/v1/readlists")
|
|
|
|
|
|
|
|
|
|
|
|
private fun parseDate(date: String?): Long =
|
|
|
|
private fun parseDate(date: String?): Long =
|
|
|
|
if (date == null)
|
|
|
|
if (date == null)
|
|
|
|
Date().time
|
|
|
|
Date().time
|
|
|
@ -263,10 +278,10 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
|
|
|
|
|
|
|
|
override fun imageUrlParse(response: Response): String = ""
|
|
|
|
override fun imageUrlParse(response: Response): String = ""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private class TypeSelect : Filter.Select<String>("Search for", arrayOf(TYPE_SERIES, TYPE_READLISTS))
|
|
|
|
private class LibraryFilter(val id: String, name: String) : Filter.CheckBox(name, false)
|
|
|
|
private class LibraryFilter(val id: String, name: String) : Filter.CheckBox(name, false)
|
|
|
|
private class LibraryGroup(libraries: List<LibraryFilter>) : Filter.Group<LibraryFilter>("Libraries", libraries)
|
|
|
|
private class LibraryGroup(libraries: List<LibraryFilter>) : Filter.Group<LibraryFilter>("Libraries", libraries)
|
|
|
|
private class CollectionFilter(val id: String, name: String) : Filter.CheckBox(name, false)
|
|
|
|
private class CollectionSelect(collections: List<CollectionFilterEntry>) : Filter.Select<CollectionFilterEntry>("Collection", collections.toTypedArray())
|
|
|
|
private class CollectionGroup(collections: List<CollectionFilter>) : Filter.Group<CollectionFilter>("Collections", collections)
|
|
|
|
|
|
|
|
private class SeriesSort : Filter.Sort("Sort", arrayOf("Alphabetically", "Date added", "Date updated"), Selection(0, true))
|
|
|
|
private class SeriesSort : Filter.Sort("Sort", arrayOf("Alphabetically", "Date added", "Date updated"), Selection(0, true))
|
|
|
|
private class StatusFilter(name: String) : Filter.CheckBox(name, false)
|
|
|
|
private class StatusFilter(name: String) : Filter.CheckBox(name, false)
|
|
|
|
private class StatusGroup(filters: List<StatusFilter>) : Filter.Group<StatusFilter>("Status", filters)
|
|
|
|
private class StatusGroup(filters: List<StatusFilter>) : Filter.Group<StatusFilter>("Status", filters)
|
|
|
@ -280,11 +295,19 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
private class AuthorFilter(val author: AuthorDto) : Filter.CheckBox(author.name, false)
|
|
|
|
private class AuthorFilter(val author: AuthorDto) : Filter.CheckBox(author.name, false)
|
|
|
|
private class AuthorGroup(role: String, authors: List<AuthorFilter>) : Filter.Group<AuthorFilter>(role, authors)
|
|
|
|
private class AuthorGroup(role: String, authors: List<AuthorFilter>) : Filter.Group<AuthorFilter>(role, authors)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private data class CollectionFilterEntry(
|
|
|
|
|
|
|
|
val name: String,
|
|
|
|
|
|
|
|
val id: String? = null
|
|
|
|
|
|
|
|
) {
|
|
|
|
|
|
|
|
override fun toString() = name
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
override fun getFilterList(): FilterList =
|
|
|
|
override fun getFilterList(): FilterList =
|
|
|
|
FilterList(
|
|
|
|
FilterList(
|
|
|
|
UnreadOnly(),
|
|
|
|
UnreadOnly(),
|
|
|
|
|
|
|
|
TypeSelect(),
|
|
|
|
|
|
|
|
CollectionSelect(listOf(CollectionFilterEntry("None")) + collections.map { CollectionFilterEntry(it.name, it.id) }),
|
|
|
|
LibraryGroup(libraries.map { LibraryFilter(it.id, it.name) }.sortedBy { it.name.toLowerCase() }),
|
|
|
|
LibraryGroup(libraries.map { LibraryFilter(it.id, it.name) }.sortedBy { it.name.toLowerCase() }),
|
|
|
|
CollectionGroup(collections.map { CollectionFilter(it.id, it.name) }.sortedBy { it.name.toLowerCase() }),
|
|
|
|
|
|
|
|
StatusGroup(listOf("Ongoing", "Ended", "Abandoned", "Hiatus").map { StatusFilter(it) }),
|
|
|
|
StatusGroup(listOf("Ongoing", "Ended", "Abandoned", "Hiatus").map { StatusFilter(it) }),
|
|
|
|
GenreGroup(genres.map { GenreFilter(it) }),
|
|
|
|
GenreGroup(genres.map { GenreFilter(it) }),
|
|
|
|
TagGroup(tags.map { TagFilter(it) }),
|
|
|
|
TagGroup(tags.map { TagFilter(it) }),
|
|
|
@ -484,7 +507,7 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
{ response ->
|
|
|
|
{ response ->
|
|
|
|
authors = try {
|
|
|
|
authors = try {
|
|
|
|
val list: List<AuthorDto> = gson.fromJson(response.body()?.charStream()!!)
|
|
|
|
val list: List<AuthorDto> = gson.fromJson(response.body()?.charStream()!!)
|
|
|
|
list.groupBy({ it.role }, { it })
|
|
|
|
list.groupBy { it.role }
|
|
|
|
} catch (e: Exception) {
|
|
|
|
} catch (e: Exception) {
|
|
|
|
emptyMap()
|
|
|
|
emptyMap()
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -502,5 +525,8 @@ open class Komga(suffix: String = "") : ConfigurableSource, HttpSource() {
|
|
|
|
private const val PASSWORD_DEFAULT = ""
|
|
|
|
private const val PASSWORD_DEFAULT = ""
|
|
|
|
|
|
|
|
|
|
|
|
private val supportedImageTypes = listOf("image/jpeg", "image/png", "image/gif", "image/webp")
|
|
|
|
private val supportedImageTypes = listOf("image/jpeg", "image/png", "image/gif", "image/webp")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private const val TYPE_SERIES = "Series"
|
|
|
|
|
|
|
|
private const val TYPE_READLISTS = "Read lists"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|