switch to v2 and api server + old style chapter urls for delegation

(cherry picked from commit b79c1572470fea4568708d3526f5170868a0c3c1)

# Conflicts:
#	app/src/main/java/eu/kanade/tachiyomi/source/online/handlers/ApiChapterParser.kt
#	app/src/main/java/eu/kanade/tachiyomi/source/online/handlers/FollowsHandler.kt
#	app/src/main/java/exh/md/handlers/SearchHandler.kt
This commit is contained in:
Carlos 2021-01-06 20:28:30 -05:00 committed by Jobobby04
parent ac2301e4be
commit c9062cc089
11 changed files with 68 additions and 42 deletions

View File

@ -114,7 +114,7 @@ class MangaDex(delegate: HttpSource, val context: Context) :
override fun mapUrlToChapterUrl(uri: Uri): String? { override fun mapUrlToChapterUrl(uri: Uri): String? {
if (!uri.pathSegments.firstOrNull().equals("chapter", true)) return null if (!uri.pathSegments.firstOrNull().equals("chapter", true)) return null
val id = uri.pathSegments.getOrNull(1) ?: return null val id = uri.pathSegments.getOrNull(1) ?: return null
return MdUtil.apiChapter + id return MdUtil.apiChapterOld + id
} }
override suspend fun mapChapterUrlToMangaUrl(uri: Uri): String? { override suspend fun mapChapterUrlToMangaUrl(uri: Uri): String? {

View File

@ -1,26 +1,27 @@
package exh.md.handlers package exh.md.handlers
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import exh.md.handlers.serializers.ApiChapterSerializer
import exh.md.utils.MdUtil
import kotlinx.serialization.decodeFromString import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.jsonArray
import kotlinx.serialization.json.jsonPrimitive import kotlinx.serialization.json.jsonPrimitive
import okhttp3.Response import okhttp3.Response
class ApiChapterParser { class ApiChapterParser {
fun pageListParse(response: Response): List<Page> { fun pageListParse(response: Response): List<Page> {
val jsonData = response.body!!.string() val jsonData = response.body!!.string()
val json = Json.decodeFromString<JsonObject>(jsonData) val networkApiChapter = MdUtil.jsonParser.decodeFromString<ApiChapterSerializer>(jsonData)
val pages = mutableListOf<Page>() val pages = mutableListOf<Page>()
val hash = json["hash"]!!.jsonPrimitive.content val hash = networkApiChapter.data.hash
val pageArray = json["page_array"]!!.jsonArray val pageArray = networkApiChapter.data.pages
val server = json["server"]!!.jsonPrimitive.content val server = networkApiChapter.data.server
pageArray.forEach { pageArray.forEach {
val url = "$hash/${it.jsonPrimitive.content}" val url = "$hash/$it"
pages.add(Page(pages.size, "$server,${response.request.url},${System.currentTimeMillis()}", url)) pages.add(Page(pages.size, "$server,${response.request.url},${System.currentTimeMillis()}", url))
} }

View File

@ -275,7 +275,7 @@ class ApiMangaParser(private val langs: List<String>) {
groups: Map<Long, String> groups: Map<Long, String>
): SChapter { ): SChapter {
val chapter = SChapter.create() val chapter = SChapter.create()
chapter.url = MdUtil.apiChapter + networkChapter.id chapter.url = MdUtil.apiChapterOld + networkChapter.id
val chapterName = mutableListOf<String>() val chapterName = mutableListOf<String>()
// Build chapter name // Build chapter name

View File

@ -10,8 +10,8 @@ import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
import eu.kanade.tachiyomi.source.model.MetadataMangasPage import eu.kanade.tachiyomi.source.model.MetadataMangasPage
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import exh.md.handlers.serializers.FollowsPageResult import exh.md.handlers.serializers.FollowPage
import exh.md.handlers.serializers.Result import exh.md.handlers.serializers.FollowsPageSerializer
import exh.md.utils.FollowStatus import exh.md.utils.FollowStatus
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
@ -50,15 +50,15 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
) )
} catch (e: Exception) { } catch (e: Exception) {
XLog.tag("FollowsHandler").enableStackTrace(2).e("error parsing follows", e) XLog.tag("FollowsHandler").enableStackTrace(2).e("error parsing follows", e)
FollowsPageResult() FollowsPageSerializer(emptyList())
} }
if (followsPageResult.result.isEmpty()) { if (followsPageResult.data.isEmpty()) {
return MetadataMangasPage(emptyList(), false, emptyList()) return MetadataMangasPage(emptyList(), false, emptyList())
} }
val lowQualityCovers = if (forceHd) false else useLowQualityCovers val lowQualityCovers = if (forceHd) false else useLowQualityCovers
val follows = followsPageResult.result.map { val follows = followsPageResult.data.map {
followFromElement(it, lowQualityCovers) followFromElement(it, lowQualityCovers)
} }
@ -80,19 +80,19 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
) )
} catch (e: Exception) { } catch (e: Exception) {
XLog.tag("FollowsHandler").enableStackTrace(2).e("error parsing follows", e) XLog.tag("FollowsHandler").enableStackTrace(2).e("error parsing follows", e)
FollowsPageResult() FollowsPageSerializer(emptyList())
} }
val track = Track.create(TrackManager.MDLIST) val track = Track.create(TrackManager.MDLIST)
if (followsPageResult.result.isEmpty()) { if (followsPageResult.data.isEmpty()) {
track.status = FollowStatus.UNFOLLOWED.int track.status = FollowStatus.UNFOLLOWED.int
} else { } else {
val follow = followsPageResult.result.first() val follow = followsPageResult.data.first()
track.status = follow.follow_type track.status = follow.followType
if (followsPageResult.result[0].chapter.isNotBlank()) { if (followsPageResult.data[0].chapter.isNotBlank()) {
track.last_chapter_read = follow.chapter.toFloat().floor() track.last_chapter_read = follow.chapter.toFloat().floor()
} }
track.tracking_url = MdUtil.baseUrl + follow.manga_id.toString() track.tracking_url = MdUtil.baseUrl + follow.mangaId.toString()
track.title = follow.title track.title = follow.mangaTitle
} }
return track return track
} }
@ -101,22 +101,22 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
* build Request for follows page * build Request for follows page
*/ */
private fun followsListRequest(): Request { private fun followsListRequest(): Request {
return GET("${MdUtil.baseUrl}${MdUtil.followsAllApi}", headers, CacheControl.FORCE_NETWORK) return GET("${MdUtil.apiUrl}${MdUtil.followsAllApi}", headers, CacheControl.FORCE_NETWORK)
} }
/** /**
* Parse result element to manga * Parse result element to manga
*/ */
private fun followFromElement(result: Result, lowQualityCovers: Boolean): Pair<SManga, MangaDexSearchMetadata> { private fun followFromElement(result: FollowPage, lowQualityCovers: Boolean): Pair<SManga, MangaDexSearchMetadata> {
val manga = SManga.create() val manga = SManga.create()
manga.title = MdUtil.cleanString(result.title) manga.title = MdUtil.cleanString(result.mangaTitle)
manga.url = "/manga/${result.manga_id}/" manga.url = "/manga/${result.mangaId}/"
manga.thumbnail_url = MdUtil.formThumbUrl(manga.url, lowQualityCovers) manga.thumbnail_url = MdUtil.formThumbUrl(manga.url, lowQualityCovers)
return manga to MangaDexSearchMetadata().apply { return manga to MangaDexSearchMetadata().apply {
title = manga.title title = manga.title
mdUrl = manga.url mdUrl = manga.url
thumbnail_url = manga.thumbnail_url thumbnail_url = manga.thumbnail_url
follow_status = FollowStatus.fromInt(result.follow_type)?.int follow_status = FollowStatus.fromInt(result.followType)?.int
} }
} }
@ -211,7 +211,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
suspend fun fetchTrackingInfo(url: String): Track { suspend fun fetchTrackingInfo(url: String): Track {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val request = GET( val request = GET(
"${MdUtil.baseUrl}${MdUtil.followsMangaApi}" + MdUtil.getMangaId(url), "${MdUtil.apiUrl}${MdUtil.followsMangaApi}" + MdUtil.getMangaId(url),
headers, headers,
CacheControl.FORCE_NETWORK CacheControl.FORCE_NETWORK
) )

View File

@ -56,7 +56,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
suspend fun getMangaIdFromChapterId(urlChapterId: String): Int { suspend fun getMangaIdFromChapterId(urlChapterId: String): Int {
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
val request = GET(MdUtil.baseUrl + MdUtil.apiChapter + urlChapterId + MdUtil.apiChapterSuffix, headers, CacheControl.FORCE_NETWORK) val request = GET(MdUtil.apiUrl + MdUtil.apiChapter + urlChapterId + MdUtil.apiChapterSuffix, headers, CacheControl.FORCE_NETWORK)
val response = client.newCall(request).await() val response = client.newCall(request).await()
ApiMangaParser(langs).chapterParseForMangaId(response) ApiMangaParser(langs).chapterParseForMangaId(response)
} }
@ -126,10 +126,10 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val langs: Li
} }
private fun apiRequest(manga: SManga): Request { private fun apiRequest(manga: SManga): Request {
return GET(MdUtil.baseUrl + MdUtil.apiManga + MdUtil.getMangaId(manga.url) + MdUtil.includeChapters, headers, CacheControl.FORCE_NETWORK) return GET(MdUtil.apiUrl + MdUtil.apiManga + MdUtil.getMangaId(manga.url) + MdUtil.includeChapters, headers, CacheControl.FORCE_NETWORK)
} }
private fun coverRequest(manga: SManga): Request { private fun coverRequest(manga: SManga): Request {
return GET(MdUtil.baseUrl + MdUtil.apiManga + MdUtil.getMangaId(manga.url) + MdUtil.apiCovers, headers, CacheControl.FORCE_NETWORK) return GET(MdUtil.apiUrl + MdUtil.apiManga + MdUtil.getMangaId(manga.url) + MdUtil.apiCovers, headers, CacheControl.FORCE_NETWORK)
} }
} }

View File

@ -32,6 +32,6 @@ class PageHandler(val client: OkHttpClient, val headers: Headers, private val im
private fun pageListRequest(chapter: SChapter): Request { private fun pageListRequest(chapter: SChapter): Request {
val chpUrl = chapter.url.substringBefore(MdUtil.apiChapterSuffix) val chpUrl = chapter.url.substringBefore(MdUtil.apiChapterSuffix)
return GET("${MdUtil.baseUrl}${chpUrl}${MdUtil.apiChapterSuffix}&server=$imageServer&saver=$dataSaver", headers, CacheControl.FORCE_NETWORK) return GET("${MdUtil.apiUrl}${chpUrl}${MdUtil.apiChapterSuffix}&server=$imageServer&saver=$dataSaver", headers, CacheControl.FORCE_NETWORK)
} }
} }

View File

@ -193,7 +193,7 @@ class SearchHandler(val client: OkHttpClient, private val headers: Headers, val
} }
private fun searchMangaByIdRequest(id: String): Request { private fun searchMangaByIdRequest(id: String): Request {
return GET(MdUtil.baseUrl + MdUtil.apiManga + id, headers, CacheControl.FORCE_NETWORK) return GET(MdUtil.apiUrl + MdUtil.apiManga + id + MdUtil.includeChapters, headers, CacheControl.FORCE_NETWORK)
} }
private fun searchMangaByGroupRequest(group: String): Request { private fun searchMangaByGroupRequest(group: String): Request {

View File

@ -0,0 +1,23 @@
package exh.md.handlers.serializers
import kotlinx.serialization.Serializable
/*
* Copyright (C) 2020 The Neko Manga Open Source Project
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
@Serializable
data class ApiChapterSerializer(
val data: ChapterPageSerializer
)
@Serializable
data class ChapterPageSerializer(
val hash: String,
val pages: List<String>,
val server: String
)

View File

@ -3,15 +3,15 @@ package exh.md.handlers.serializers
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
@Serializable @Serializable
data class FollowsPageResult( data class FollowsPageSerializer(
val result: List<Result> = emptyList() val data: List<FollowPage>
) )
@Serializable @Serializable
data class Result( data class FollowPage(
val title: String, val mangaTitle: String,
val chapter: String, val chapter: String,
val follow_type: Int, val followType: Int,
val manga_id: Int, val mangaId: Int,
val volume: String val volume: String
) )

View File

@ -23,13 +23,15 @@ class MdUtil {
const val cdnUrl = "https://mangadex.org" // "https://s0.mangadex.org" const val cdnUrl = "https://mangadex.org" // "https://s0.mangadex.org"
const val baseUrl = "https://mangadex.org" const val baseUrl = "https://mangadex.org"
const val randMangaPage = "/manga/" const val randMangaPage = "/manga/"
const val apiManga = "/api/v2/manga/" const val apiUrl = "https://api.mangadex.org"
const val apiManga = "/v2/manga/"
const val includeChapters = "?include=chapters" const val includeChapters = "?include=chapters"
const val apiChapter = "/api/chapter/" const val apiChapter = "/v2/chapter/"
const val apiChapterOld = "/api/chapter/"
const val apiChapterSuffix = "?mark_read=0" const val apiChapterSuffix = "?mark_read=0"
const val groupSearchUrl = "$baseUrl/groups/0/1/" const val groupSearchUrl = "$baseUrl/groups/0/1/"
const val followsAllApi = "/api/?type=manga_follows" const val followsAllApi = "/v2/user/me/followed-manga"
const val followsMangaApi = "/api/?type=manga_follows&manga_id=" const val followsMangaApi = "/v2/user/me/manga/"
const val apiCovers = "/covers" const val apiCovers = "/covers"
const val reportUrl = "https://api.mangadex.network/report" const val reportUrl = "https://api.mangadex.network/report"
const val imageUrl = "$baseUrl/data" const val imageUrl = "$baseUrl/data"