Implement search and filters (#8706)

This commit is contained in:
Arraiment 2021-08-22 01:32:34 +08:00 committed by GitHub
parent 4ba9118ce3
commit 40ea248097
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 112 additions and 22 deletions

View File

@ -1,11 +1,12 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlinx-serialization'
ext {
extName = 'Comic Fx'
pkgNameSuffix = 'id.comicfx'
extClass = '.ComicFx'
extVersionCode = 2
extVersionCode = 3
libVersion = '1.2'
}

View File

@ -1,18 +1,27 @@
package eu.kanade.tachiyomi.extension.id.comicfx
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import kotlinx.serialization.json.Json
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.Request
import okhttp3.Response
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.api.get
import rx.Observable
import uy.kohesive.injekt.injectLazy
import java.text.ParseException
import java.text.SimpleDateFormat
import java.util.Locale
@ -62,14 +71,54 @@ class ComicFx : ParsedHttpSource() {
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
// Search
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
// Text search cannot use filters
if (query.isNotEmpty()) {
return client.newCall(GET("$baseUrl/search?query=$query"))
.asObservableSuccess()
.map { response ->
parseSearchApiResponse(response)
}
}
return super.fetchSearchManga(page, query, filters)
}
private val json: Json by injectLazy()
private fun parseSearchApiResponse(response: Response): MangasPage {
val results = json.parseToJsonElement(response.body!!.string()).jsonObject["suggestions"]!!.jsonArray
val manga = results.map {
SManga.create().apply {
title = it.jsonObject["value"]!!.jsonPrimitive.content
url = "/komik/${it.jsonObject["data"]!!.jsonPrimitive.content}"
}
}
return MangasPage(manga, false)
}
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val filters = if (filters.isEmpty()) getFilterList() else filters
val genre = filters.findInstance<GenreList>()?.toUriPart()
val order = filters.findInstance<OrderByFilter>()?.toUriPart()
val filterList = if (filters.isEmpty()) getFilterList() else filters
// todo search
val url = "$baseUrl/filterList".toHttpUrlOrNull()!!.newBuilder()
return GET("$baseUrl/filterList?page=$page&cstatus=&ctype=&cat=$genre&alpha=&$order&author=&artist=&tag=") // filter
for (filter in filterList) {
when (filter) {
is GenreFilter -> url.addQueryParameter("cat", filter.toUriPart())
is SortFilter -> {
url.addQueryParameter("sortBy", filter.toUriPart())
url.addQueryParameter("asc", filter.state!!.ascending.toString())
}
is StatusFilter -> url.addQueryParameter("cstatus", filter.toUriPart())
is TypeFilter -> url.addQueryParameter("ctype", filter.toUriPart())
is AuthorFilter -> url.addQueryParameter("author", filter.state)
is ArtistFilter -> url.addQueryParameter("artist", filter.state)
}
}
url.addQueryParameter("page", page.toString())
// Unimplemented parameters: "alpha" (For filtering by alphabet) and "tag" (idk)
return GET(url.toString())
}
override fun searchMangaSelector() = popularMangaSelector()
@ -105,18 +154,31 @@ class ComicFx : ParsedHttpSource() {
val updateOn = document.select(".infokomik .infolengkap span:contains(update) b").text()
val date = document.select(".infokomik .infolengkap span:contains(update)").text().substringAfter(updateOn)
val checkChapter = document.select(chapterListSelector()).firstOrNull()
if (date != "" && checkChapter != null) chapters[0].date_upload = parseDate(date)
if (date != "" && checkChapter != null && chapters[0].date_upload == 0L) {
chapters[0].date_upload = SimpleDateFormat("dd mmm yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
}
return chapters
}
private fun parseDate(date: String): Long {
return SimpleDateFormat("dd MMM yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
return when (date) {
"hari ini" -> System.currentTimeMillis()
"kemarin" -> System.currentTimeMillis() - (1000 * 60 * 60 * 24) // yesterday
else -> {
try {
SimpleDateFormat("dd-mm-yyyy", Locale.ENGLISH).parse(date)?.time ?: 0L
} catch (_: ParseException) {
0L
}
}
}
}
override fun chapterFromElement(element: Element) = SChapter.create().apply {
setUrlWithoutDomain(element.attr("href"))
name = element.text()
name = element.selectFirst("span.chapternum").text()
date_upload = parseDate(element.selectFirst("span.chapterdate").text())
}
// Pages
@ -137,22 +199,29 @@ class ComicFx : ParsedHttpSource() {
// filters
override fun getFilterList() = FilterList(
OrderByFilter(),
GenreList()
SortFilter(sortList),
GenreFilter(),
StatusFilter(),
TypeFilter(),
ArtistFilter("Artist"),
AuthorFilter("Author")
)
private class OrderByFilter : UriPartFilter(
"Sort by",
arrayOf(
Pair("sortBy=name&asc=true", "Default"),
Pair("sortBy=name&asc=true", "A-Z"),
Pair("sortBy=name&asc=false", "Z-A"),
Pair("sortBy=views&asc=false", "Popular to Less"),
Pair("sortBy=views&asc=true", "Less to Popular")
)
private class ArtistFilter(name: String) : Filter.Text(name)
private class AuthorFilter(name: String) : Filter.Text(name)
private class SortFilter(val sortables: List<Pair<String, String>>) : Filter.Sort("Sort", sortables.map { it.second }.toTypedArray(), Selection(1, false)) {
fun toUriPart(): String {
return sortables[this.state!!.index].first
}
}
private val sortList = listOf(
Pair("name", "Alphabetical"),
Pair("views", "Popular"),
)
private class GenreList : UriPartFilter(
private class GenreFilter : UriPartFilter(
"Select Genre",
arrayOf(
Pair("", "<select>"),
@ -190,6 +259,26 @@ class ComicFx : ParsedHttpSource() {
)
)
private class StatusFilter : UriPartFilter(
"Status",
arrayOf(
Pair("", "All"),
Pair("1", "Ongoing"),
Pair("2", "Complete")
)
)
private class TypeFilter : UriPartFilter(
"Type",
arrayOf(
Pair("", "All"),
Pair("1", "Manhua (Chinese)"),
Pair("2", "Manhwa (Korean)"),
Pair("3", "Manga"),
Pair("4", "Oneshot"),
)
)
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
Filter.Select<String>(displayName, vals.map { it.second }.toTypedArray()) {
fun toUriPart() = vals[state].first