Separate MDList from Mangadex manga, allowing it to be used with other sources(not implemented)

This commit is contained in:
Jobobby04 2021-02-11 16:41:23 -05:00
parent 86c228243d
commit 227de5d838
6 changed files with 50 additions and 31 deletions

View File

@ -4,7 +4,6 @@ import android.content.Context
import android.graphics.Color import android.graphics.Color
import androidx.annotation.StringRes import androidx.annotation.StringRes
import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.data.database.DatabaseHelper
import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.data.database.models.Manga
import eu.kanade.tachiyomi.data.database.models.Track import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.data.track.TrackManager
@ -13,17 +12,10 @@ import eu.kanade.tachiyomi.data.track.model.TrackSearch
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
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.base.getFlatMetadataForManga
import exh.metadata.metadata.base.insertFlatMetadataAsync
import exh.util.executeOnIO
import exh.util.floor
import uy.kohesive.injekt.injectLazy
class MdList(private val context: Context, id: Int) : TrackService(id) { class MdList(private val context: Context, id: Int) : TrackService(id) {
private val mdex by lazy { MdUtil.getEnabledMangaDex() } private val mdex by lazy { MdUtil.getEnabledMangaDex() }
private val db: DatabaseHelper by injectLazy()
@StringRes @StringRes
override fun nameRes(): Int = R.string.mdlist override fun nameRes(): Int = R.string.mdlist
@ -51,16 +43,16 @@ class MdList(private val context: Context, id: Int) : TrackService(id) {
override suspend fun update(track: Track): Track { override suspend fun update(track: Track): Track {
val mdex = mdex ?: throw Exception("Mangadex not enabled") val mdex = mdex ?: throw Exception("Mangadex not enabled")
val mangaMetadata = db.getFlatMetadataForManga(track.manga_id).executeAsBlocking()
?.raise<MangaDexSearchMetadata>() val remoteTrack = mdex.fetchTrackingInfo(track.tracking_url)
?: throw Exception("Invalid manga metadata")
val followStatus = FollowStatus.fromInt(track.status) val followStatus = FollowStatus.fromInt(track.status)
// this updates the follow status in the metadata
// allow follow status to update // allow follow status to update
if (mangaMetadata.follow_status != followStatus.int) { if (remoteTrack.status != followStatus.int) {
mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus) mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus)
mangaMetadata.follow_status = followStatus.int remoteTrack.status = followStatus.int
db.insertFlatMetadataAsync(mangaMetadata.flatten()).await() // db.insertFlatMetadataAsync(mangaMetadata.flatten()).await()
} }
if (track.score.toInt() > 0) { if (track.score.toInt() > 0) {
@ -78,8 +70,8 @@ class MdList(private val context: Context, id: Int) : TrackService(id) {
val newFollowStatus = FollowStatus.READING val newFollowStatus = FollowStatus.READING
track.status = FollowStatus.READING.int track.status = FollowStatus.READING.int
mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), newFollowStatus) mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), newFollowStatus)
mangaMetadata.follow_status = newFollowStatus.int remoteTrack.status = newFollowStatus.int
db.insertFlatMetadataAsync(mangaMetadata.flatten()).await() // db.insertFlatMetadataAsync(mangaMetadata.flatten()).await()
} }
mdex.updateReadingProgress(track) mdex.updateReadingProgress(track)
@ -96,20 +88,20 @@ class MdList(private val context: Context, id: Int) : TrackService(id) {
override suspend fun refresh(track: Track): Track { override suspend fun refresh(track: Track): Track {
val mdex = mdex ?: throw Exception("Mangadex not enabled") val mdex = mdex ?: throw Exception("Mangadex not enabled")
val remoteTrack = mdex.fetchTrackingInfo(track.tracking_url) val (remoteTrack, mangaMetadata) = mdex.getTrackingAndMangaInfo(track)
track.copyPersonalFrom(remoteTrack) track.copyPersonalFrom(remoteTrack)
if (track.total_chapters == 0 && db.getManga(track.manga_id).executeOnIO()?.status == SManga.COMPLETED) { if (track.total_chapters == 0 && mangaMetadata.status == SManga.COMPLETED) {
track.total_chapters = db.getChapters(track.manga_id).executeOnIO().maxOfOrNull { it.chapter_number }?.floor() ?: 0 track.total_chapters = mangaMetadata.maxChapterNumber ?: 0
} }
return track return track
} }
fun createInitialTracker(manga: Manga): Track { fun createInitialTracker(dbManga: Manga, mdManga: Manga = dbManga): Track {
val track = Track.create(TrackManager.MDLIST) val track = Track.create(TrackManager.MDLIST)
track.manga_id = manga.id!! track.manga_id = dbManga.id!!
track.status = FollowStatus.UNFOLLOWED.int track.status = FollowStatus.UNFOLLOWED.int
track.tracking_url = MdUtil.baseUrl + manga.url track.tracking_url = MdUtil.baseUrl + mdManga.url
track.title = manga.title track.title = mdManga.title
return track return track
} }

View File

@ -268,6 +268,10 @@ class MangaDex(delegate: HttpSource, val context: Context) :
} }
} }
suspend fun getTrackingAndMangaInfo(track: Track): Pair<Track, MangaDexSearchMetadata> {
return MangaHandler(client, headers, lang).getTrackingInfo(track, useLowQualityThumbnail())
}
override suspend fun updateFollowStatus(mangaID: String, followStatus: FollowStatus): Boolean { override suspend fun updateFollowStatus(mangaID: String, followStatus: FollowStatus): Boolean {
return withIOContext { FollowsHandler(client, headers, Injekt.get(), useLowQualityThumbnail()).updateFollowStatus(mangaID, followStatus) } return withIOContext { FollowsHandler(client, headers, Injekt.get(), useLowQualityThumbnail()).updateFollowStatus(mangaID, followStatus) }
} }

View File

@ -126,6 +126,7 @@ class ApiMangaParser(private val lang: String) {
if (publishedOrCancelled && isMangaCompleted(networkApiManga, filteredChapters)) { if (publishedOrCancelled && isMangaCompleted(networkApiManga, filteredChapters)) {
status = SManga.COMPLETED status = SManga.COMPLETED
missing_chapters = null missing_chapters = null
maxChapterNumber = networkApiManga.data.manga.lastChapter?.toDoubleOrNull()?.floor()
} else { } else {
status = tempStatus status = tempStatus
} }

View File

@ -7,6 +7,7 @@ import eu.kanade.tachiyomi.data.track.TrackManager
import eu.kanade.tachiyomi.network.GET 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.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
@ -75,9 +76,7 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
private fun followStatusParse(response: Response): Track { private fun followStatusParse(response: Response): Track {
val followsPageResult = try { val followsPageResult = try {
MdUtil.jsonParser.decodeFromString<FollowsIndividualSerializer>( response.parseAs<FollowsIndividualSerializer>(MdUtil.jsonParser)
response.body?.string().orEmpty()
)
} 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)
throw e throw e
@ -214,14 +213,21 @@ class FollowsHandler(val client: OkHttpClient, val headers: Headers, val prefere
suspend fun fetchTrackingInfo(url: String): Track { suspend fun fetchTrackingInfo(url: String): Track {
return withIOContext { return withIOContext {
val request = GET( val request = GET(
"${MdUtil.apiUrl}${MdUtil.followsMangaApi}" + MdUtil.getMangaId(url), MdUtil.apiUrl + MdUtil.followsMangaApi + MdUtil.getMangaId(url),
headers, headers,
CacheControl.FORCE_NETWORK CacheControl.FORCE_NETWORK
) )
val response = client.newCall(request).await() try {
val track = followStatusParse(response) val response = client.newCall(request).await()
followStatusParse(response)
track } catch (e: Exception) {
if (e.message.equals("HTTP error 404", true)) {
XLog.enableStackTrace(10).e(e)
Track.create(TrackManager.MDLIST).apply {
status = FollowStatus.UNFOLLOWED.int
}
} else throw e
}
} }
} }
} }

View File

@ -1,5 +1,6 @@
package exh.md.handlers package exh.md.handlers
import eu.kanade.tachiyomi.data.database.models.Track
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.await
@ -13,6 +14,7 @@ import eu.kanade.tachiyomi.util.lang.withIOContext
import exh.md.handlers.serializers.ApiCovers import exh.md.handlers.serializers.ApiCovers
import exh.md.handlers.serializers.ApiMangaSerializer import exh.md.handlers.serializers.ApiMangaSerializer
import exh.md.utils.MdUtil import exh.md.utils.MdUtil
import exh.metadata.metadata.MangaDexSearchMetadata
import okhttp3.CacheControl import okhttp3.CacheControl
import okhttp3.Headers import okhttp3.Headers
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@ -20,6 +22,8 @@ import okhttp3.Request
import rx.Observable import rx.Observable
import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.ChapterInfo
import tachiyomi.source.model.MangaInfo import tachiyomi.source.model.MangaInfo
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: String, val forceLatestCovers: Boolean = false) { class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: String, val forceLatestCovers: Boolean = false) {
@ -115,6 +119,16 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, val lang: Str
} }
} }
suspend fun getTrackingInfo(track: Track, useLowQualityCovers: Boolean): Pair<Track, MangaDexSearchMetadata> {
val mangaUrl = MdUtil.mapMdIdToMangaUrl(MdUtil.getMangaId(track.tracking_url).toInt())
val manga = MangaInfo(mangaUrl, track.title)
val response = client.newCall(apiRequest(manga)).await()
val metadata = MangaDexSearchMetadata()
ApiMangaParser(lang).parseIntoMetadata(metadata, response, emptyList())
val remoteTrack = FollowsHandler(client, headers, Injekt.get(), useLowQualityCovers).fetchTrackingInfo(track.tracking_url)
return remoteTrack to metadata
}
private fun randomMangaRequest(): Request { private fun randomMangaRequest(): Request {
return GET(MdUtil.baseUrl + MdUtil.randMangaPage, cache = CacheControl.Builder().noCache().build()) return GET(MdUtil.baseUrl + MdUtil.randMangaPage, cache = CacheControl.Builder().noCache().build())
} }

View File

@ -40,6 +40,8 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() {
var follow_status: Int? = null var follow_status: Int? = null
var maxChapterNumber: Int? = null
override fun createMangaInfo(manga: MangaInfo): MangaInfo { override fun createMangaInfo(manga: MangaInfo): MangaInfo {
val key = mdUrl?.let { val key = mdUrl?.let {
try { try {