fixed suggestions

master
Naga 2 years ago
parent 2e86c480ec
commit efc9b3502c

@ -67,14 +67,7 @@ class Manga(
* Manga source * Manga source
*/ */
@JvmField val source: MangaSource, @JvmField val source: MangaSource,
) {
@JvmField val date: Long? = null,
@JvmField val readCount: Long? = null,
@JvmField val likeCount: Long? = null,
) {
/** /**
* Return if manga has a specified rating * Return if manga has a specified rating
@ -116,10 +109,7 @@ class Manga(
largeCoverUrl = largeCoverUrl, largeCoverUrl = largeCoverUrl,
description = description, description = description,
chapters = chapters, chapters = chapters,
source = source, source = source
date = date,
readCount = readCount,
likeCount = likeCount,
) )
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
@ -143,9 +133,7 @@ class Manga(
if (description != other.description) return false if (description != other.description) return false
if (chapters != other.chapters) return false if (chapters != other.chapters) return false
if (source != other.source) return false if (source != other.source) return false
if (date != other.date) return false
if (readCount != other.readCount) return false
if (likeCount != other.likeCount) return false
return true return true
} }
@ -165,9 +153,6 @@ class Manga(
result = 31 * result + (description?.hashCode() ?: 0) result = 31 * result + (description?.hashCode() ?: 0)
result = 31 * result + (chapters?.hashCode() ?: 0) result = 31 * result + (chapters?.hashCode() ?: 0)
result = 31 * result + source.hashCode() result = 31 * result + source.hashCode()
result = 31 * result + (date?.hashCode() ?: 0)
result = 31 * result + (readCount?.hashCode() ?: 0)
result = 31 * result + (likeCount?.hashCode() ?: 0)
return result return result
} }

@ -1,6 +1,5 @@
package org.koitharu.kotatsu.parsers.site.all package org.koitharu.kotatsu.parsers.site.all
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.async import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.coroutineScope
@ -24,6 +23,7 @@ import org.koitharu.kotatsu.parsers.model.MangaSource
import org.koitharu.kotatsu.parsers.model.MangaTag import org.koitharu.kotatsu.parsers.model.MangaTag
import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN import org.koitharu.kotatsu.parsers.model.RATING_UNKNOWN
import org.koitharu.kotatsu.parsers.model.SortOrder import org.koitharu.kotatsu.parsers.model.SortOrder
import org.koitharu.kotatsu.parsers.util.SoftSuspendLazy
import org.koitharu.kotatsu.parsers.util.SuspendLazy import org.koitharu.kotatsu.parsers.util.SuspendLazy
import org.koitharu.kotatsu.parsers.util.domain import org.koitharu.kotatsu.parsers.util.domain
import org.koitharu.kotatsu.parsers.util.generateUid import org.koitharu.kotatsu.parsers.util.generateUid
@ -86,50 +86,19 @@ internal abstract class WebtoonsParser(
"zh" -> "zh-hant" "zh" -> "zh-hant"
else -> tag else -> tag
} }
/*
private suspend fun getChapters(titleNo: Long): List<MangaChapter> {
val firstResult = makeRequest(
url = "/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=0&pageSize=30",
)
val totalEpisodeCount = firstResult.getJSONObject("episodeList").getInt("totalServiceEpisodeCount")
val episodes = firstResult.getJSONObject("episodeList").getJSONArray("episode").toJSONList().toMutableList()
while (episodes.count() < totalEpisodeCount) {
val page = makeRequest(
url = "/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=${episodes.count()}&pageSize=30",
).getJSONObject("episodeList").getJSONArray("episode").toJSONList()
episodes.addAll(page)
}
return episodes.mapChapters { i, jo ->
MangaChapter(
id = generateUid("$titleNo-$i"),
name = jo.getString("episodeTitle"),
number = jo.getInt("episodeSeq"),
url = "$titleNo-${jo.get("episodeNo")}",
uploadDate = jo.getLong("registerYmdt"),
branch = null,
scanlator = null,
source = source,
)
}.sortedBy { it.number }
}
*/
private suspend fun fetchEpisodes(titleNo: Long): List<MangaChapter> = coroutineScope { private suspend fun fetchEpisodes(titleNo: Long): List<MangaChapter> = coroutineScope {
val firstResult = makeRequest("/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=0&pageSize=30") val firstResult =
makeRequest("/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=0&pageSize=30")
val totalEpisodeCount = firstResult.getJSONObject("episodeList").getInt("totalServiceEpisodeCount") val totalEpisodeCount = firstResult.getJSONObject("episodeList").getInt("totalServiceEpisodeCount")
val episodes = firstResult.getJSONObject("episodeList").getJSONArray("episode").toJSONList().toMutableList() val episodes = firstResult.getJSONObject("episodeList").getJSONArray("episode").toJSONList().toMutableList()
val additionalEpisodes = (episodes.size until totalEpisodeCount step 30).map { startIndex -> val additionalEpisodes = (episodes.size until totalEpisodeCount step 30).map { startIndex ->
async(Dispatchers.IO) { async {
makeRequest("/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=$startIndex&pageSize=30") makeRequest("/lineWebtoon/webtoon/episodeList.json?v=5&titleNo=$titleNo&startIndex=$startIndex&pageSize=30").getJSONObject(
.getJSONObject("episodeList") "episodeList",
.getJSONArray("episode") ).getJSONArray("episode").toJSONList()
.toJSONList()
} }
}.awaitAll().flatten() }.awaitAll().flatten()
@ -145,10 +114,11 @@ internal abstract class WebtoonsParser(
uploadDate = jo.getLong("registerYmdt"), uploadDate = jo.getLong("registerYmdt"),
branch = null, branch = null,
scanlator = null, scanlator = null,
source = source source = source,
) )
}.sortedBy(MangaChapter::number) }.sortedBy(MangaChapter::number)
} }
private fun JSONArray.toJSONList(): List<JSONObject> { private fun JSONArray.toJSONList(): List<JSONObject> {
val list = mutableListOf<JSONObject>() val list = mutableListOf<JSONObject>()
for (i in 0 until length()) { for (i in 0 until length()) {
@ -156,31 +126,36 @@ internal abstract class WebtoonsParser(
} }
return list return list
} }
override suspend fun getDetails(manga: Manga): Manga = coroutineScope { override suspend fun getDetails(manga: Manga): Manga = coroutineScope {
val titleNo = manga.url.toLong() val titleNo = manga.url.toLong()
val chaptersDeferred = async { fetchEpisodes(titleNo) } val chaptersDeferred = async { fetchEpisodes(titleNo) }
val chapters = chaptersDeferred.await() val chapters = chaptersDeferred.await()
makeRequest("/lineWebtoon/webtoon/titleInfo.json?titleNo=${titleNo}&anyServiceStatus=false").getJSONObject("titleInfo") makeRequest("/lineWebtoon/webtoon/titleInfo.json?titleNo=${titleNo}&anyServiceStatus=false").getJSONObject("titleInfo")
.let { jo -> .let { jo ->
Manga( MangaWebtoon(
id = generateUid(titleNo), Manga(
title = jo.getString("title"), id = generateUid(titleNo),
altTitle = null, title = jo.getString("title"),
url = "$titleNo", altTitle = null,
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=${titleNo}", url = "$titleNo",
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f, publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=${titleNo}",
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource), rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain), isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
largeCoverUrl = jo.getStringOrNull("thumbnailVertical")?.toAbsoluteUrl(staticDomain), coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
tags = setOf(parseTag(jo.getJSONObject("genreInfo"))), largeCoverUrl = jo.getStringOrNull("thumbnailVertical")?.toAbsoluteUrl(staticDomain),
author = jo.getStringOrNull("writingAuthorName"), tags = setOf(parseTag(jo.getJSONObject("genreInfo"))),
description = jo.getString("synopsis"), author = jo.getStringOrNull("writingAuthorName"),
// I don't think the API provides this info, description = jo.getString("synopsis"),
state = null, // I don't think the API provides this info,
state = null,
chapters = chapters,
source = source,
),
date = jo.getLong("lastEpisodeRegisterYmdt"), date = jo.getLong("lastEpisodeRegisterYmdt"),
chapters = chapters, readCount = jo.getLong("readCount"),
source = source, //likeCount = jo.getLong("likeitCount")
) ).manga
} }
} }
@ -193,23 +168,25 @@ internal abstract class WebtoonsParser(
makeRequest("/lineWebtoon/webtoon/titleList.json?").getJSONObject("titleList").getJSONArray("titles") makeRequest("/lineWebtoon/webtoon/titleList.json?").getJSONObject("titleList").getJSONArray("titles")
.mapJSON { jo -> .mapJSON { jo ->
val titleNo = jo.getLong("titleNo") val titleNo = jo.getLong("titleNo")
Manga( MangaWebtoon(
id = generateUid(titleNo), Manga(
url = titleNo.toString(), id = generateUid(titleNo),
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo", url = titleNo.toString(),
title = jo.getString("title"), publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo",
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain), title = jo.getString("title"),
altTitle = null, coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
author = jo.getStringOrNull("writingAuthorName"), altTitle = null,
isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource), author = jo.getStringOrNull("writingAuthorName"),
rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f, isNsfw = jo.getBooleanOrDefault("ageGradeNotice", isNsfwSource),
tags = setOfNotNull(allGenreCache.get()[jo.getString("representGenre")]), rating = jo.getFloatOrDefault("starScoreAverage", -10f) / 10f,
description = jo.getString("synopsis"), tags = setOfNotNull(allGenreCache.get()[jo.getString("representGenre")]),
state = null, description = jo.getString("synopsis"),
source = source, state = null,
source = source,
),
date = jo.getLong("lastEpisodeRegisterYmdt"), date = jo.getLong("lastEpisodeRegisterYmdt"),
readCount = jo.getLong("readCount"), readCount = jo.getLong("readCount"),
likeCount = jo.getLong("likeitCount"), //likeCount = jo.getLong("likeitCount"),
) )
} }
} }
@ -218,7 +195,7 @@ internal abstract class WebtoonsParser(
return allGenreCache.get() return allGenreCache.get()
} }
private suspend fun getAllTitleList(): List<Manga> { private suspend fun getAllTitleList(): List<MangaWebtoon> {
return allTitleCache.get() return allTitleCache.get()
} }
@ -230,21 +207,26 @@ internal abstract class WebtoonsParser(
makeRequest("/lineWebtoon/webtoon/searchWebtoon?query=${filter.query.urlEncoded()}").getJSONObject("webtoonSearch") makeRequest("/lineWebtoon/webtoon/searchWebtoon?query=${filter.query.urlEncoded()}").getJSONObject("webtoonSearch")
.getJSONArray("titleList").mapJSON { jo -> .getJSONArray("titleList").mapJSON { jo ->
val titleNo = jo.getLong("titleNo") val titleNo = jo.getLong("titleNo")
Manga( MangaWebtoon(
id = generateUid(titleNo), Manga(
title = jo.getString("title"), id = generateUid(titleNo),
altTitle = null, title = jo.getString("title"),
url = titleNo.toString(), altTitle = null,
publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo", url = titleNo.toString(),
rating = RATING_UNKNOWN, publicUrl = "https://$domain/$languageCode/originals/a/list?title_no=$titleNo",
isNsfw = isNsfwSource, rating = RATING_UNKNOWN,
coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain), isNsfw = isNsfwSource,
largeCoverUrl = null, coverUrl = jo.getString("thumbnail").toAbsoluteUrl(staticDomain),
tags = emptySet(), largeCoverUrl = null,
author = jo.getStringOrNull("writingAuthorName"), tags = emptySet(),
description = null, author = jo.getStringOrNull("writingAuthorName"),
state = null, description = null,
source = source, state = null,
source = source,
),
date = jo.getLong("lastEpisodeRegisterYmdt"),
readCount = jo.getLong("readCount"),
//likeCount = jo.getLong("likeitCount"),
) )
} }
} }
@ -258,13 +240,13 @@ internal abstract class WebtoonsParser(
val sortedResult = when (filter.sortOrder) { val sortedResult = when (filter.sortOrder) {
SortOrder.UPDATED -> result.sortedBy { it.date } SortOrder.UPDATED -> result.sortedBy { it.date }
SortOrder.POPULARITY -> result.sortedByDescending { it.readCount } SortOrder.POPULARITY -> result.sortedByDescending { it.readCount }
SortOrder.RATING -> result.sortedByDescending { it.rating } SortOrder.RATING -> result.sortedByDescending { it.manga.rating }
//SortOrder.LIKE -> result.sortedBy { it.likeCount } //SortOrder.LIKE -> result.sortedBy { it.likeitCount }
else -> throw IllegalArgumentException("Unsupported sort order: ${filter.sortOrder}") else -> throw IllegalArgumentException("Unsupported sort order: ${filter.sortOrder}")
} }
if (genre != "ALL") { if (genre != "ALL") {
sortedResult.filter { it.tags.contains(genres[genre]) } sortedResult.filter { it.manga.tags.contains(genres[genre]) }
} else { } else {
sortedResult sortedResult
} }
@ -273,7 +255,7 @@ internal abstract class WebtoonsParser(
else -> getAllTitleList() else -> getAllTitleList()
} }
return webtoons.subList(offset, (offset + 20).coerceAtMost(webtoons.size)) return webtoons.map { it.manga }.subList(offset, (offset + 20).coerceAtMost(webtoons.size))
} }
override suspend fun getPages(chapter: MangaChapter): List<MangaPage> { override suspend fun getPages(chapter: MangaChapter): List<MangaPage> {
@ -281,13 +263,13 @@ internal abstract class WebtoonsParser(
return makeRequest("/lineWebtoon/webtoon/episodeInfo.json?v=4&titleNo=$titleNo&episodeNo=$episodeNo").getJSONObject( return makeRequest("/lineWebtoon/webtoon/episodeInfo.json?v=4&titleNo=$titleNo&episodeNo=$episodeNo").getJSONObject(
"episodeInfo", "episodeInfo",
).getJSONArray("imageInfo").mapJSONIndexed { i, jo -> ).getJSONArray("imageInfo").mapJSONIndexed { i, jo ->
MangaPage( MangaPage(
id = generateUid("$titleNo-$episodeNo-$i"), id = generateUid("$titleNo-$episodeNo-$i"),
url = jo.getString("url"), url = jo.getString("url"),
preview = null, preview = null,
source = source, source = source,
) )
} }
} }
private fun parseTag(jo: JSONObject): MangaTag { private fun parseTag(jo: JSONObject): MangaTag {
@ -349,8 +331,6 @@ internal abstract class WebtoonsParser(
@MangaSourceParser("WEBTOONS_DE", "Webtoons German", "de", type = ContentType.MANGA) @MangaSourceParser("WEBTOONS_DE", "Webtoons German", "de", type = ContentType.MANGA)
class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.WEBTOONS_DE) class German(context: MangaLoaderContext) : LineWebtoonsParser(context, MangaSource.WEBTOONS_DE)
private inner class WebtoonsUrlSigner(private val secret: String) { private inner class WebtoonsUrlSigner(private val secret: String) {
private val mac = Mac.getInstance("HmacSHA1").apply { private val mac = Mac.getInstance("HmacSHA1").apply {
@ -373,4 +353,10 @@ internal abstract class WebtoonsParser(
// .addEncodedQueryParameter("md", digest.urlEncoded()) // .addEncodedQueryParameter("md", digest.urlEncoded())
} }
} }
private inner class MangaWebtoon(
val manga: Manga,
@JvmField val date: Long? = null,
@JvmField val readCount: Long? = null,
)
} }

@ -20,7 +20,7 @@ internal class TeamXNovel(context: MangaLoaderContext) : PagedMangaParser(contex
override val availableStates: Set<MangaState> = override val availableStates: Set<MangaState> =
EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED) EnumSet.of(MangaState.ONGOING, MangaState.FINISHED, MangaState.ABANDONED)
override val configKeyDomain = ConfigKey.Domain("teamxnovel.com") override val configKeyDomain = ConfigKey.Domain("team11x11.com")
override val isMultipleTagsSupported = false override val isMultipleTagsSupported = false
override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> { override suspend fun getListPage(page: Int, filter: MangaListFilter?): List<Manga> {

Loading…
Cancel
Save