Mangadex support completed status

This commit is contained in:
Jobobby04 2021-11-13 22:46:03 -05:00
parent 508f025092
commit 0df5376545
5 changed files with 76 additions and 47 deletions

View File

@ -56,7 +56,7 @@ import kotlin.reflect.KClass
@Suppress("OverridingDeprecatedMember") @Suppress("OverridingDeprecatedMember")
class MangaDex(delegate: HttpSource, val context: Context) : class MangaDex(delegate: HttpSource, val context: Context) :
DelegatedHttpSource(delegate), DelegatedHttpSource(delegate),
MetadataSource<MangaDexSearchMetadata, MangaDto>, MetadataSource<MangaDexSearchMetadata, Pair<MangaDto, List<String>>>,
UrlImportableSource, UrlImportableSource,
FollowsSource, FollowsSource,
LoginSource, LoginSource,
@ -193,8 +193,8 @@ class MangaDex(delegate: HttpSource, val context: Context) :
return MangaDexDescriptionAdapter(controller) return MangaDexDescriptionAdapter(controller)
} }
override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: MangaDto) { override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Pair<MangaDto, List<String>>) {
apiMangaParser.parseIntoMetadata(metadata, input) apiMangaParser.parseIntoMetadata(metadata, input.first, input.second)
} }
// LoginSource methods // LoginSource methods

View File

@ -122,3 +122,22 @@ data class CoverDataDto(
data class CoverAttributesDto( data class CoverAttributesDto(
val fileName: String, val fileName: String,
) )
@Serializable
data class AggregateDto(
val result: String,
val volumes: Map<String, AggregateVolume>,
)
@Serializable
data class AggregateVolume(
val volume: String,
val count: String,
val chapters: Map<String, AggregateChapter>,
)
@Serializable
data class AggregateChapter(
val chapter: String,
val count: String,
)

View File

@ -36,14 +36,14 @@ class ApiMangaParser(
}?.call() }?.call()
?: error("Could not find no-args constructor for meta class: ${metaClass.qualifiedName}!") ?: error("Could not find no-args constructor for meta class: ${metaClass.qualifiedName}!")
fun parseToManga(manga: MangaInfo, input: MangaDto, sourceId: Long): MangaInfo { fun parseToManga(manga: MangaInfo, input: MangaDto, simpleChapters: List<String>, sourceId: Long): MangaInfo {
val mangaId = db.getManga(manga.key, sourceId).executeAsBlocking()?.id val mangaId = db.getManga(manga.key, sourceId).executeAsBlocking()?.id
val metadata = if (mangaId != null) { val metadata = if (mangaId != null) {
val flatMetadata = db.getFlatMetadataForManga(mangaId).executeAsBlocking() val flatMetadata = db.getFlatMetadataForManga(mangaId).executeAsBlocking()
flatMetadata?.raise(metaClass) ?: newMetaInstance() flatMetadata?.raise(metaClass) ?: newMetaInstance()
} else newMetaInstance() } else newMetaInstance()
parseIntoMetadata(metadata, input) parseIntoMetadata(metadata, input, simpleChapters)
if (mangaId != null) { if (mangaId != null) {
metadata.mangaId = mangaId metadata.mangaId = mangaId
db.insertFlatMetadata(metadata.flatten()) db.insertFlatMetadata(metadata.flatten())
@ -52,7 +52,7 @@ class ApiMangaParser(
return metadata.createMangaInfo(manga) return metadata.createMangaInfo(manga)
} }
fun parseIntoMetadata(metadata: MangaDexSearchMetadata, mangaDto: MangaDto) { fun parseIntoMetadata(metadata: MangaDexSearchMetadata, mangaDto: MangaDto, simpleChapters: List<String>) {
with(metadata) { with(metadata) {
try { try {
val mangaAttributesDto = mangaDto.data.attributes val mangaAttributesDto = mangaDto.data.attributes
@ -73,11 +73,11 @@ class ApiMangaParser(
authors = mangaRelationshipsDto.filter { relationshipDto -> authors = mangaRelationshipsDto.filter { relationshipDto ->
relationshipDto.type.equals(MdConstants.Types.author, true) relationshipDto.type.equals(MdConstants.Types.author, true)
}.mapNotNull { it.attributes!!.name }.distinct() }.mapNotNull { it.attributes?.name }.distinct()
artists = mangaRelationshipsDto.filter { relationshipDto -> artists = mangaRelationshipsDto.filter { relationshipDto ->
relationshipDto.type.equals(MdConstants.Types.artist, true) relationshipDto.type.equals(MdConstants.Types.artist, true)
}.mapNotNull { it.attributes!!.name }.distinct() }.mapNotNull { it.attributes?.name }.distinct()
langFlag = mangaAttributesDto.originalLanguage langFlag = mangaAttributesDto.originalLanguage
val lastChapter = mangaAttributesDto.lastChapter?.toFloatOrNull() val lastChapter = mangaAttributesDto.lastChapter?.toFloatOrNull()
@ -98,15 +98,17 @@ class ApiMangaParser(
// val filteredChapters = filterChapterForChecking(networkApiManga) // val filteredChapters = filterChapterForChecking(networkApiManga)
val tempStatus = parseStatus(mangaAttributesDto.status ?: "") val tempStatus = parseStatus(mangaAttributesDto.status)
/*val publishedOrCancelled = val publishedOrCancelled = tempStatus == SManga.PUBLICATION_COMPLETE || tempStatus == SManga.CANCELLED
tempStatus == SManga.PUBLICATION_COMPLETE || tempStatus == SManga.CANCELLED status = if (
if (publishedOrCancelled && isMangaCompleted(networkApiManga, filteredChapters)) { mangaAttributesDto.lastChapter != null &&
manga.status = SManga.COMPLETED publishedOrCancelled &&
manga.missing_chapters = null mangaAttributesDto.lastChapter in simpleChapters
} else {*/ ) {
status = tempStatus SManga.COMPLETED
// } } else {
tempStatus
}
// things that will go with the genre tags but aren't actually genre // things that will go with the genre tags but aren't actually genre
val nonGenres = listOfNotNull( val nonGenres = listOfNotNull(
@ -134,34 +136,6 @@ class ApiMangaParser(
} }
} }
/**
* If chapter title is oneshot or a chapter exists which matches the last chapter in the required language
* return manga is complete
*/
/*private fun isMangaCompleted(
serializer: ApiMangaSerializer,
filteredChapters: List<ChapterSerializer>
): Boolean {
if (filteredChapters.isEmpty() || serializer.data.manga.lastChapter.isNullOrEmpty()) {
return false
}
val finalChapterNumber = serializer.data.manga.lastChapter!!
if (MdUtil.validOneShotFinalChapters.contains(finalChapterNumber)) {
filteredChapters.firstOrNull()?.let {
if (isOneShot(it, finalChapterNumber)) {
return true
}
}
}
val removeOneshots = filteredChapters.asSequence()
.map { it.chapter!!.toDoubleOrNull() }
.filter { it != null }
.map { floor(it!!).toInt() }
.filter { it != 0 }
.toList().distinctBy { it }
return removeOneshots.toList().size == floor(finalChapterNumber.toDouble()).toInt()
}*/
/* private fun filterChapterForChecking(serializer: ApiMangaSerializer): List<ChapterSerializer> { /* private fun filterChapterForChecking(serializer: ApiMangaSerializer): List<ChapterSerializer> {
serializer.data.chapters ?: return emptyList() serializer.data.chapters ?: return emptyList()
return serializer.data.chapters.asSequence() return serializer.data.chapters.asSequence()
@ -182,7 +156,7 @@ class ApiMangaParser(
((chapter.chapter.isNullOrEmpty() || chapter.chapter == "0") && MdUtil.validOneShotFinalChapters.contains(finalChapterNumber)) ((chapter.chapter.isNullOrEmpty() || chapter.chapter == "0") && MdUtil.validOneShotFinalChapters.contains(finalChapterNumber))
}*/ }*/
private fun parseStatus(status: String) = when (status) { private fun parseStatus(status: String?) = when (status) {
"ongoing" -> SManga.ONGOING "ongoing" -> SManga.ONGOING
"completed" -> SManga.PUBLICATION_COMPLETE "completed" -> SManga.PUBLICATION_COMPLETE
"cancelled" -> SManga.CANCELLED "cancelled" -> SManga.CANCELLED

View File

@ -14,6 +14,7 @@ import exh.md.utils.MdConstants
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.md.utils.mdListCall import exh.md.utils.mdListCall
import exh.metadata.metadata.MangaDexSearchMetadata import exh.metadata.metadata.MangaDexSearchMetadata
import kotlinx.coroutines.CancellationException
import kotlinx.coroutines.async import kotlinx.coroutines.async
import rx.Observable import rx.Observable
import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.ChapterInfo
@ -27,7 +28,8 @@ class MangaHandler(
) { ) {
suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): MangaInfo { suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): MangaInfo {
val response = withIOContext { service.viewManga(MdUtil.getMangaId(manga.key)) } val response = withIOContext { service.viewManga(MdUtil.getMangaId(manga.key)) }
return apiMangaParser.parseToManga(manga, response, sourceId) val simpleChapters = withIOContext { getSimpleChapters(manga) }
return apiMangaParser.parseToManga(manga, response, simpleChapters, sourceId)
} }
fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long, forceLatestCovers: Boolean): Observable<SManga> { fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long, forceLatestCovers: Boolean): Observable<SManga> {
@ -88,4 +90,17 @@ class MangaHandler(
apiMangaParser.chapterParseForMangaId(service.viewChapter(chapterId)) apiMangaParser.chapterParseForMangaId(service.viewChapter(chapterId))
} }
} }
private suspend fun getSimpleChapters(manga: MangaInfo): List<String> {
return runCatching { service.aggregateChapters(MdUtil.getMangaId(manga.key), lang) }
.onFailure {
if (it is CancellationException) throw it
}
.map { dto ->
dto.volumes.values
.flatMap { it.chapters.values }
.map { it.chapter }
}
.getOrDefault(emptyList())
}
} }

View File

@ -4,6 +4,7 @@ import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
import eu.kanade.tachiyomi.network.parseAs import eu.kanade.tachiyomi.network.parseAs
import exh.md.dto.AggregateDto
import exh.md.dto.AtHomeDto import exh.md.dto.AtHomeDto
import exh.md.dto.AtHomeImageReportDto import exh.md.dto.AtHomeImageReportDto
import exh.md.dto.ChapterDto import exh.md.dto.ChapterDto
@ -64,6 +65,26 @@ class MangaDexService(
).await().parseAs(MdUtil.jsonParser) ).await().parseAs(MdUtil.jsonParser)
} }
suspend fun aggregateChapters(
id: String,
translatedLanguage: String
): AggregateDto {
return client.newCall(
GET(
MdApi.manga.toHttpUrl()
.newBuilder()
.apply {
addPathSegment(id)
addPathSegment("aggregate")
addQueryParameter("translatedLanguage[]", translatedLanguage)
}
.build()
.toString(),
cache = CacheControl.FORCE_NETWORK
)
).await().parseAs(MdUtil.jsonParser)
}
suspend fun viewChapters( suspend fun viewChapters(
id: String, id: String,
translatedLanguage: String, translatedLanguage: String,