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:
Alessandro Jean 2023-10-04 13:58:39 -03:00 committed by GitHub
parent 477ef241b3
commit 42a3e238fe
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 168 additions and 33 deletions

View File

@ -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?

View File

@ -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.

View File

@ -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.

View File

@ -6,7 +6,7 @@ ext {
extName = 'MANGA Plus by SHUEISHA'
pkgNameSuffix = 'all.mangaplus'
extClass = '.MangaPlusFactory'
extVersionCode = 44
extVersionCode = 45
}
dependencies {

View File

@ -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.

View File

@ -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,
) {