Webtoons.com: add rate limit & handle chapter count reset on new season (#9593)
* Webtoons: ratelimit chapters fetch api closes https://github.com/keiyoushi/extensions-source/issues/9570 * handle season number reset closes https://github.com/keiyoushi/extensions-source/issues/9495 * edge case bug * bump
This commit is contained in:
parent
827e91d2c6
commit
d773d2692b
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Webtoons.com'
|
||||
extClass = '.WebtoonsFactory'
|
||||
extVersionCode = 49
|
||||
extVersionCode = 50
|
||||
isNsfw = false
|
||||
}
|
||||
|
||||
|
@ -20,7 +20,10 @@ class Episode(
|
||||
val viewerLink: String,
|
||||
val exposureDateMillis: Long,
|
||||
val hasBgm: Boolean = false,
|
||||
)
|
||||
) {
|
||||
var chapterNumber = -1f
|
||||
var seasonNumber = 1
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class MotionToonResponse(
|
||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.lib.textinterceptor.TextInterceptor
|
||||
import eu.kanade.tachiyomi.lib.textinterceptor.TextInterceptorHelper
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
@ -65,6 +66,7 @@ open class Webtoons(
|
||||
}
|
||||
}
|
||||
.addInterceptor(TextInterceptor())
|
||||
.rateLimitHost(mobileUrl.toHttpUrl(), 1)
|
||||
.build()
|
||||
|
||||
private val preferences by getPreferencesLazy()
|
||||
@ -276,10 +278,60 @@ open class Webtoons(
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val result = response.parseAs<EpisodeListResponse>()
|
||||
|
||||
val recognized: MutableList<Int> = mutableListOf()
|
||||
val unrecognized: MutableList<Int> = mutableListOf()
|
||||
var recognized = 0
|
||||
var unrecognized = 0
|
||||
|
||||
val chapters = result.result.episodeList.mapIndexed { index, episode ->
|
||||
val chapters = result.result.episodeList.onEach { episode ->
|
||||
val match = episodeNoRegex
|
||||
.find(episode.episodeTitle)
|
||||
?.groupValues
|
||||
?.takeIf { it[6].isEmpty() } // skip mini/bonus episodes
|
||||
|
||||
episode.chapterNumber = match?.get(11)?.toFloat() ?: -1f
|
||||
episode.seasonNumber = match?.get(4)?.takeIf(String::isNotBlank)?.toInt() ?: 1
|
||||
|
||||
if (episode.chapterNumber == -1f) {
|
||||
unrecognized++
|
||||
} else {
|
||||
recognized++
|
||||
}
|
||||
}
|
||||
|
||||
if (unrecognized > recognized) {
|
||||
chapters.onEachIndexed { index, chapter ->
|
||||
chapter.chapterNumber = (index + 1).toFloat()
|
||||
}
|
||||
} else {
|
||||
var maxChapterNumber = 0f
|
||||
var currentSeason = 1
|
||||
var seasonOffset = 0f
|
||||
|
||||
chapters.forEachIndexed { idx, chapter ->
|
||||
if (chapter.chapterNumber != -1f) {
|
||||
val originalNumber = chapter.chapterNumber
|
||||
|
||||
// Check if we've moved to a new season
|
||||
if (chapter.seasonNumber > currentSeason) {
|
||||
currentSeason = chapter.seasonNumber
|
||||
if (originalNumber <= maxChapterNumber) {
|
||||
seasonOffset = maxChapterNumber
|
||||
}
|
||||
}
|
||||
|
||||
chapter.chapterNumber = seasonOffset + originalNumber
|
||||
maxChapterNumber = maxOf(maxChapterNumber, chapter.chapterNumber)
|
||||
} else {
|
||||
val previous = chapters.getOrNull(idx - 1)
|
||||
if (previous == null) {
|
||||
chapter.chapterNumber = 0f
|
||||
} else {
|
||||
chapter.chapterNumber = previous.chapterNumber + 0.01f
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chapters.map { episode ->
|
||||
SChapter.create().apply {
|
||||
url = episode.viewerLink
|
||||
name = Parser.unescapeEntities(episode.episodeTitle, false)
|
||||
@ -287,41 +339,16 @@ open class Webtoons(
|
||||
name += " ♫"
|
||||
}
|
||||
date_upload = episode.exposureDateMillis
|
||||
chapter_number = episodeNoRegex
|
||||
.find(episode.episodeTitle)
|
||||
?.groupValues
|
||||
?.get(4)
|
||||
?.toFloat()
|
||||
?: -1f
|
||||
if (chapter_number == -1f) {
|
||||
unrecognized += index
|
||||
} else {
|
||||
recognized += index
|
||||
}
|
||||
chapter_number = episode.chapterNumber
|
||||
}
|
||||
}
|
||||
|
||||
if (unrecognized.size > recognized.size) {
|
||||
chapters.onEachIndexed { index, chapter ->
|
||||
chapter.chapter_number = (index + 1).toFloat()
|
||||
}
|
||||
} else {
|
||||
unrecognized.forEach { uIdx ->
|
||||
val chapter = chapters[uIdx]
|
||||
val previous = chapters.getOrNull(uIdx - 1)
|
||||
if (previous == null) {
|
||||
chapter.chapter_number = 0f
|
||||
} else {
|
||||
chapter.chapter_number = previous.chapter_number + 0.01f
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return chapters.asReversed()
|
||||
}.asReversed()
|
||||
}
|
||||
|
||||
// season number - 4 capture group
|
||||
// possible bonus/mini/special episode - 6 capture group
|
||||
// episode number - 11 capture group
|
||||
private val episodeNoRegex = Regex(
|
||||
"""(ep(isode)?|ch(apter)?)\s*\.?\s*(\d+(\.\d+)?)""",
|
||||
"""(?:(s(eason)?|part|vol(ume)?)\s*\.?\s*(\d+).*?)?(.*?(mini|bonus|special).*?)?(e(p(isode)?)?|ch(apter)?)\s*\.?\s*(\d+(\.\d+)?)""",
|
||||
RegexOption.IGNORE_CASE,
|
||||
)
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user