Artist filter support

master
Koitharu 1 year ago
parent 9a1d37166a
commit 522b3d53cc
Signed by: Koitharu
GPG Key ID: 676DEE768C17A9D7

@ -15,6 +15,7 @@ public data class MangaListFilter(
@JvmField val year: Int = YEAR_UNKNOWN,
@JvmField val yearFrom: Int = YEAR_UNKNOWN,
@JvmField val yearTo: Int = YEAR_UNKNOWN,
@JvmField val author: String? = null,
) {
private fun isNonSearchOptionsEmpty(): Boolean = tags.isEmpty() &&
@ -27,7 +28,8 @@ public data class MangaListFilter(
yearFrom == YEAR_UNKNOWN &&
yearTo == YEAR_UNKNOWN &&
types.isEmpty() &&
demographics.isEmpty()
demographics.isEmpty() &&
author.isNullOrEmpty()
public fun isEmpty(): Boolean = isNonSearchOptionsEmpty() && query.isNullOrEmpty()

@ -47,4 +47,10 @@ public data class MangaListFilterCapabilities @InternalParsersApi constructor(
* @see [MangaListFilterOptions.availableLocales]
*/
val isOriginalLocaleSupported: Boolean = false,
/**
* Whether parser supports searching by author name
* @see [MangaListFilter.author]
*/
val isAuthorSearchSupported: Boolean = false,
)

@ -19,6 +19,7 @@ import org.koitharu.kotatsu.parsers.exception.AuthRequiredException
import org.koitharu.kotatsu.parsers.exception.TooManyRequestExceptions
import org.koitharu.kotatsu.parsers.model.*
import org.koitharu.kotatsu.parsers.util.*
import java.text.SimpleDateFormat
import java.util.*
import java.util.Collections.emptyList
import java.util.concurrent.TimeUnit
@ -54,6 +55,7 @@ internal class ExHentaiParser(
isTagsExclusionSupported = true,
isSearchSupported = true,
isSearchWithFiltersSupported = true,
isAuthorSearchSupported = true,
)
override val isAuthorized: Boolean
@ -172,8 +174,8 @@ internal class ExHentaiParser(
url = href,
publicUrl = a.absUrl("href"),
rating = td2.selectFirst("div.ir")?.parseRating() ?: RATING_UNKNOWN,
isNsfw = true,
coverUrl = td1.selectFirst("img")?.absUrl("src").orEmpty(),
contentRating = ContentRating.ADULT,
coverUrl = td1.selectFirst("img")?.attrAsAbsoluteUrlOrNull("src"),
tags = tagsDiv.parseTags(),
state = null,
author = tagsDiv.getElementsContainingOwnText("artist:").first()
@ -190,9 +192,18 @@ internal class ExHentaiParser(
val title = root.getElementById("gd2")
val tagList = root.getElementById("taglist")
val tabs = doc.body().selectFirst("table.ptt")?.selectFirst("tr")
val lang = root.getElementById("gd3")
val gd3 = root.getElementById("gd3")
val lang = gd3
?.selectFirst("tr:contains(Language)")
?.selectFirst(".gdt2")?.ownTextOrNull()
val uploadDate = gd3
?.selectFirst("tr:contains(Posted)")
?.selectFirst(".gdt2")?.ownTextOrNull()
.let { SimpleDateFormat("yyyy-MM-dd HH:mm", sourceLocale).tryParse(it) }
val uploader = gd3
?.getElementsByAttributeValueContaining("href", "/uploader/")
?.firstOrNull()
?.ownTextOrNull()
val tags = tagList?.parseTags().orEmpty()
return manga.copy(
@ -223,9 +234,9 @@ internal class ExHentaiParser(
number = i.toFloat(),
volume = 0,
url = url,
uploadDate = 0L,
uploadDate = uploadDate,
source = source,
scanlator = null,
scanlator = uploader,
branch = lang,
)
}
@ -415,6 +426,11 @@ internal class ExHentaiParser(
joiner.append(lc.toLanguagePath())
joiner.append("\"$")
}
if (!author.isNullOrEmpty()) {
joiner.add("artist:\"")
joiner.append(author)
joiner.append("\"$")
}
return joiner.complete().nullIfEmpty()
}

@ -103,12 +103,13 @@ internal abstract class GroupleParser(
} else {
advancedSearch(offset, order, filter).parseHtml()
}
val tiles =
root.selectFirst("div.tiles.row") ?: if (root.select(".alert").any { it.ownText() == NOTHING_FOUND }) {
val tiles = root.selectFirst("div.tiles.row")
if (tiles == null) {
if (!root.getElementsContainingOwnText(NOTHING_FOUND).isNullOrEmpty()) {
return emptyList()
} else {
root.parseFailed("No tiles found")
}
root.parseFailed("No tiles found")
}
return tiles.select("div.tile").mapNotNull(::parseManga)
}

Loading…
Cancel
Save