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:
parent
ac2301e4be
commit
c9062cc089
@ -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? {
|
||||||
|
@ -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))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
|
)
|
@ -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
|
||||||
)
|
)
|
||||||
|
@ -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"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user