Some refactor and fix warnings
This commit is contained in:
1111
docs/parser_classes.gaphor
Normal file
1111
docs/parser_classes.gaphor
Normal file
File diff suppressed because it is too large
Load Diff
BIN
docs/parser_classes.png
Normal file
BIN
docs/parser_classes.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 53 KiB |
@@ -28,6 +28,13 @@ public interface MangaParser : Interceptor {
|
||||
|
||||
public val config: MangaSourceConfig
|
||||
|
||||
/**
|
||||
* Provide default domain and available alternatives, if any.
|
||||
*
|
||||
* Never hardcode domain in requests, use [domain] instead.
|
||||
*/
|
||||
public val configKeyDomain: ConfigKey.Domain
|
||||
|
||||
public val domain: String
|
||||
|
||||
public suspend fun getList(query: MangaSearchQuery): List<Manga>
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.*
|
||||
@InternalParsersApi
|
||||
public abstract class AbstractMangaParser @InternalParsersApi constructor(
|
||||
@property:InternalParsersApi public val context: MangaLoaderContext,
|
||||
public override val source: MangaParserSource,
|
||||
public final override val source: MangaParserSource,
|
||||
) : MangaParser {
|
||||
|
||||
public override val config: MangaSourceConfig by lazy { context.getConfig(source) }
|
||||
@@ -30,16 +30,18 @@ public abstract class AbstractMangaParser @InternalParsersApi constructor(
|
||||
public open val sourceLocale: Locale
|
||||
get() = if (source.locale.isEmpty()) Locale.ROOT else Locale(source.locale)
|
||||
|
||||
/**
|
||||
* Provide default domain and available alternatives, if any.
|
||||
*
|
||||
* Never hardcode domain in requests, use [domain] instead.
|
||||
*/
|
||||
@InternalParsersApi
|
||||
public abstract val configKeyDomain: ConfigKey.Domain
|
||||
|
||||
protected open val userAgentKey: ConfigKey.UserAgent = ConfigKey.UserAgent(context.getDefaultUserAgent())
|
||||
|
||||
protected val sourceContentRating: ContentRating?
|
||||
get() = if (source.contentType == ContentType.HENTAI) {
|
||||
ContentRating.ADULT
|
||||
} else {
|
||||
null
|
||||
}
|
||||
|
||||
final override val domain: String
|
||||
get() = config[configKeyDomain]
|
||||
|
||||
@Deprecated("Override intercept() instead")
|
||||
override fun getRequestHeaders(): Headers = Headers.Builder()
|
||||
.add("User-Agent", config[userAgentKey])
|
||||
@@ -54,9 +56,6 @@ public abstract class AbstractMangaParser @InternalParsersApi constructor(
|
||||
return SortOrder.entries.first { it in supported }
|
||||
}
|
||||
|
||||
override val domain: String
|
||||
get() = config[configKeyDomain]
|
||||
|
||||
@JvmField
|
||||
protected val webClient: WebClient = OkHttpWebClient(context.httpClient, source)
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ import java.util.*
|
||||
@InternalParsersApi
|
||||
public abstract class LegacyMangaParser @InternalParsersApi constructor(
|
||||
@property:InternalParsersApi public val context: MangaLoaderContext,
|
||||
public override val source: MangaParserSource,
|
||||
public final override val source: MangaParserSource,
|
||||
) : MangaParser {
|
||||
|
||||
public final override val searchQueryCapabilities: MangaSearchQueryCapabilities
|
||||
@@ -37,14 +37,6 @@ public abstract class LegacyMangaParser @InternalParsersApi constructor(
|
||||
|
||||
protected val isNsfwSource: Boolean = source.contentType == ContentType.HENTAI
|
||||
|
||||
/**
|
||||
* Provide default domain and available alternatives, if any.
|
||||
*
|
||||
* Never hardcode domain in requests, use [domain] instead.
|
||||
*/
|
||||
@InternalParsersApi
|
||||
public abstract val configKeyDomain: ConfigKey.Domain
|
||||
|
||||
protected open val userAgentKey: ConfigKey.UserAgent = ConfigKey.UserAgent(context.getDefaultUserAgent())
|
||||
|
||||
override fun getRequestHeaders(): Headers = Headers.Builder()
|
||||
@@ -60,7 +52,7 @@ public abstract class LegacyMangaParser @InternalParsersApi constructor(
|
||||
return SortOrder.entries.first { it in supported }
|
||||
}
|
||||
|
||||
override val domain: String
|
||||
final override val domain: String
|
||||
get() = config[configKeyDomain]
|
||||
|
||||
@JvmField
|
||||
|
||||
@@ -14,11 +14,11 @@ internal class MangaParserWrapper(
|
||||
private val delegate: MangaParser,
|
||||
) : MangaParser by delegate {
|
||||
|
||||
override suspend fun getList(searchQuery: MangaSearchQuery): List<Manga> = withContext(Dispatchers.Default) {
|
||||
if (!searchQuery.skipValidation) {
|
||||
searchQueryCapabilities.validate(searchQuery)
|
||||
override suspend fun getList(query: MangaSearchQuery): List<Manga> = withContext(Dispatchers.Default) {
|
||||
if (!query.skipValidation) {
|
||||
searchQueryCapabilities.validate(query)
|
||||
}
|
||||
delegate.getList(searchQuery)
|
||||
delegate.getList(query)
|
||||
}
|
||||
|
||||
override suspend fun getDetails(manga: Manga): Manga = withContext(Dispatchers.Default) {
|
||||
|
||||
@@ -180,7 +180,7 @@ internal abstract class MangaboxParser(
|
||||
authors = emptySet(),
|
||||
state = null,
|
||||
source = source,
|
||||
contentRating = if (source.contentType == ContentType.HENTAI) ContentRating.ADULT else ContentRating.SAFE,
|
||||
contentRating = sourceContentRating,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ internal class ManhwaIndoParser(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
private suspend fun fetchPage(img: Element): MangaPage? = runCatchingCancellable {
|
||||
val url = img.requireSrc().toAbsoluteUrl(domain) ?: return@runCatchingCancellable null
|
||||
val url = img.requireSrc().toAbsoluteUrl(domain)
|
||||
webClient.httpHead(url).use { response ->
|
||||
if (response.mimeType?.startsWith("image/") == true) {
|
||||
MangaPage(
|
||||
|
||||
@@ -50,7 +50,7 @@ internal class Hentai18VN(context: MangaLoaderContext) :
|
||||
parseMangaSearch(response)
|
||||
}
|
||||
|
||||
!filter.tags.isNullOrEmpty() -> {
|
||||
filter.tags.isNotEmpty() -> {
|
||||
val tag = filter.tags.first()
|
||||
val url = buildString {
|
||||
append("https://")
|
||||
|
||||
@@ -52,7 +52,7 @@ internal class HentaiVnBuzz(context: MangaLoaderContext) :
|
||||
}
|
||||
}
|
||||
|
||||
!filter.tags.isNullOrEmpty() -> {
|
||||
filter.tags.isNotEmpty() -> {
|
||||
val tag = filter.tags.first()
|
||||
buildString {
|
||||
append("/the-loai/")
|
||||
@@ -110,7 +110,7 @@ internal class HentaiVnBuzz(context: MangaLoaderContext) :
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return when {
|
||||
!filter.query.isNullOrEmpty() -> parseSearchManga(doc)
|
||||
!filter.tags.isNullOrEmpty() -> parseSearchManga(doc)
|
||||
filter.tags.isNotEmpty() -> parseSearchManga(doc)
|
||||
else -> parseListManga(doc)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ internal class TruyenHentaiVN(context: MangaLoaderContext) :
|
||||
append(domain)
|
||||
|
||||
when {
|
||||
!filter.tags.isNullOrEmpty() -> {
|
||||
filter.tags.isNotEmpty() -> {
|
||||
val tag = filter.tags.first()
|
||||
append(tag.key)
|
||||
if (page > 1) {
|
||||
|
||||
@@ -222,7 +222,7 @@ internal class DocTruyen3Q(context: MangaLoaderContext) :
|
||||
val fullUrl = chapter.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.page-chapter img").mapNotNull { img ->
|
||||
val url = img.attr("src")?.toAbsoluteUrl(domain) ?: return@mapNotNull null
|
||||
val url = img.attrAsAbsoluteUrlOrNull("src") ?: return@mapNotNull null
|
||||
MangaPage(
|
||||
id = generateUid(url),
|
||||
url = url,
|
||||
|
||||
@@ -3,19 +3,18 @@ package org.koitharu.kotatsu.parsers.site.wpcomics.vi
|
||||
import androidx.collection.ArraySet
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.coroutineScope
|
||||
import org.jsoup.nodes.Document
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import org.koitharu.kotatsu.parsers.MangaLoaderContext
|
||||
import org.koitharu.kotatsu.parsers.MangaSourceParser
|
||||
import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser
|
||||
import org.koitharu.kotatsu.parsers.exception.ParseException
|
||||
import org.koitharu.kotatsu.parsers.model.*
|
||||
import org.koitharu.kotatsu.parsers.site.wpcomics.WpComicsParser
|
||||
import org.koitharu.kotatsu.parsers.util.*
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
@MangaSourceParser("NEWTRUYEN", "NewTruyen", "vi")
|
||||
internal class NewTruyen(context: MangaLoaderContext) :
|
||||
WpComicsParser(context, MangaParserSource.NEWTRUYEN, "newtruyen2.com", 36) {
|
||||
WpComicsParser(context, MangaParserSource.NEWTRUYEN, "newtruyen2.com", 36) {
|
||||
|
||||
override suspend fun getFilterOptions() = MangaListFilterOptions(
|
||||
availableTags = getAvailableTags(),
|
||||
@@ -26,14 +25,14 @@ internal class NewTruyen(context: MangaLoaderContext) :
|
||||
val fullUrl = manga.url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
val storyID = doc.selectFirst("input#storyID")?.attr("value")
|
||||
?: throw ParseException("Story ID not found", fullUrl)
|
||||
?: throw ParseException("Story ID not found", fullUrl)
|
||||
val chaptersDeferred = async { getChapterList(storyID) }
|
||||
val tagsElement = doc.select("p.col-xs-12 a.tr-theloai")
|
||||
val mangaTags = tagsElement.map {
|
||||
MangaTag(
|
||||
title = it.text(),
|
||||
key = it.attr("href").substringAfterLast('/'),
|
||||
source = source
|
||||
source = source,
|
||||
)
|
||||
}.toSet()
|
||||
val author = doc.body().select(selectAut).textOrNull()
|
||||
@@ -54,7 +53,7 @@ internal class NewTruyen(context: MangaLoaderContext) :
|
||||
}
|
||||
|
||||
private suspend fun getChapterList(storyID: String): List<MangaChapter> {
|
||||
val url = "/Story/ListChapterByStoryID?storyID=" + storyID
|
||||
val url = "/Story/ListChapterByStoryID?storyID=$storyID"
|
||||
val fullUrl = url.toAbsoluteUrl(domain)
|
||||
val doc = webClient.httpGet(fullUrl).parseHtml()
|
||||
return doc.select("div.col-xs-5.chapter").mapChapters(reversed = true) { i, li ->
|
||||
|
||||
@@ -87,3 +87,15 @@ public inline fun <T, reified R> Collection<T>.mapToArray(transform: (T) -> R):
|
||||
forEachIndexed { index, t -> result[index] = transform(t) }
|
||||
return result as Array<R>
|
||||
}
|
||||
|
||||
public fun <T> Array<T>.toArraySet(): Set<T> = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(first())
|
||||
else -> ArraySet(this)
|
||||
}
|
||||
|
||||
public fun <T> Collection<T>.toArraySet(): Set<T> = when (size) {
|
||||
0 -> emptySet()
|
||||
1 -> setOf(first())
|
||||
else -> ArraySet(this)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user