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 {
|
ext {
|
||||||
extName = 'Webtoons.com'
|
extName = 'Webtoons.com'
|
||||||
extClass = '.WebtoonsFactory'
|
extClass = '.WebtoonsFactory'
|
||||||
extVersionCode = 49
|
extVersionCode = 50
|
||||||
isNsfw = false
|
isNsfw = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,7 +20,10 @@ class Episode(
|
|||||||
val viewerLink: String,
|
val viewerLink: String,
|
||||||
val exposureDateMillis: Long,
|
val exposureDateMillis: Long,
|
||||||
val hasBgm: Boolean = false,
|
val hasBgm: Boolean = false,
|
||||||
)
|
) {
|
||||||
|
var chapterNumber = -1f
|
||||||
|
var seasonNumber = 1
|
||||||
|
}
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
class MotionToonResponse(
|
class MotionToonResponse(
|
||||||
|
@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.lib.textinterceptor.TextInterceptor
|
|||||||
import eu.kanade.tachiyomi.lib.textinterceptor.TextInterceptorHelper
|
import eu.kanade.tachiyomi.lib.textinterceptor.TextInterceptorHelper
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
import eu.kanade.tachiyomi.network.asObservableSuccess
|
||||||
|
import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.model.FilterList
|
import eu.kanade.tachiyomi.source.model.FilterList
|
||||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||||
@ -65,6 +66,7 @@ open class Webtoons(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.addInterceptor(TextInterceptor())
|
.addInterceptor(TextInterceptor())
|
||||||
|
.rateLimitHost(mobileUrl.toHttpUrl(), 1)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private val preferences by getPreferencesLazy()
|
private val preferences by getPreferencesLazy()
|
||||||
@ -276,10 +278,60 @@ open class Webtoons(
|
|||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val result = response.parseAs<EpisodeListResponse>()
|
val result = response.parseAs<EpisodeListResponse>()
|
||||||
|
|
||||||
val recognized: MutableList<Int> = mutableListOf()
|
var recognized = 0
|
||||||
val unrecognized: MutableList<Int> = mutableListOf()
|
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 {
|
SChapter.create().apply {
|
||||||
url = episode.viewerLink
|
url = episode.viewerLink
|
||||||
name = Parser.unescapeEntities(episode.episodeTitle, false)
|
name = Parser.unescapeEntities(episode.episodeTitle, false)
|
||||||
@ -287,41 +339,16 @@ open class Webtoons(
|
|||||||
name += " ♫"
|
name += " ♫"
|
||||||
}
|
}
|
||||||
date_upload = episode.exposureDateMillis
|
date_upload = episode.exposureDateMillis
|
||||||
chapter_number = episodeNoRegex
|
chapter_number = episode.chapterNumber
|
||||||
.find(episode.episodeTitle)
|
|
||||||
?.groupValues
|
|
||||||
?.get(4)
|
|
||||||
?.toFloat()
|
|
||||||
?: -1f
|
|
||||||
if (chapter_number == -1f) {
|
|
||||||
unrecognized += index
|
|
||||||
} else {
|
|
||||||
recognized += index
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}.asReversed()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unrecognized.size > recognized.size) {
|
// season number - 4 capture group
|
||||||
chapters.onEachIndexed { index, chapter ->
|
// possible bonus/mini/special episode - 6 capture group
|
||||||
chapter.chapter_number = (index + 1).toFloat()
|
// episode number - 11 capture group
|
||||||
}
|
|
||||||
} 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()
|
|
||||||
}
|
|
||||||
|
|
||||||
private val episodeNoRegex = Regex(
|
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,
|
RegexOption.IGNORE_CASE,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user