komikku/app/src/main/java/exh/md/handlers/MangaHandler.kt

157 lines
6 KiB
Kotlin
Raw Normal View History

package exh.md.handlers
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.parseAs
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.source.model.toMangaInfo
2021-01-16 04:29:57 +01:00
import eu.kanade.tachiyomi.source.model.toSChapter
import eu.kanade.tachiyomi.source.model.toSManga
import eu.kanade.tachiyomi.util.lang.runAsObservable
import eu.kanade.tachiyomi.util.lang.withIOContext
import exh.md.handlers.serializers.ChapterResponse
import exh.md.handlers.serializers.GroupListResponse
import exh.md.utils.MdUtil
2021-05-11 19:06:55 +02:00
import exh.md.utils.mdListCall
import exh.metadata.metadata.MangaDexSearchMetadata
import kotlinx.coroutines.async
import okhttp3.CacheControl
import okhttp3.Headers
import okhttp3.OkHttpClient
import okhttp3.Request
import rx.Observable
2021-01-16 04:29:57 +01:00
import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.api.get
2021-05-17 18:45:33 +02:00
class MangaHandler(
2021-06-03 22:42:26 +02:00
private val client: OkHttpClient,
private val headers: Headers,
2021-05-17 18:45:33 +02:00
private val lang: String,
private val apiMangaParser: ApiMangaParser,
private val followsHandler: FollowsHandler
) {
2021-05-17 18:45:33 +02:00
suspend fun fetchMangaAndChapterDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): Pair<MangaInfo, List<ChapterInfo>> {
return withIOContext {
val response = client.newCall(mangaRequest(manga)).await()
2021-06-03 22:28:38 +02:00
apiMangaParser.parseToManga(manga, response, sourceId) to getChapterList(manga)
}
}
2021-06-03 22:28:38 +02:00
/*suspend fun getCovers(manga: MangaInfo, forceLatestCovers: Boolean): List<String> {
*//* if (forceLatestCovers) {
val covers = client.newCall(coverRequest(manga)).await().parseAs<ApiCovers>(MdUtil.jsonParser)
return covers.data.map { it.url }
2021-06-03 22:28:38 +02:00
} else {*//*
2021-05-17 18:45:33 +02:00
return emptyList()
// }
2021-06-03 22:28:38 +02:00
}*/
suspend fun getMangaIdFromChapterId(urlChapterId: String): String {
return withIOContext {
val request = GET(MdUtil.chapterUrl + urlChapterId)
2020-10-28 00:52:32 +01:00
val response = client.newCall(request).await()
2021-05-17 18:45:33 +02:00
apiMangaParser.chapterParseForMangaId(response)
}
}
2021-05-17 18:45:33 +02:00
suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): MangaInfo {
2021-05-10 05:27:18 +02:00
val response = withIOContext { client.newCall(mangaRequest(manga)).await() }
2021-06-03 22:28:38 +02:00
return apiMangaParser.parseToManga(manga, response, sourceId)
}
2021-05-17 18:45:33 +02:00
fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long, forceLatestCovers: Boolean): Observable<SManga> {
2021-05-11 19:06:55 +02:00
return runAsObservable({
2021-05-17 18:45:33 +02:00
getMangaDetails(manga.toMangaInfo(), sourceId, forceLatestCovers).toSManga()
2021-05-11 19:06:55 +02:00
})
}
2021-05-11 19:06:55 +02:00
fun fetchChapterListObservable(manga: SManga): Observable<List<SChapter>> = runAsObservable({
getChapterList(manga.toMangaInfo()).map { it.toSChapter() }
})
2021-01-16 04:29:57 +01:00
suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
return withIOContext {
2021-05-11 19:06:55 +02:00
val results = client.mdListCall<ChapterResponse> {
mangaFeedRequest(manga, it, lang)
}
val groupMap = getGroupMap(results)
2021-05-17 18:45:33 +02:00
apiMangaParser.chapterListParse(results, groupMap)
}
}
private suspend fun getGroupMap(results: List<ChapterResponse>): Map<String, String> {
val groupIds = results.asSequence()
2021-05-11 19:06:55 +02:00
.flatMap { chapter -> chapter.relationships }
.filter { it.type == "scanlation_group" }
.map { it.id }
2021-05-11 19:06:55 +02:00
.toSet()
return runCatching {
groupIds.chunked(100).flatMapIndexed { index, ids ->
val response = client.newCall(groupIdRequest(ids, 100 * index)).await()
if (response.code != 204) {
response
.parseAs<GroupListResponse>(MdUtil.jsonParser)
2021-05-11 19:06:55 +02:00
.results.map { group -> group.data.id to group.data.attributes.name }
} else {
emptyList()
}
}.toMap()
2021-05-11 19:06:55 +02:00
}.getOrNull().orEmpty()
}
2020-12-26 20:22:55 +01:00
suspend fun fetchRandomMangaId(): String {
return withIOContext {
val response = client.newCall(randomMangaRequest()).await()
2021-05-17 18:45:33 +02:00
apiMangaParser.randomMangaIdParse(response)
}
}
2021-05-26 05:34:56 +02:00
suspend fun getTrackingInfo(track: Track): Pair<Track, MangaDexSearchMetadata?> {
return withIOContext {
/*val metadata = async {
2021-05-17 18:45:33 +02:00
val mangaUrl = MdUtil.buildMangaUrl(MdUtil.getMangaId(track.tracking_url))
val manga = MangaInfo(mangaUrl, track.title)
val response = client.newCall(mangaRequest(manga)).await()
val metadata = MangaDexSearchMetadata()
2021-05-17 18:45:33 +02:00
apiMangaParser.parseIntoMetadata(metadata, response, emptyList())
metadata
}*/
val remoteTrack = async {
2021-05-17 18:45:33 +02:00
followsHandler.fetchTrackingInfo(track.tracking_url)
}
2021-05-07 19:41:33 +02:00
remoteTrack.await() to null
}
}
private fun randomMangaRequest(): Request {
return GET(MdUtil.randomMangaUrl, cache = CacheControl.FORCE_NETWORK)
}
private fun mangaRequest(manga: MangaInfo): Request {
return GET(MdUtil.mangaUrl + "/" + MdUtil.getMangaId(manga.key), headers, CacheControl.FORCE_NETWORK)
}
private fun mangaFeedRequest(manga: MangaInfo, offset: Int, lang: String): Request {
return GET(MdUtil.mangaFeedUrl(MdUtil.getMangaId(manga.key), offset, lang), headers, CacheControl.FORCE_NETWORK)
}
private fun groupIdRequest(id: List<String>, offset: Int): Request {
val urlSuffix = id.joinToString("&ids[]=", "?limit=100&offset=$offset&ids[]=")
return GET(MdUtil.groupUrl + urlSuffix, headers)
}
/* private fun coverRequest(manga: SManga): Request {
return GET(MdUtil.apiUrl + MdUtil.apiManga + MdUtil.getMangaId(manga.url) + MdUtil.apiCovers, headers, CacheControl.FORCE_NETWORK)
}*/
companion object {
}
}