Mangadex Api 5.0.4
This commit is contained in:
parent
c26adbb81d
commit
fc354f5792
@ -8,7 +8,7 @@ import exh.md.utils.FollowStatus
|
|||||||
import exh.metadata.metadata.base.RaisedSearchMetadata
|
import exh.metadata.metadata.base.RaisedSearchMetadata
|
||||||
|
|
||||||
interface FollowsSource : CatalogueSource {
|
interface FollowsSource : CatalogueSource {
|
||||||
suspend fun fetchFollows(): MangasPage
|
suspend fun fetchFollows(page: Int): MangasPage
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of all Follows retrieved by Coroutines
|
* Returns a list of all Follows retrieved by Coroutines
|
||||||
|
@ -161,8 +161,8 @@ class MangaDex(delegate: HttpSource, val context: Context) :
|
|||||||
ApiMangaParser(baseHttpClient, mdLang.lang).parseIntoMetadata(metadata, input, emptyList())
|
ApiMangaParser(baseHttpClient, mdLang.lang).parseIntoMetadata(metadata, input, emptyList())
|
||||||
}
|
}
|
||||||
|
|
||||||
override suspend fun fetchFollows(): MangasPage {
|
override suspend fun fetchFollows(page: Int): MangasPage {
|
||||||
return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).fetchFollows()
|
return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).fetchFollows(page)
|
||||||
}
|
}
|
||||||
|
|
||||||
override val requiresLogin: Boolean = false
|
override val requiresLogin: Boolean = false
|
||||||
|
@ -14,7 +14,7 @@ import rx.schedulers.Schedulers
|
|||||||
class MangaDexFollowsPager(val source: MangaDex) : Pager() {
|
class MangaDexFollowsPager(val source: MangaDex) : Pager() {
|
||||||
|
|
||||||
override fun requestNext(): Observable<MangasPage> {
|
override fun requestNext(): Observable<MangasPage> {
|
||||||
return runAsObservable({ source.fetchFollows() })
|
return runAsObservable({ source.fetchFollows(currentPage) })
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.doOnNext { onPageReceived(it) }
|
.doOnNext { onPageReceived(it) }
|
||||||
|
@ -219,7 +219,7 @@ class ApiMangaParser(val client: OkHttpClient, private val lang: String) {
|
|||||||
private fun parseStatus(status: String) = when (status) {
|
private fun parseStatus(status: String) = when (status) {
|
||||||
"ongoing" -> SManga.ONGOING
|
"ongoing" -> SManga.ONGOING
|
||||||
"complete" -> SManga.PUBLICATION_COMPLETE
|
"complete" -> SManga.PUBLICATION_COMPLETE
|
||||||
"abandoned" -> SManga.CANCELLED
|
"cancelled" -> SManga.CANCELLED
|
||||||
"hiatus" -> SManga.HIATUS
|
"hiatus" -> SManga.HIATUS
|
||||||
else -> SManga.UNKNOWN
|
else -> SManga.UNKNOWN
|
||||||
}
|
}
|
||||||
|
@ -14,15 +14,14 @@ import eu.kanade.tachiyomi.source.model.toSManga
|
|||||||
import eu.kanade.tachiyomi.util.lang.withIOContext
|
import eu.kanade.tachiyomi.util.lang.withIOContext
|
||||||
import exh.md.handlers.serializers.MangaListResponse
|
import exh.md.handlers.serializers.MangaListResponse
|
||||||
import exh.md.handlers.serializers.MangaResponse
|
import exh.md.handlers.serializers.MangaResponse
|
||||||
|
import exh.md.handlers.serializers.MangaStatusListResponse
|
||||||
|
import exh.md.handlers.serializers.MangaStatusResponse
|
||||||
import exh.md.handlers.serializers.UpdateReadingStatus
|
import exh.md.handlers.serializers.UpdateReadingStatus
|
||||||
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
|
||||||
import exh.util.under
|
import exh.util.under
|
||||||
import kotlinx.serialization.encodeToString
|
import kotlinx.serialization.encodeToString
|
||||||
import kotlinx.serialization.json.JsonObject
|
|
||||||
import kotlinx.serialization.json.jsonObject
|
|
||||||
import kotlinx.serialization.json.jsonPrimitive
|
|
||||||
import okhttp3.CacheControl
|
import okhttp3.CacheControl
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||||
@ -31,7 +30,6 @@ import okhttp3.OkHttpClient
|
|||||||
import okhttp3.Request
|
import okhttp3.Request
|
||||||
import okhttp3.RequestBody.Companion.toRequestBody
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import tachiyomi.source.model.MangaInfo
|
|
||||||
import java.util.Locale
|
import java.util.Locale
|
||||||
|
|
||||||
class FollowsHandler(
|
class FollowsHandler(
|
||||||
@ -44,28 +42,22 @@ class FollowsHandler(
|
|||||||
) {
|
) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetch all follows
|
* fetch follows page
|
||||||
*/
|
*/
|
||||||
suspend fun fetchFollows(): MetadataMangasPage {
|
suspend fun fetchFollows(page: Int): MetadataMangasPage {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val response = client.newCall(followsListRequest(0)).await()
|
val response = client.newCall(followsListRequest(MdUtil.mangaLimit * page - 1)).await()
|
||||||
|
|
||||||
val mangaListResponse = response.parseAs<MangaListResponse>(MdUtil.jsonParser)
|
val mangaListResponse = response.parseAs<MangaListResponse>(MdUtil.jsonParser)
|
||||||
val results = mangaListResponse.results.toMutableList()
|
|
||||||
|
|
||||||
var hasMoreResults = mangaListResponse.limit + mangaListResponse.offset under mangaListResponse.total
|
if (mangaListResponse.results.isEmpty()) {
|
||||||
var lastOffset = mangaListResponse.offset
|
return@withIOContext MetadataMangasPage(emptyList(), false, emptyList())
|
||||||
|
|
||||||
while (hasMoreResults) {
|
|
||||||
val offset = lastOffset + mangaListResponse.limit
|
|
||||||
val newMangaListResponse = client.newCall(followsListRequest(offset)).await()
|
|
||||||
.parseAs<MangaListResponse>(MdUtil.jsonParser)
|
|
||||||
results.addAll(newMangaListResponse.results)
|
|
||||||
hasMoreResults = newMangaListResponse.limit + newMangaListResponse.offset under newMangaListResponse.total
|
|
||||||
lastOffset = newMangaListResponse.offset
|
|
||||||
}
|
}
|
||||||
val statusListResponse = client.newCall(statusListRequest()).await().parseAs<JsonObject>()
|
|
||||||
followsParseMangaPage(results, statusListResponse)
|
val hasMoreResults = mangaListResponse.limit + mangaListResponse.offset under mangaListResponse.total
|
||||||
|
val statusListResponse = client.newCall(mangaStatusListRequest(mangaListResponse.results)).await().parseAs<MangaStatusListResponse>()
|
||||||
|
val results = followsParseMangaPage(mangaListResponse.results, statusListResponse)
|
||||||
|
|
||||||
|
MetadataMangasPage(results.map { it.first }, hasMoreResults, results.map { it.second })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,25 +65,29 @@ class FollowsHandler(
|
|||||||
* Parse follows api to manga page
|
* Parse follows api to manga page
|
||||||
* used when multiple follows
|
* used when multiple follows
|
||||||
*/
|
*/
|
||||||
private fun followsParseMangaPage(response: List<MangaResponse>, statusListResponse: JsonObject): MetadataMangasPage {
|
private fun followsParseMangaPage(response: List<MangaResponse>, statusListResponse: MangaStatusListResponse): List<Pair<SManga, MangaDexSearchMetadata>> {
|
||||||
val comparator = compareBy<Pair<MangaInfo, MangaDexSearchMetadata>> { it.second.followStatus }
|
val comparator = compareBy<Pair<SManga, MangaDexSearchMetadata>> { it.second.followStatus }
|
||||||
.thenBy { it.first.title }
|
.thenBy { it.first.title }
|
||||||
val result = response.map {
|
|
||||||
MdUtil.createMangaEntry(it, lang, useLowQualityCovers) to MangaDexSearchMetadata().apply {
|
return response.map {
|
||||||
followStatus = getFollowStatus(statusListResponse, it.data.id).int
|
MdUtil.createMangaEntry(
|
||||||
|
it,
|
||||||
|
lang,
|
||||||
|
useLowQualityCovers
|
||||||
|
).toSManga() to MangaDexSearchMetadata().apply {
|
||||||
|
followStatus = FollowStatus.fromDex(statusListResponse.statuses[it.data.id]).int
|
||||||
}
|
}
|
||||||
}.sortedWith(comparator)
|
}.sortedWith(comparator)
|
||||||
|
|
||||||
return MetadataMangasPage(result.map { it.first.toSManga() }, false, result.map { it.second })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fetch follow status used when fetching status for 1 manga
|
* fetch follow status used when fetching status for 1 manga
|
||||||
*/
|
*/
|
||||||
private fun followStatusParse(response: Response, statusListResponse: JsonObject): Track {
|
private fun followStatusParse(response: Response, sResponse: Response): Track {
|
||||||
val mangaResponse = response.parseAs<MangaResponse>(MdUtil.jsonParser)
|
val mangaResponse = response.parseAs<MangaResponse>(MdUtil.jsonParser)
|
||||||
|
val statusResponse = sResponse.parseAs<MangaStatusResponse>()
|
||||||
val track = Track.create(TrackManager.MDLIST)
|
val track = Track.create(TrackManager.MDLIST)
|
||||||
track.status = getFollowStatus(statusListResponse, mangaResponse.data.id).int
|
track.status = FollowStatus.fromDex(statusResponse.status).int
|
||||||
track.tracking_url = MdUtil.baseUrl + "/manga/" + mangaResponse.data.id
|
track.tracking_url = MdUtil.baseUrl + "/manga/" + mangaResponse.data.id
|
||||||
track.title = mangaResponse.data.attributes.title[lang] ?: mangaResponse.data.attributes.title["en"]!!
|
track.title = mangaResponse.data.attributes.title[lang] ?: mangaResponse.data.attributes.title["en"]!!
|
||||||
|
|
||||||
@ -197,30 +193,51 @@ class FollowsHandler(
|
|||||||
*/
|
*/
|
||||||
suspend fun fetchAllFollows(): List<Pair<SManga, MangaDexSearchMetadata>> {
|
suspend fun fetchAllFollows(): List<Pair<SManga, MangaDexSearchMetadata>> {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val metadata: List<MangaDexSearchMetadata>
|
val response = client.newCall(followsListRequest(0)).await()
|
||||||
fetchFollows().also { metadata = it.mangasMetadata.filterIsInstance<MangaDexSearchMetadata>() }.mangas.mapIndexed { index, manga ->
|
|
||||||
manga to metadata[index]
|
val mangaListResponse = response.parseAs<MangaListResponse>(MdUtil.jsonParser)
|
||||||
|
val results = mangaListResponse.results.toMutableList()
|
||||||
|
|
||||||
|
if (results.isEmpty()) {
|
||||||
|
return@withIOContext emptyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var hasMoreResults = mangaListResponse.limit + mangaListResponse.offset under mangaListResponse.total
|
||||||
|
var lastOffset = mangaListResponse.offset
|
||||||
|
|
||||||
|
while (hasMoreResults) {
|
||||||
|
val offset = lastOffset + mangaListResponse.limit
|
||||||
|
val newMangaListResponse = client.newCall(followsListRequest(offset)).await()
|
||||||
|
.parseAs<MangaListResponse>(MdUtil.jsonParser)
|
||||||
|
results.addAll(newMangaListResponse.results)
|
||||||
|
hasMoreResults = newMangaListResponse.limit + newMangaListResponse.offset under newMangaListResponse.total
|
||||||
|
lastOffset = newMangaListResponse.offset
|
||||||
|
}
|
||||||
|
val statusListResponse = client.newCall(mangaStatusListRequest(results)).await().parseAs<MangaStatusListResponse>()
|
||||||
|
followsParseMangaPage(results, statusListResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun fetchTrackingInfo(url: String): Track {
|
suspend fun fetchTrackingInfo(url: String): Track {
|
||||||
return withIOContext {
|
return withIOContext {
|
||||||
val statusListResponse = client.newCall(statusListRequest()).await().parseAs<JsonObject>(MdUtil.jsonParser)
|
val mangaId = MdUtil.getMangaId(url)
|
||||||
val request = GET(
|
val request = GET(
|
||||||
MdUtil.mangaUrl + "/" + MdUtil.getMangaId(url),
|
MdUtil.mangaUrl + "/" + mangaId,
|
||||||
|
MdUtil.getAuthHeaders(headers, preferences, mdList),
|
||||||
|
CacheControl.FORCE_NETWORK
|
||||||
|
)
|
||||||
|
val statusRequest = GET(
|
||||||
|
MdUtil.mangaUrl + "/" + mangaId + "/status",
|
||||||
MdUtil.getAuthHeaders(headers, preferences, mdList),
|
MdUtil.getAuthHeaders(headers, preferences, mdList),
|
||||||
CacheControl.FORCE_NETWORK
|
CacheControl.FORCE_NETWORK
|
||||||
)
|
)
|
||||||
val response = client.newCall(request).await()
|
val response = client.newCall(request).await()
|
||||||
followStatusParse(response, statusListResponse)
|
val statusResponse = client.newCall(statusRequest).await()
|
||||||
|
followStatusParse(response, statusResponse)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getFollowStatus(jsonObject: JsonObject, id: String) =
|
private fun mangaStatusListRequest(mangaListResponse: List<MangaResponse>): Request {
|
||||||
FollowStatus.fromDex(jsonObject["statuses"]?.jsonObject?.get(id)?.jsonPrimitive?.content)
|
return GET(MdUtil.mangaStatus + "/" + mangaListResponse.joinToString("&ids[]=", "?ids[]=") { it.data.id }, MdUtil.getAuthHeaders(headers, preferences, mdList), CacheControl.FORCE_NETWORK)
|
||||||
|
|
||||||
private fun statusListRequest(): Request {
|
|
||||||
return GET(MdUtil.mangaStatus, MdUtil.getAuthHeaders(headers, preferences, mdList), CacheControl.FORCE_NETWORK)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ data class NetworkChapter(
|
|||||||
@Serializable
|
@Serializable
|
||||||
data class ChapterAttributes(
|
data class ChapterAttributes(
|
||||||
val title: String?,
|
val title: String?,
|
||||||
val volume: Int?,
|
val volume: String?,
|
||||||
val chapter: String?,
|
val chapter: String?,
|
||||||
val translatedLanguage: String,
|
val translatedLanguage: String,
|
||||||
val publishAt: String,
|
val publishAt: String,
|
||||||
|
@ -27,14 +27,13 @@ data class NetworkMangaAttributes(
|
|||||||
val description: Map<String, String>,
|
val description: Map<String, String>,
|
||||||
val links: Map<String, String>?,
|
val links: Map<String, String>?,
|
||||||
val originalLanguage: String,
|
val originalLanguage: String,
|
||||||
val lastVolume: Int?,
|
val lastVolume: String?,
|
||||||
val lastChapter: String,
|
val lastChapter: String,
|
||||||
val contentRating: String?,
|
val contentRating: String?,
|
||||||
val publicationDemographic: String?,
|
val publicationDemographic: String?,
|
||||||
val status: String?,
|
val status: String?,
|
||||||
val year: Int?,
|
val year: Int?,
|
||||||
val tags: List<TagsSerializer>
|
val tags: List<TagsSerializer>
|
||||||
// val readingStatus: String? = null,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
@ -80,3 +79,13 @@ data class AuthorAttributes(
|
|||||||
data class UpdateReadingStatus(
|
data class UpdateReadingStatus(
|
||||||
val status: String?
|
val status: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MangaStatusResponse(
|
||||||
|
val status: String?
|
||||||
|
)
|
||||||
|
|
||||||
|
@Serializable
|
||||||
|
data class MangaStatusListResponse(
|
||||||
|
val statuses: Map<String, String?>
|
||||||
|
)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user