Fix broken thumbnails after expiration time at MangaPlus. (#3974)
This commit is contained in:
parent
064710af68
commit
8fdfba373f
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'MANGA Plus by SHUEISHA'
|
extName = 'MANGA Plus by SHUEISHA'
|
||||||
pkgNameSuffix = 'all.mangaplus'
|
pkgNameSuffix = 'all.mangaplus'
|
||||||
extClass = '.MangaPlusFactory'
|
extClass = '.MangaPlusFactory'
|
||||||
extVersionCode = 10
|
extVersionCode = 11
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,6 +54,7 @@ abstract class MangaPlus(
|
||||||
|
|
||||||
override val client: OkHttpClient = network.client.newBuilder()
|
override val client: OkHttpClient = network.client.newBuilder()
|
||||||
.addInterceptor { imageIntercept(it) }
|
.addInterceptor { imageIntercept(it) }
|
||||||
|
.addInterceptor { thumbnailIntercept(it) }
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
private val protobufJs: String by lazy {
|
private val protobufJs: String by lazy {
|
||||||
|
@ -72,6 +73,8 @@ abstract class MangaPlus(
|
||||||
private val splitImages: String
|
private val splitImages: String
|
||||||
get() = if (preferences.getBoolean("${SPLIT_PREF_KEY}_$lang", SPLIT_PREF_DEFAULT_VALUE)) "yes" else "no"
|
get() = if (preferences.getBoolean("${SPLIT_PREF_KEY}_$lang", SPLIT_PREF_DEFAULT_VALUE)) "yes" else "no"
|
||||||
|
|
||||||
|
private var titleList: List<Title>? = null
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int): Request {
|
override fun popularMangaRequest(page: Int): Request {
|
||||||
val newHeaders = headersBuilder()
|
val newHeaders = headersBuilder()
|
||||||
.set("Referer", "$baseUrl/manga_list/hot")
|
.set("Referer", "$baseUrl/manga_list/hot")
|
||||||
|
@ -86,15 +89,16 @@ abstract class MangaPlus(
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
|
||||||
val mangas = result.success.titleRankingView!!.titles
|
titleList = result.success.titleRankingView!!.titles
|
||||||
.filter { it.language == langCode }
|
.filter { it.language == langCode }
|
||||||
.map {
|
|
||||||
SManga.create().apply {
|
val mangas = titleList!!.map {
|
||||||
title = it.name
|
SManga.create().apply {
|
||||||
thumbnail_url = it.portraitImageUrl.toWeservUrl()
|
title = it.name
|
||||||
url = "#/titles/${it.titleId}"
|
thumbnail_url = it.portraitImageUrl
|
||||||
}
|
url = "#/titles/${it.titleId}"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MangasPage(mangas, false)
|
return MangasPage(mangas, false)
|
||||||
}
|
}
|
||||||
|
@ -113,6 +117,14 @@ abstract class MangaPlus(
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
|
||||||
|
// Fetch all titles to get newer thumbnail urls at the interceptor.
|
||||||
|
val popularResponse = client.newCall(popularMangaRequest(1)).execute().asProto()
|
||||||
|
|
||||||
|
if (popularResponse.success != null) {
|
||||||
|
titleList = popularResponse.success.titleRankingView!!.titles
|
||||||
|
.filter { it.language == langCode }
|
||||||
|
}
|
||||||
|
|
||||||
val mangas = result.success.webHomeView!!.groups
|
val mangas = result.success.webHomeView!!.groups
|
||||||
.flatMap { it.titles }
|
.flatMap { it.titles }
|
||||||
.mapNotNull { it.title }
|
.mapNotNull { it.title }
|
||||||
|
@ -120,7 +132,7 @@ abstract class MangaPlus(
|
||||||
.map {
|
.map {
|
||||||
SManga.create().apply {
|
SManga.create().apply {
|
||||||
title = it.name
|
title = it.name
|
||||||
thumbnail_url = it.portraitImageUrl.toWeservUrl()
|
thumbnail_url = it.portraitImageUrl
|
||||||
url = "#/titles/${it.titleId}"
|
url = "#/titles/${it.titleId}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,15 +160,16 @@ abstract class MangaPlus(
|
||||||
if (result.success == null)
|
if (result.success == null)
|
||||||
throw Exception(result.error!!.langPopup.body)
|
throw Exception(result.error!!.langPopup.body)
|
||||||
|
|
||||||
val mangas = result.success.allTitlesView!!.titles
|
titleList = result.success.allTitlesView!!.titles
|
||||||
.filter { it.language == langCode }
|
.filter { it.language == langCode }
|
||||||
.map {
|
|
||||||
SManga.create().apply {
|
val mangas = titleList!!.map {
|
||||||
title = it.name
|
SManga.create().apply {
|
||||||
thumbnail_url = it.portraitImageUrl.toWeservUrl()
|
title = it.name
|
||||||
url = "#/titles/${it.titleId}"
|
thumbnail_url = it.portraitImageUrl
|
||||||
}
|
url = "#/titles/${it.titleId}"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return MangasPage(mangas, false)
|
return MangasPage(mangas, false)
|
||||||
}
|
}
|
||||||
|
@ -200,7 +213,7 @@ abstract class MangaPlus(
|
||||||
artist = author
|
artist = author
|
||||||
description = details.overview + "\n\n" + details.viewingPeriodDescription
|
description = details.overview + "\n\n" + details.viewingPeriodDescription
|
||||||
status = if (isCompleted) SManga.COMPLETED else SManga.ONGOING
|
status = if (isCompleted) SManga.COMPLETED else SManga.ONGOING
|
||||||
thumbnail_url = title.portraitImageUrl.toWeservUrl()
|
thumbnail_url = title.portraitImageUrl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -385,12 +398,26 @@ abstract class MangaPlus(
|
||||||
return ByteArray(content.size) { pos -> content[pos].toByte() }
|
return ByteArray(content.size) { pos -> content[pos].toByte() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.toWeservUrl(): String {
|
private fun thumbnailIntercept(chain: Interceptor.Chain): Response {
|
||||||
val imageUrl = substringBefore("&duration")
|
val request = chain.request()
|
||||||
|
val response = chain.proceed(request)
|
||||||
|
|
||||||
return HttpUrl.parse(IMAGES_WESERV_URL)!!.newBuilder()
|
// Check if it is 404 to maintain compatibility when the extension used Weserv.
|
||||||
.addEncodedQueryParameter("url", imageUrl)
|
val isBadCode = (response.code() == 401 || response.code() == 404)
|
||||||
.toString()
|
|
||||||
|
if (isBadCode && request.url().toString().contains(TITLE_THUMBNAIL_PATH)) {
|
||||||
|
val titleId = request.url().toString()
|
||||||
|
.substringBefore("/$TITLE_THUMBNAIL_PATH")
|
||||||
|
.substringAfterLast("/")
|
||||||
|
.toInt()
|
||||||
|
val title = titleList?.find { it.titleId == titleId } ?: return response
|
||||||
|
|
||||||
|
response.close()
|
||||||
|
val thumbnailRequest = GET(title.portraitImageUrl, request.headers())
|
||||||
|
return chain.proceed(thumbnailRequest)
|
||||||
|
}
|
||||||
|
|
||||||
|
return response
|
||||||
}
|
}
|
||||||
|
|
||||||
private val ErrorResult.langPopup: Popup
|
private val ErrorResult.langPopup: Popup
|
||||||
|
@ -429,7 +456,6 @@ abstract class MangaPlus(
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val API_URL = "https://jumpg-webapi.tokyo-cdn.com/api"
|
private const val API_URL = "https://jumpg-webapi.tokyo-cdn.com/api"
|
||||||
private const val IMAGES_WESERV_URL = "https://images.weserv.nl"
|
|
||||||
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36"
|
private const val USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36"
|
||||||
|
|
||||||
private val HEX_GROUP = "(.{1,2})".toRegex()
|
private val HEX_GROUP = "(.{1,2})".toRegex()
|
||||||
|
@ -448,5 +474,7 @@ abstract class MangaPlus(
|
||||||
private const val SPLIT_PREF_DEFAULT_VALUE = true
|
private const val SPLIT_PREF_DEFAULT_VALUE = true
|
||||||
|
|
||||||
private val COMPLETE_REGEX = "completado|complete".toRegex()
|
private val COMPLETE_REGEX = "completado|complete".toRegex()
|
||||||
|
|
||||||
|
private const val TITLE_THUMBNAIL_PATH = "title_thumbnail_portrait_list"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue