Mangadex: Use updated /at-home/server/ endpoint for pages (#10221)
* Move chapter images data to atHome Response Updates ChapterDto and AtHomeDto as per Deprecation notice * Use new atHome response to fetch chapter pages this commit does the following: - updates the Dtos as per deprecation notice - creates a call to `/at-home/server/` in `pageListRequest` - made sure to track of how old chapter token is as was previous practice - `pageListParse` no longer has the 204 response. Instead we get a 404 response (not sure about the 504 response for /at-home/server too but have to check again. If its not used now, then it could be removed - since `atHomeRequestUrl` was necessary for `getValidImageUrlForPage`, tried to fetch it from the response. As per their docs and our usecase, it should be fine hopefully Ref: https://square.github.io/okhttp/4.x/okhttp/okhttp3/-response/request/ - since /chapter/ no longer has `data` attribute, the additional check for external chapters was removed - tested on 0.12.3 (on Mi A2, running Android12): read few chapter/oneshots without issues * Increment mangadex.extVersionCode essentially a Christmas present from MD (for its servers :d) * remove redundant isSuccessful check essentially dead code since the check is done by `fetchPageList` before it calls `pageListParse`
This commit is contained in:
parent
4bce404938
commit
1f9be45238
|
@ -6,7 +6,7 @@ ext {
|
||||||
extName = 'MangaDex'
|
extName = 'MangaDex'
|
||||||
pkgNameSuffix = 'all.mangadex'
|
pkgNameSuffix = 'all.mangadex'
|
||||||
extClass = '.MangaDexFactory'
|
extClass = '.MangaDexFactory'
|
||||||
extVersionCode = 147
|
extVersionCode = 148
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@ import androidx.preference.MultiSelectListPreference
|
||||||
import androidx.preference.PreferenceScreen
|
import androidx.preference.PreferenceScreen
|
||||||
import androidx.preference.SwitchPreferenceCompat
|
import androidx.preference.SwitchPreferenceCompat
|
||||||
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateDto
|
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateDto
|
||||||
|
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AtHomeDto
|
||||||
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterDto
|
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterDto
|
||||||
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterListDto
|
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterListDto
|
||||||
import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaDto
|
import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaDto
|
||||||
|
@ -231,8 +232,7 @@ abstract class MangaDex(override val lang: String, val dexLang: String) :
|
||||||
tempUrl.apply {
|
tempUrl.apply {
|
||||||
addQueryParameter("group", groupID)
|
addQueryParameter("group", groupID)
|
||||||
}
|
}
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
tempUrl.apply {
|
tempUrl.apply {
|
||||||
val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
|
val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
|
||||||
if (actualQuery.isNotBlank()) {
|
if (actualQuery.isNotBlank()) {
|
||||||
|
@ -375,40 +375,33 @@ abstract class MangaDex(override val lang: String, val dexLang: String) :
|
||||||
if (!helper.containsUuid(chapter.url)) {
|
if (!helper.containsUuid(chapter.url)) {
|
||||||
throw Exception("Migrate this manga from MangaDex to MangaDex to update it")
|
throw Exception("Migrate this manga from MangaDex to MangaDex to update it")
|
||||||
}
|
}
|
||||||
return GET(MDConstants.apiUrl + chapter.url, headers, CacheControl.FORCE_NETWORK)
|
val chapterId = chapter.url.substringAfter("/chapter/")
|
||||||
|
val usingStandardHTTPS =
|
||||||
|
preferences.getBoolean(MDConstants.getStandardHttpsPreferenceKey(dexLang), false)
|
||||||
|
val atHomeRequestUrl = if (usingStandardHTTPS) {
|
||||||
|
"${MDConstants.apiUrl}/at-home/server/$chapterId?forcePort443=true"
|
||||||
|
} else {
|
||||||
|
"${MDConstants.apiUrl}/at-home/server/$chapterId"
|
||||||
|
}
|
||||||
|
|
||||||
|
return helper.mdAtHomeRequest(atHomeRequestUrl, headers, CacheControl.FORCE_NETWORK)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
if (response.isSuccessful.not()) {
|
val atHomeRequestUrl = response.request.url
|
||||||
throw Exception("HTTP ${response.code}")
|
val atHomeDto = helper.json.decodeFromString<AtHomeDto>(response.body!!.string())
|
||||||
}
|
val host = atHomeDto.baseUrl
|
||||||
if (response.code == 204) {
|
|
||||||
return emptyList()
|
|
||||||
}
|
|
||||||
val chapterDto = helper.json.decodeFromString<ChapterDto>(response.body!!.string()).data
|
|
||||||
val usingStandardHTTPS =
|
|
||||||
preferences.getBoolean(MDConstants.getStandardHttpsPreferenceKey(dexLang), false)
|
|
||||||
|
|
||||||
val atHomeRequestUrl = if (usingStandardHTTPS) {
|
|
||||||
"${MDConstants.apiUrl}/at-home/server/${chapterDto.id}?forcePort443=true"
|
|
||||||
} else {
|
|
||||||
"${MDConstants.apiUrl}/at-home/server/${chapterDto.id}"
|
|
||||||
}
|
|
||||||
|
|
||||||
val host =
|
|
||||||
helper.getMdAtHomeUrl(atHomeRequestUrl, client, headers, CacheControl.FORCE_NETWORK)
|
|
||||||
|
|
||||||
val usingDataSaver =
|
val usingDataSaver =
|
||||||
preferences.getBoolean(MDConstants.getDataSaverPreferenceKey(dexLang), false)
|
preferences.getBoolean(MDConstants.getDataSaverPreferenceKey(dexLang), false)
|
||||||
|
|
||||||
// have to add the time, and url to the page because pages timeout within 30mins now
|
// have to add the time, and url to the page because pages timeout within 30mins now
|
||||||
val now = Date().time
|
val now = Date().time
|
||||||
|
|
||||||
val hash = chapterDto.attributes.hash
|
val hash = atHomeDto.chapter.hash
|
||||||
val pageSuffix = if (usingDataSaver) {
|
val pageSuffix = if (usingDataSaver) {
|
||||||
chapterDto.attributes.dataSaver.map { "/data-saver/$hash/$it" }
|
atHomeDto.chapter.dataSaver.map { "/data-saver/$hash/$it" }
|
||||||
} else {
|
} else {
|
||||||
chapterDto.attributes.data.map { "/data/$hash/$it" }
|
atHomeDto.chapter.data.map { "/data/$hash/$it" }
|
||||||
}
|
}
|
||||||
|
|
||||||
return pageSuffix.mapIndexed { index, imgUrl ->
|
return pageSuffix.mapIndexed { index, imgUrl ->
|
||||||
|
|
|
@ -142,17 +142,14 @@ class MangaDexHelper() {
|
||||||
/**
|
/**
|
||||||
* get the md@home url
|
* get the md@home url
|
||||||
*/
|
*/
|
||||||
fun getMdAtHomeUrl(
|
private fun getMdAtHomeUrl(
|
||||||
tokenRequestUrl: String,
|
tokenRequestUrl: String,
|
||||||
client: OkHttpClient,
|
client: OkHttpClient,
|
||||||
headers: Headers,
|
headers: Headers,
|
||||||
cacheControl: CacheControl,
|
cacheControl: CacheControl,
|
||||||
): String {
|
): String {
|
||||||
if (cacheControl == CacheControl.FORCE_NETWORK) {
|
|
||||||
tokenTracker[tokenRequestUrl] = Date().time
|
|
||||||
}
|
|
||||||
val response =
|
val response =
|
||||||
client.newCall(GET(tokenRequestUrl, headers, cacheControl)).execute()
|
client.newCall(mdAtHomeRequest(tokenRequestUrl, headers, cacheControl)).execute()
|
||||||
|
|
||||||
// This check is for the error that causes pages to fail to load.
|
// This check is for the error that causes pages to fail to load.
|
||||||
// It should never be entered, but in case it is, we retry the request.
|
// It should never be entered, but in case it is, we retry the request.
|
||||||
|
@ -164,6 +161,21 @@ class MangaDexHelper() {
|
||||||
return json.decodeFromString<AtHomeDto>(response.body!!.string()).baseUrl
|
return json.decodeFromString<AtHomeDto>(response.body!!.string()).baseUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create an md at home Request
|
||||||
|
*/
|
||||||
|
fun mdAtHomeRequest(
|
||||||
|
tokenRequestUrl: String,
|
||||||
|
headers: Headers,
|
||||||
|
cacheControl: CacheControl
|
||||||
|
): Request {
|
||||||
|
if (cacheControl == CacheControl.FORCE_NETWORK) {
|
||||||
|
tokenTracker[tokenRequestUrl] = Date().time
|
||||||
|
}
|
||||||
|
|
||||||
|
return GET(tokenRequestUrl, headers, cacheControl)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* create an SManga from json element only basic elements
|
* create an SManga from json element only basic elements
|
||||||
*/
|
*/
|
||||||
|
@ -314,7 +326,7 @@ class MangaDexHelper() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (attr.externalUrl != null && attr.data.isEmpty()) {
|
if (attr.externalUrl != null) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,15 @@ import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class AtHomeDto(
|
data class AtHomeDto(
|
||||||
val baseUrl: String
|
val baseUrl: String,
|
||||||
|
val chapter: AtHomeChapterDto,
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class AtHomeChapterDto(
|
||||||
|
val hash: String,
|
||||||
|
val data: List<String>,
|
||||||
|
val dataSaver: List<String>,
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
|
|
|
@ -30,8 +30,5 @@ data class ChapterAttributesDto(
|
||||||
val volume: String?,
|
val volume: String?,
|
||||||
val chapter: String?,
|
val chapter: String?,
|
||||||
val publishAt: String,
|
val publishAt: String,
|
||||||
val data: List<String>,
|
|
||||||
val dataSaver: List<String>,
|
|
||||||
val hash: String,
|
|
||||||
val externalUrl: String?,
|
val externalUrl: String?,
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue