Update MangaPlus to handle the subscription changes (#18367)
* Update MangaPlus to handle the subscription changes. * Update the FAQ for MangaPlus. * Remove unused import.
This commit is contained in:
parent
477ef241b3
commit
42a3e238fe
|
@ -9,10 +9,10 @@ Table of Content
|
|||
|
||||
### Why chapters are missing in some titles?
|
||||
|
||||
MANGA Plus does not host all chapters due to their licensing politics. The website
|
||||
MANGA Plus does not host all chapters for free due to their licensing politics. The website
|
||||
is designed to let the users read the weekly/monthly official simulreleases. If you want
|
||||
to read old chapters of a series that does not have the complete list, you need to find
|
||||
another sources.
|
||||
to read old chapters of a series that does not have the complete list, you need subscribe
|
||||
to one of their paid plans and read directly in their app instead.
|
||||
|
||||
### Why disabling split pages setting does not work?
|
||||
|
||||
|
|
|
@ -4,7 +4,21 @@ image_quality_high=High
|
|||
image_quality_low=Low
|
||||
image_quality_medium=Medium
|
||||
not_available=Title not available in this language.
|
||||
rating=Rating: %s
|
||||
rating_all_ages=All ages
|
||||
rating_mature=Mature
|
||||
rating_teen=Teen
|
||||
rating_teen_plus=Teen Plus
|
||||
schedule=Schedule: %s
|
||||
schedule_bimonthly=Bimonthly
|
||||
schedule_biweekly=Biweekly
|
||||
schedule_everyday=Everyday
|
||||
schedule_monthly=Monthly
|
||||
schedule_other=Other
|
||||
schedule_trimonthly=Trimonthly
|
||||
schedule_weekly=Weekly
|
||||
serialization=Serialization: %s
|
||||
split_double_pages=Split double pages
|
||||
split_double_pages_summary=Only a few titles supports disabling this setting.
|
||||
title_removed=This title was removed from the MANGA Plus catalogue.
|
||||
unknown_error=An unknown error happened.
|
||||
unknown_error=An unknown error happened.
|
||||
|
|
|
@ -4,7 +4,21 @@ image_quality_high=Alta
|
|||
image_quality_low=Baixa
|
||||
image_quality_medium=Média
|
||||
not_available=Título não disponível neste idioma.
|
||||
rating=Classificação: %s
|
||||
rating_all_ages=Todas as idades
|
||||
rating_mature=+18
|
||||
rating_teen=+10
|
||||
rating_teen_plus=+16
|
||||
schedule=Periodicidade: %s
|
||||
schedule_bimonthly=Bimestral
|
||||
schedule_biweekly=Bisemanal
|
||||
schedule_everyday=Diário
|
||||
schedule_monthly=Mensal
|
||||
schedule_other=Outros
|
||||
schedule_trimonthly=Trimestral
|
||||
schedule_weekly=Semanal
|
||||
serialization=Serialização: %s
|
||||
split_double_pages=Dividir as páginas duplas
|
||||
split_double_pages_summary=Somente poucos títulos suportam a desativação desta configuração.
|
||||
title_removed=Este título foi removido do catálogo do MANGA Plus.
|
||||
unknown_error=Um erro desconhecido ocorreu.
|
||||
unknown_error=Um erro desconhecido ocorreu.
|
||||
|
|
|
@ -6,7 +6,7 @@ ext {
|
|||
extName = 'MANGA Plus by SHUEISHA'
|
||||
pkgNameSuffix = 'all.mangaplus'
|
||||
extClass = '.MangaPlusFactory'
|
||||
extVersionCode = 44
|
||||
extVersionCode = 45
|
||||
}
|
||||
|
||||
dependencies {
|
||||
|
|
|
@ -186,7 +186,7 @@ class MangaPlus(
|
|||
|
||||
titleResult.success.titleDetailView!!
|
||||
.takeIf { it.title.language == langCode }
|
||||
?.toSManga()
|
||||
?.toSManga(intl)
|
||||
}
|
||||
|
||||
return MangasPage(listOfNotNull(title), hasNextPage = false)
|
||||
|
@ -220,7 +220,7 @@ class MangaPlus(
|
|||
.set("Referer", "$baseUrl/titles/$titleId")
|
||||
.build()
|
||||
|
||||
return GET("$API_URL/title_detail?title_id=$titleId&format=json", newHeaders)
|
||||
return GET("$API_URL/title_detailV3?title_id=$titleId&format=json", newHeaders)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
|
@ -240,7 +240,7 @@ class MangaPlus(
|
|||
.takeIf { it.title.language == langCode }
|
||||
?: throw Exception(intl["not_available"])
|
||||
|
||||
return titleDetails.toSManga()
|
||||
return titleDetails.toSManga(intl)
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request = mangaDetailsRequest(manga.url)
|
||||
|
@ -260,11 +260,10 @@ class MangaPlus(
|
|||
|
||||
val titleDetailView = result.success.titleDetailView!!
|
||||
|
||||
val chapters = titleDetailView.firstChapterList + titleDetailView.lastChapterList
|
||||
|
||||
return chapters.reversed()
|
||||
return titleDetailView.chapterList
|
||||
.filterNot(Chapter::isExpired)
|
||||
.map(Chapter::toSChapter)
|
||||
.reversed()
|
||||
}
|
||||
|
||||
// Remove the '#' and map to the new url format used in website.
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package eu.kanade.tachiyomi.extension.all.mangaplus
|
||||
|
||||
import eu.kanade.tachiyomi.lib.i18n.Intl
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import kotlinx.serialization.SerialName
|
||||
|
@ -57,51 +58,83 @@ data class TitleDetailView(
|
|||
val title: Title,
|
||||
val titleImageUrl: String,
|
||||
val overview: String? = null,
|
||||
val backgroundImageUrl: String,
|
||||
val nextTimeStamp: Int = 0,
|
||||
val viewingPeriodDescription: String = "",
|
||||
val nonAppearanceInfo: String = "",
|
||||
val firstChapterList: List<Chapter> = emptyList(),
|
||||
val lastChapterList: List<Chapter> = emptyList(),
|
||||
val chapterListGroup: List<ChapterListGroup> = emptyList(),
|
||||
val isSimulReleased: Boolean = false,
|
||||
val rating: Rating = Rating.ALL_AGES,
|
||||
val chaptersDescending: Boolean = true,
|
||||
val titleLabels: TitleLabels,
|
||||
val label: Label? = Label(LabelCode.WEEKLY_SHOUNEN_JUMP),
|
||||
) {
|
||||
|
||||
val chapterList: List<Chapter> by lazy {
|
||||
chapterListGroup.flatMap { it.firstChapterList + it.lastChapterList }
|
||||
}
|
||||
|
||||
private val isWebtoon: Boolean
|
||||
get() = firstChapterList.all(Chapter::isVerticalOnly) &&
|
||||
lastChapterList.all(Chapter::isVerticalOnly)
|
||||
get() = chapterList.isNotEmpty() && chapterList.all(Chapter::isVerticalOnly)
|
||||
|
||||
private val isOneShot: Boolean
|
||||
get() = chapterCount == 1 && firstChapterList.firstOrNull()
|
||||
get() = chapterList.size == 1 && chapterList.firstOrNull()
|
||||
?.name?.equals("one-shot", true) == true
|
||||
|
||||
private val chapterCount: Int
|
||||
get() = firstChapterList.size + lastChapterList.size
|
||||
|
||||
private val isReEdition: Boolean
|
||||
get() = viewingPeriodDescription.contains(REEDITION_REGEX)
|
||||
|
||||
private val isCompleted: Boolean
|
||||
get() = nonAppearanceInfo.contains(COMPLETED_REGEX) || isOneShot
|
||||
get() = nonAppearanceInfo.contains(COMPLETED_REGEX) || isOneShot ||
|
||||
titleLabels.releaseSchedule == ReleaseSchedule.COMPLETED ||
|
||||
titleLabels.releaseSchedule == ReleaseSchedule.DISABLED
|
||||
|
||||
private val isSimulpub: Boolean
|
||||
get() = isSimulReleased || titleLabels.isSimulpub
|
||||
|
||||
private val isOnHiatus: Boolean
|
||||
get() = nonAppearanceInfo.contains(HIATUS_REGEX)
|
||||
|
||||
private val genres: List<String>
|
||||
get() = listOfNotNull(
|
||||
"Simulrelease".takeIf { isSimulReleased && !isReEdition && !isOneShot },
|
||||
"One-shot".takeIf { isOneShot },
|
||||
"Re-edition".takeIf { isReEdition },
|
||||
"Webtoon".takeIf { isWebtoon },
|
||||
)
|
||||
private fun createGenres(intl: Intl): List<String> = buildList {
|
||||
if (isSimulpub && !isReEdition && !isOneShot && !isCompleted) {
|
||||
add("Simulrelease")
|
||||
}
|
||||
|
||||
fun toSManga(): SManga = title.toSManga().apply {
|
||||
description = (overview.orEmpty() + "\n\n" + viewingPeriodDescription).trim()
|
||||
if (isOneShot) {
|
||||
add("One-shot")
|
||||
}
|
||||
|
||||
if (isReEdition) {
|
||||
add("Re-edition")
|
||||
}
|
||||
|
||||
if (isWebtoon) {
|
||||
add("Webtoon")
|
||||
}
|
||||
|
||||
if (label?.magazine != null) {
|
||||
add(intl.format("serialization", label.magazine))
|
||||
}
|
||||
|
||||
if (!isCompleted) {
|
||||
val scheduleLabel = intl["schedule_" + titleLabels.releaseSchedule.toString().lowercase()]
|
||||
add(intl.format("schedule", scheduleLabel))
|
||||
}
|
||||
|
||||
val ratingLabel = intl["rating_" + rating.toString().lowercase()]
|
||||
add(intl.format("rating", ratingLabel))
|
||||
}
|
||||
|
||||
private val viewingInformation: String?
|
||||
get() = viewingPeriodDescription.takeIf { !isCompleted }
|
||||
|
||||
fun toSManga(intl: Intl): SManga = title.toSManga().apply {
|
||||
description = "${overview.orEmpty()}\n\n${viewingInformation.orEmpty()}".trim()
|
||||
status = when {
|
||||
isCompleted -> SManga.COMPLETED
|
||||
isOnHiatus -> SManga.ON_HIATUS
|
||||
else -> SManga.ONGOING
|
||||
}
|
||||
genre = genres.joinToString()
|
||||
genre = createGenres(intl).joinToString()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
@ -111,6 +144,82 @@ data class TitleDetailView(
|
|||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class TitleLabels(
|
||||
val releaseSchedule: ReleaseSchedule = ReleaseSchedule.DISABLED,
|
||||
val isSimulpub: Boolean = false,
|
||||
)
|
||||
|
||||
enum class ReleaseSchedule {
|
||||
DISABLED,
|
||||
EVERYDAY,
|
||||
WEEKLY,
|
||||
BIWEEKLY,
|
||||
MONTHLY,
|
||||
BIMONTHLY,
|
||||
TRIMONTHLY,
|
||||
OTHER,
|
||||
COMPLETED,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
enum class Rating {
|
||||
@SerialName("ALLAGE")
|
||||
ALL_AGES,
|
||||
TEEN,
|
||||
|
||||
@SerialName("TEENPLUS")
|
||||
TEEN_PLUS,
|
||||
MATURE,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class Label(val label: LabelCode? = LabelCode.WEEKLY_SHOUNEN_JUMP) {
|
||||
val magazine: String?
|
||||
get() = when (label) {
|
||||
LabelCode.WEEKLY_SHOUNEN_JUMP -> "Weekly Shounen Jump"
|
||||
LabelCode.JUMP_SQUARE -> "Jump SQ."
|
||||
LabelCode.V_JUMP -> "V Jump"
|
||||
LabelCode.WEEKLY_YOUNG_JUMP -> "Weekly Young Jump"
|
||||
LabelCode.TONARI_NO_YOUNG_JUMP -> "Tonari no Young Jump"
|
||||
LabelCode.SHOUNEN_JUMP_PLUS -> "Shounen Jump+"
|
||||
LabelCode.REVIVAL -> "Revival"
|
||||
LabelCode.MANGA_PLUS_CREATORS -> "MANGA Plus Creators"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
enum class LabelCode {
|
||||
@SerialName("WJ")
|
||||
WEEKLY_SHOUNEN_JUMP,
|
||||
|
||||
@SerialName("SQ")
|
||||
JUMP_SQUARE,
|
||||
|
||||
@SerialName("VJ")
|
||||
V_JUMP,
|
||||
|
||||
@SerialName("YJ")
|
||||
WEEKLY_YOUNG_JUMP,
|
||||
|
||||
@SerialName("TYJ")
|
||||
TONARI_NO_YOUNG_JUMP,
|
||||
|
||||
@SerialName("J_PLUS")
|
||||
SHOUNEN_JUMP_PLUS,
|
||||
REVIVAL,
|
||||
|
||||
@SerialName("CREATORS")
|
||||
MANGA_PLUS_CREATORS,
|
||||
}
|
||||
|
||||
@Serializable
|
||||
data class ChapterListGroup(
|
||||
val firstChapterList: List<Chapter> = emptyList(),
|
||||
val lastChapterList: List<Chapter> = emptyList(),
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class MangaViewer(
|
||||
val pages: List<MangaPlusPage> = emptyList(),
|
||||
|
@ -124,7 +233,6 @@ data class Title(
|
|||
val name: String,
|
||||
val author: String? = null,
|
||||
val portraitImageUrl: String,
|
||||
val landscapeImageUrl: String,
|
||||
val viewCount: Int = 0,
|
||||
val language: Language? = Language.ENGLISH,
|
||||
) {
|
||||
|
|
Loading…
Reference in New Issue