From 33a590d895eb1ede052a8de4c974a74d2ebb8462 Mon Sep 17 00:00:00 2001 From: Jobobby04 Date: Mon, 17 May 2021 12:45:33 -0400 Subject: [PATCH] Mangadex fixes --- .../tachiyomi/data/track/mdlist/MdList.kt | 2 + .../tachiyomi/source/online/all/MangaDex.kt | 57 +++++++++++++------ .../browse/source/browse/SourceFilterSheet.kt | 26 ++++----- .../ui/manga/chapter/ChaptersSettingsSheet.kt | 6 +- .../java/exh/md/handlers/ApiMangaParser.kt | 12 ++-- .../java/exh/md/handlers/FollowsHandler.kt | 9 +-- .../main/java/exh/md/handlers/MangaHandler.kt | 45 +++++++-------- .../main/java/exh/md/handlers/PageHandler.kt | 14 +++-- .../java/exh/md/handlers/PopularHandler.kt | 4 +- .../java/exh/md/handlers/SearchHandler.kt | 8 +-- .../java/exh/md/handlers/SimilarHandler.kt | 7 +-- .../java/exh/md/handlers/serializers/Auth.kt | 2 +- .../exh/md/network/MangaDexLoginHelper.kt | 6 +- app/src/main/java/exh/md/utils/MdUtil.kt | 42 ++++++-------- .../metadata/MangaDexSearchMetadata.kt | 2 +- .../metadata/base/RaisedSearchMetadata.kt | 4 +- 16 files changed, 135 insertions(+), 111 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt index 64d13de53..87928a3d5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/data/track/mdlist/MdList.kt @@ -59,6 +59,8 @@ class MdList(private val context: Context, id: Int) : TrackService(id) { if (remoteTrack.status != followStatus.int) { if (mdex.updateFollowStatus(MdUtil.getMangaId(track.tracking_url), followStatus)) { remoteTrack.status = followStatus.int + } else { + track.status = remoteTrack.status } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt index 4092c4644..b8e23d598 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/source/online/all/MangaDex.kt @@ -84,6 +84,25 @@ class MangaDex(delegate: HttpSource, val context: Context) : private fun useLowQualityThumbnail() = false // sourcePreferences.getInt(SHOW_THUMBNAIL_PREF, 0) == LOW_QUALITY + private val apiMangaParser by lazy { + ApiMangaParser(baseHttpClient, mdLang.lang) + } + private val apiChapterParser by lazy { + ApiChapterParser() + } + private val followsHandler by lazy { + FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, mdList) + } + private val mangaHandler by lazy { + MangaHandler(baseHttpClient, headers, mdLang.lang, apiMangaParser, followsHandler) + } + private val similarHandler by lazy { + SimilarHandler(baseHttpClient, mdLang.lang) + } + private val mangaPlusHandler by lazy { + MangaPlusHandler(network.client) + } + /*override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable = urlImportFetchSearchManga(context, query) { importIdToMdId(query) { @@ -114,28 +133,28 @@ class MangaDex(delegate: HttpSource, val context: Context) : }*/ override fun fetchMangaDetails(manga: SManga): Observable { - return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).fetchMangaDetailsObservable(manga, id) + return mangaHandler.fetchMangaDetailsObservable(manga, id, preferences.mangaDexForceLatestCovers().get()) } override suspend fun getMangaDetails(manga: MangaInfo): MangaInfo { - return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).getMangaDetails(manga, id) + return mangaHandler.getMangaDetails(manga, id, preferences.mangaDexForceLatestCovers().get()) } override fun fetchChapterList(manga: SManga): Observable> { - return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).fetchChapterListObservable(manga) + return mangaHandler.fetchChapterListObservable(manga) } override suspend fun getChapterList(manga: MangaInfo): List { - return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).getChapterList(manga) + return mangaHandler.getChapterList(manga) } override fun fetchPageList(chapter: SChapter): Observable> { return if (chapter.scanlator == "MangaPlus") { - baseHttpClient.newCall(mangaPlusPageListRequest(chapter)) + mangaPlusHandler.client.newCall(mangaPlusPageListRequest(chapter)) .asObservableSuccess() .map { response -> - val chapterId = ApiChapterParser().externalParse(response) - MangaPlusHandler(baseHttpClient).fetchPageList(chapterId) + val chapterId = apiChapterParser.externalParse(response) + mangaPlusHandler.fetchPageList(chapterId) } } else super.fetchPageList(chapter) } @@ -146,7 +165,7 @@ class MangaDex(delegate: HttpSource, val context: Context) : override fun fetchImage(page: Page): Observable { return if (page.imageUrl?.contains("mangaplus", true) == true) { - MangaPlusHandler(network.client).client.newCall(GET(page.imageUrl!!, headers)) + mangaPlusHandler.client.newCall(GET(page.imageUrl!!, headers)) .asObservableSuccess() } else super.fetchImage(page) } @@ -158,11 +177,11 @@ class MangaDex(delegate: HttpSource, val context: Context) : } override suspend fun parseIntoMetadata(metadata: MangaDexSearchMetadata, input: Response) { - ApiMangaParser(baseHttpClient, mdLang.lang).parseIntoMetadata(metadata, input, emptyList()) + apiMangaParser.parseIntoMetadata(metadata, input, emptyList()) } override suspend fun fetchFollows(page: Int): MangasPage { - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).fetchFollows(page) + return followsHandler.fetchFollows(page) } override val requiresLogin: Boolean = false @@ -199,6 +218,8 @@ class MangaDex(delegate: HttpSource, val context: Context) : loginHelper.logout(MdUtil.getAuthHeaders(Headers.Builder().build(), preferences, mdList)) } catch (e: NoSessionException) { true + } catch (e: Exception) { + e.message?.equals("HTTP error 405") ?: false } return if (result) { @@ -208,30 +229,30 @@ class MangaDex(delegate: HttpSource, val context: Context) : } override suspend fun fetchAllFollows(): List> { - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).fetchAllFollows() + return followsHandler.fetchAllFollows() } suspend fun updateReadingProgress(track: Track): Boolean { - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).updateReadingProgress(track) + return followsHandler.updateReadingProgress(track) } suspend fun updateRating(track: Track): Boolean { - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).updateRating(track) + return followsHandler.updateRating(track) } override suspend fun fetchTrackingInfo(url: String): Track { if (!isLogged()) { throw Exception("Not Logged in") } - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).fetchTrackingInfo(url) + return followsHandler.fetchTrackingInfo(url) } suspend fun getTrackingAndMangaInfo(track: Track): Pair { - return MangaHandler(baseHttpClient, headers, mdLang.lang).getTrackingInfo(track, useLowQualityThumbnail(), mdList) + return mangaHandler.getTrackingInfo(track, mdList) } override suspend fun updateFollowStatus(mangaID: String, followStatus: FollowStatus): Boolean { - return FollowsHandler(baseHttpClient, headers, preferences, mdLang.lang, useLowQualityThumbnail(), mdList).updateFollowStatus(mangaID, followStatus) + return followsHandler.updateFollowStatus(mangaID, followStatus) } override fun getFilterHeader(controller: BaseController<*>, onClick: () -> Unit): MangaDexFabHeaderAdapter { @@ -239,11 +260,11 @@ class MangaDex(delegate: HttpSource, val context: Context) : } override suspend fun fetchRandomMangaUrl(): String { - return MangaHandler(baseHttpClient, headers, mdLang.lang).fetchRandomMangaId() + return mangaHandler.fetchRandomMangaId() } suspend fun getMangaSimilar(manga: MangaInfo): MangasPage { - return SimilarHandler(baseHttpClient, mdLang.lang, preferences, useLowQualityThumbnail()).getSimilar(manga) + return similarHandler.getSimilar(manga) } // todo remove when mangadex gets it cover api diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt index d3833bdea..f51d07a5c 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceFilterSheet.kt @@ -4,7 +4,6 @@ import android.app.Activity import android.content.Context import android.util.AttributeSet import android.view.LayoutInflater -import android.view.View import android.view.ViewGroup import androidx.core.view.isVisible import androidx.recyclerview.widget.ConcatAdapter @@ -21,6 +20,7 @@ import eu.kanade.tachiyomi.widget.SimpleNavigationView import eu.kanade.tachiyomi.widget.sheet.BaseBottomSheetDialog import exh.savedsearches.EXHSavedSearch import exh.source.getMainSource +import exh.util.under class SourceFilterSheet( activity: Activity, @@ -155,22 +155,20 @@ class SourceFilterSheet( private fun getSavedSearchesChips(searches: List): List { recycler.post { - binding.saveSearchBtn.visibility = if (searches.size < MAX_SAVED_SEARCHES) View.VISIBLE else View.GONE + binding.saveSearchBtn.isVisible = searches.size under MAX_SAVED_SEARCHES } - val chips: MutableList = mutableListOf() - - searches.withIndex().sortedBy { it.value.name }.forEach { (index, search) -> - val chip = Chip(context).apply { - text = search.name - setOnClickListener { onSavedSearchClicked(index) } - setOnLongClickListener { - onSavedSearchDeleteClicked(index, search.name); true + return searches.withIndex() + .sortedBy { it.value.name } + .map { (index, search) -> + Chip(context).apply { + text = search.name + setOnClickListener { onSavedSearchClicked(index) } + setOnLongClickListener { + onSavedSearchDeleteClicked(index, search.name); true + } } } - - chips += chip - } - return chips.sortedBy { it.text.toString().toLowerCase() } + .sortedBy { it.text.toString().toLowerCase() } } fun hideFilterButton() { diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt index 6c3266402..7d88f2aa2 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/manga/chapter/ChaptersSettingsSheet.kt @@ -114,7 +114,11 @@ class ChaptersSettingsSheet( if (item is Item.DrawableSelection) { val scanlators = presenter.allChapterScanlators.toList() val filteredScanlators = presenter.manga.filtered_scanlators?.let { MdUtil.getScanlators(it) } - val preselected = if (filteredScanlators.isNullOrEmpty()) scanlators.mapIndexed { index, _ -> index }.toIntArray() else filteredScanlators.map { scanlators.indexOf(it) }.toIntArray() + val preselected = if (filteredScanlators.isNullOrEmpty()) { + scanlators.mapIndexed { index, _ -> index } + } else { + filteredScanlators.map { scanlators.indexOf(it) } + }.toIntArray() MaterialDialog(context) .title(R.string.select_scanlators) diff --git a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt index 38efc3d6d..523c3c1af 100644 --- a/app/src/main/java/exh/md/handlers/ApiMangaParser.kt +++ b/app/src/main/java/exh/md/handlers/ApiMangaParser.kt @@ -23,7 +23,6 @@ import okhttp3.Response import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.MangaInfo import uy.kohesive.injekt.injectLazy -import java.util.Date import java.util.Locale class ApiMangaParser(val client: OkHttpClient, private val lang: String) { @@ -138,7 +137,7 @@ class ApiMangaParser(val client: OkHttpClient, private val lang: String) { cover = "https://coverapi.orell.dev/api/v1/mal/manga/$myAnimeListId/cover" } if (cover == null) { - cover = "https://coverapi.orell.dev/api/v1/mdaltimage/manga/$mdUuid/cover" + cover = MdUtil.formThumbUrl(mdUuid.toString()) } // val filteredChapters = filterChapterForChecking(networkApiManga) @@ -155,8 +154,11 @@ class ApiMangaParser(val client: OkHttpClient, private val lang: String) { // things that will go with the genre tags but aren't actually genre val nonGenres = listOfNotNull( - networkManga.publicationDemographic?.let { RaisedTag("Demographic", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) }, - networkManga.contentRating?.let { RaisedTag("Content Rating", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) }, + networkManga.publicationDemographic + ?.let { RaisedTag("Demographic", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) }, + networkManga.contentRating + ?.takeUnless { it == "safe" } + ?.let { RaisedTag("Content Rating", it.capitalize(Locale.US), MangaDexSearchMetadata.TAG_TYPE_DEFAULT) }, ) val genres = nonGenres + networkManga.tags @@ -239,7 +241,7 @@ class ApiMangaParser(val client: OkHttpClient, private val lang: String) { } fun chapterListParse(chapterListResponse: List, groupMap: Map): List { - val now = Date().time + val now = System.currentTimeMillis() return chapterListResponse.asSequence() .map { diff --git a/app/src/main/java/exh/md/handlers/FollowsHandler.kt b/app/src/main/java/exh/md/handlers/FollowsHandler.kt index 3d5077ae8..9210c6e22 100644 --- a/app/src/main/java/exh/md/handlers/FollowsHandler.kt +++ b/app/src/main/java/exh/md/handlers/FollowsHandler.kt @@ -16,6 +16,7 @@ import exh.md.handlers.serializers.MangaListResponse import exh.md.handlers.serializers.MangaResponse import exh.md.handlers.serializers.MangaStatusListResponse import exh.md.handlers.serializers.MangaStatusResponse +import exh.md.handlers.serializers.ResultResponse import exh.md.handlers.serializers.UpdateReadingStatus import exh.md.utils.FollowStatus import exh.md.utils.MdUtil @@ -38,7 +39,6 @@ class FollowsHandler( val headers: Headers, val preferences: PreferencesHelper, private val lang: String, - private val useLowQualityCovers: Boolean, private val mdList: MdList ) { @@ -78,8 +78,7 @@ class FollowsHandler( return response.map { MdUtil.createMangaEntry( it, - lang, - useLowQualityCovers + lang ).toSManga() to MangaDexSearchMetadata().apply { followStatus = FollowStatus.fromDex(statuses[it.data.id]).int } @@ -135,7 +134,9 @@ class FollowsHandler( jsonString.toRequestBody("application/json".toMediaType()) ) ).await() - postResult.isSuccessful + + val body = postResult.parseAs(MdUtil.jsonParser) + body.result == "ok" } } diff --git a/app/src/main/java/exh/md/handlers/MangaHandler.kt b/app/src/main/java/exh/md/handlers/MangaHandler.kt index d7ee76d88..7982135fc 100644 --- a/app/src/main/java/exh/md/handlers/MangaHandler.kt +++ b/app/src/main/java/exh/md/handlers/MangaHandler.kt @@ -25,18 +25,22 @@ import okhttp3.Request import rx.Observable import tachiyomi.source.model.ChapterInfo import tachiyomi.source.model.MangaInfo -import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get -class MangaHandler(val client: OkHttpClient, val headers: Headers, private val lang: String, private val forceLatestCovers: Boolean = false) { +class MangaHandler( + val client: OkHttpClient, + val headers: Headers, + private val lang: String, + private val apiMangaParser: ApiMangaParser, + private val followsHandler: FollowsHandler +) { - suspend fun fetchMangaAndChapterDetails(manga: MangaInfo, sourceId: Long): Pair> { + suspend fun fetchMangaAndChapterDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): Pair> { return withIOContext { val response = client.newCall(mangaRequest(manga)).await() val covers = getCovers(manga, forceLatestCovers) - val parser = ApiMangaParser(client, lang) - parser.parseToManga(manga, response, covers, sourceId) to getChapterList(manga) + apiMangaParser.parseToManga(manga, response, covers, sourceId) to getChapterList(manga) } } @@ -45,7 +49,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, private val l val covers = client.newCall(coverRequest(manga)).await().parseAs(MdUtil.jsonParser) return covers.data.map { it.url } } else {*/ - return emptyList() + return emptyList() // } } @@ -53,19 +57,19 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, private val l return withIOContext { val request = GET(MdUtil.chapterUrl + urlChapterId) val response = client.newCall(request).await() - ApiMangaParser(client, lang).chapterParseForMangaId(response) + apiMangaParser.chapterParseForMangaId(response) } } - suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long): MangaInfo { + suspend fun getMangaDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): MangaInfo { val response = withIOContext { client.newCall(mangaRequest(manga)).await() } val covers = withIOContext { getCovers(manga, forceLatestCovers) } - return ApiMangaParser(client, lang).parseToManga(manga, response, covers, sourceId) + return apiMangaParser.parseToManga(manga, response, covers, sourceId) } - fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long): Observable { + fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long, forceLatestCovers: Boolean): Observable { return runAsObservable({ - getMangaDetails(manga.toMangaInfo(), sourceId).toSManga() + getMangaDetails(manga.toMangaInfo(), sourceId, forceLatestCovers).toSManga() }) } @@ -81,7 +85,7 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, private val l val groupMap = getGroupMap(results) - ApiMangaParser(client, lang).chapterListParse(results, groupMap) + apiMangaParser.chapterListParse(results, groupMap) } } @@ -109,29 +113,22 @@ class MangaHandler(val client: OkHttpClient, val headers: Headers, private val l suspend fun fetchRandomMangaId(): String { return withIOContext { val response = client.newCall(randomMangaRequest()).await() - ApiMangaParser(client, lang).randomMangaIdParse(response) + apiMangaParser.randomMangaIdParse(response) } } - suspend fun getTrackingInfo(track: Track, useLowQualityCovers: Boolean, mdList: MdList): Pair { + suspend fun getTrackingInfo(track: Track, mdList: MdList): Pair { return withIOContext { val metadata = async { - val mangaUrl = "/manga/" + MdUtil.getMangaId(track.tracking_url) + 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() - ApiMangaParser(client, lang).parseIntoMetadata(metadata, response, emptyList()) + apiMangaParser.parseIntoMetadata(metadata, response, emptyList()) metadata } val remoteTrack = async { - FollowsHandler( - client, - headers, - Injekt.get(), - lang, - useLowQualityCovers, - mdList - ).fetchTrackingInfo(track.tracking_url) + followsHandler.fetchTrackingInfo(track.tracking_url) } remoteTrack.await() to null } diff --git a/app/src/main/java/exh/md/handlers/PageHandler.kt b/app/src/main/java/exh/md/handlers/PageHandler.kt index a86873cdc..9bc7cd6cf 100644 --- a/app/src/main/java/exh/md/handlers/PageHandler.kt +++ b/app/src/main/java/exh/md/handlers/PageHandler.kt @@ -11,22 +11,28 @@ import okhttp3.OkHttpClient import okhttp3.Request import rx.Observable -class PageHandler(val client: OkHttpClient, val headers: Headers, private val dataSaver: Boolean) { +class PageHandler( + val client: OkHttpClient, + val headers: Headers, + private val dataSaver: Boolean, + private val apiChapterParser: ApiChapterParser, + private val mangaPlusHandler: MangaPlusHandler +) { fun fetchPageList(chapter: SChapter): Observable> { if (chapter.scanlator.equals("MangaPlus")) { return client.newCall(pageListRequest(chapter)) .asObservableSuccess() .map { response -> - val chapterId = ApiChapterParser().externalParse(response) - MangaPlusHandler(client).fetchPageList(chapterId) + val chapterId = apiChapterParser.externalParse(response) + mangaPlusHandler.fetchPageList(chapterId) } } return client.newCall(pageListRequest(chapter)) .asObservableSuccess() .map { response -> val host = MdUtil.atHomeUrlHostUrl("${MdUtil.atHomeUrl}/${MdUtil.getChapterId(chapter.url)}", client) - ApiChapterParser().pageListParse(response, host, dataSaver) + apiChapterParser.pageListParse(response, host, dataSaver) } } diff --git a/app/src/main/java/exh/md/handlers/PopularHandler.kt b/app/src/main/java/exh/md/handlers/PopularHandler.kt index b6ae49893..e1173eb57 100644 --- a/app/src/main/java/exh/md/handlers/PopularHandler.kt +++ b/app/src/main/java/exh/md/handlers/PopularHandler.kt @@ -18,7 +18,7 @@ import rx.Observable /** * Returns the latest manga from the updates url since it actually respects the users settings */ -class PopularHandler(val client: OkHttpClient, private val headers: Headers, private val lang: String, private val useLowQualityCovers: Boolean) { +class PopularHandler(val client: OkHttpClient, private val headers: Headers, private val lang: String) { fun fetchPopularManga(page: Int): Observable { return client.newCall(popularMangaRequest(page)) @@ -42,7 +42,7 @@ class PopularHandler(val client: OkHttpClient, private val headers: Headers, pri private fun popularMangaParse(response: Response): MangasPage { val mlResponse = response.parseAs(MdUtil.jsonParser) val hasMoreResults = mlResponse.limit + mlResponse.offset < mlResponse.total - val mangaList = mlResponse.results.map { MdUtil.createMangaEntry(it, lang, useLowQualityCovers).toSManga() } + val mangaList = mlResponse.results.map { MdUtil.createMangaEntry(it, lang).toSManga() } return MangasPage(mangaList, hasMoreResults) } } diff --git a/app/src/main/java/exh/md/handlers/SearchHandler.kt b/app/src/main/java/exh/md/handlers/SearchHandler.kt index 6fc6bd487..7f4e27daa 100644 --- a/app/src/main/java/exh/md/handlers/SearchHandler.kt +++ b/app/src/main/java/exh/md/handlers/SearchHandler.kt @@ -18,7 +18,7 @@ import okhttp3.Request import okhttp3.Response import rx.Observable -class SearchHandler(val client: OkHttpClient, private val headers: Headers, val lang: String, val filterHandler: FilterHandler, private val useLowQualityCovers: Boolean) { +class SearchHandler(val client: OkHttpClient, private val headers: Headers, val lang: String, val filterHandler: FilterHandler, private val apiMangaParser: ApiMangaParser) { fun fetchSearchManga(page: Int, query: String, filters: FilterList, sourceId: Long): Observable { return if (query.startsWith(PREFIX_ID_SEARCH)) { @@ -28,8 +28,8 @@ class SearchHandler(val client: OkHttpClient, private val headers: Headers, val .flatMap { response -> runAsObservable({ val mangaResponse = response.parseAs(MdUtil.jsonParser) - val details = ApiMangaParser(client, lang) - .parseToManga(MdUtil.createMangaEntry(mangaResponse, lang, useLowQualityCovers), response, emptyList(), sourceId).toSManga() + val details = apiMangaParser + .parseToManga(MdUtil.createMangaEntry(mangaResponse, lang), response, emptyList(), sourceId).toSManga() MangasPage(listOf(details), false) }) } @@ -45,7 +45,7 @@ class SearchHandler(val client: OkHttpClient, private val headers: Headers, val private fun searchMangaParse(response: Response): MangasPage { val mlResponse = response.parseAs(MdUtil.jsonParser) val hasMoreResults = mlResponse.limit + mlResponse.offset < mlResponse.total - val mangaList = mlResponse.results.map { MdUtil.createMangaEntry(it, lang, useLowQualityCovers).toSManga() } + val mangaList = mlResponse.results.map { MdUtil.createMangaEntry(it, lang).toSManga() } return MangasPage(mangaList, hasMoreResults) } diff --git a/app/src/main/java/exh/md/handlers/SimilarHandler.kt b/app/src/main/java/exh/md/handlers/SimilarHandler.kt index b89121530..e14a5e2e5 100644 --- a/app/src/main/java/exh/md/handlers/SimilarHandler.kt +++ b/app/src/main/java/exh/md/handlers/SimilarHandler.kt @@ -1,6 +1,5 @@ package exh.md.handlers -import eu.kanade.tachiyomi.data.preference.PreferencesHelper import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.await import eu.kanade.tachiyomi.network.parseAs @@ -15,7 +14,7 @@ import okhttp3.Request import okhttp3.Response import tachiyomi.source.model.MangaInfo -class SimilarHandler(val client: OkHttpClient, val lang: String, val preferences: PreferencesHelper, private val useLowQualityCovers: Boolean) { +class SimilarHandler(val client: OkHttpClient, val lang: String) { suspend fun getSimilar(manga: MangaInfo): MangasPage { val response = client.newCall(similarMangaRequest(manga)).await() @@ -30,9 +29,9 @@ class SimilarHandler(val client: OkHttpClient, val lang: String, val preferences private fun similarMangaParse(response: Response): MangasPage { val mangaList = response.parseAs().matches.map { SManga.create().apply { - url = "/manga/" + it.id + url = MdUtil.buildMangaUrl(it.id) title = MdUtil.cleanString(it.title[lang] ?: it.title["en"]!!) - thumbnail_url = "https://coverapi.orell.dev/api/v1/mdaltimage/manga/${it.id}/cover" + thumbnail_url = MdUtil.formThumbUrl(url) } } return MangasPage(mangaList, false) diff --git a/app/src/main/java/exh/md/handlers/serializers/Auth.kt b/app/src/main/java/exh/md/handlers/serializers/Auth.kt index c4807b509..2692707f3 100644 --- a/app/src/main/java/exh/md/handlers/serializers/Auth.kt +++ b/app/src/main/java/exh/md/handlers/serializers/Auth.kt @@ -24,7 +24,7 @@ data class LoginBodyToken(val session: String, val refresh: String) * Response after logout */ @Serializable -data class LogoutResponse(val result: String) +data class ResultResponse(val result: String) /** * Check if session token is valid diff --git a/app/src/main/java/exh/md/network/MangaDexLoginHelper.kt b/app/src/main/java/exh/md/network/MangaDexLoginHelper.kt index cd3ed4d24..1b4afad2a 100644 --- a/app/src/main/java/exh/md/network/MangaDexLoginHelper.kt +++ b/app/src/main/java/exh/md/network/MangaDexLoginHelper.kt @@ -12,8 +12,8 @@ import exh.md.handlers.serializers.CheckTokenResponse import exh.md.handlers.serializers.LoginBodyToken import exh.md.handlers.serializers.LoginRequest import exh.md.handlers.serializers.LoginResponse -import exh.md.handlers.serializers.LogoutResponse import exh.md.handlers.serializers.RefreshTokenRequest +import exh.md.handlers.serializers.ResultResponse import exh.md.utils.MdUtil import kotlinx.serialization.SerializationException import kotlinx.serialization.encodeToString @@ -78,7 +78,7 @@ class MangaDexLoginHelper(val client: OkHttpClient, val preferences: Preferences null } - if (response.code == 200 && loginResponse != null) { + if (response.code == 200 && loginResponse != null && loginResponse.result == "ok") { LoginResult.Success(loginResponse.token) } else { LoginResult.Failure() @@ -103,7 +103,7 @@ class MangaDexLoginHelper(val client: OkHttpClient, val preferences: Preferences suspend fun logout(authHeaders: Headers): Boolean { val response = client.newCall(GET(MdUtil.logoutUrl, authHeaders, CacheControl.FORCE_NETWORK)).await() - val body = response.parseAs(MdUtil.jsonParser) + val body = response.parseAs(MdUtil.jsonParser) return body.result == "ok" } } diff --git a/app/src/main/java/exh/md/utils/MdUtil.kt b/app/src/main/java/exh/md/utils/MdUtil.kt index 93b5e7b3d..1273b5627 100644 --- a/app/src/main/java/exh/md/utils/MdUtil.kt +++ b/app/src/main/java/exh/md/utils/MdUtil.kt @@ -202,13 +202,12 @@ class MdUtil { "(zh-Hant)", ) - // guess the thumbnail url is .jpg this has a ~80% success rate - fun formThumbUrl(mangaUrl: String, lowQuality: Boolean): String { - var ext = ".jpg" - if (lowQuality) { - ext = ".thumb$ext" - } - return cdnUrl + "/images/manga/" + getMangaId(mangaUrl) + ext + fun buildMangaUrl(mangaUuid: String): String { + return "/manga/$mangaUuid" + } + + fun formThumbUrl(mangaUrl: String): String { + return "https://coverapi.orell.dev/api/v1/mdaltimage/manga/${getMangaId(mangaUrl)}/cover" } // Get the ID from the manga url @@ -255,9 +254,9 @@ class MdUtil { return baseUrl + attr } - fun getScanlators(scanlators: String?): List { - if (scanlators.isNullOrBlank()) return emptyList() - return scanlators.split(scanlatorSeparator).distinct() + fun getScanlators(scanlators: String?): Set { + if (scanlators.isNullOrBlank()) return emptySet() + return scanlators.split(scanlatorSeparator).toSet() } fun getScanlatorString(scanlators: Set): String { @@ -301,32 +300,27 @@ class MdUtil { fun parseDate(dateAsString: String): Long = dateFormatter.parse(dateAsString)?.time ?: 0 - fun createMangaEntry(json: MangaResponse, lang: String, lowQualityCovers: Boolean): MangaInfo { - val key = "/manga/" + json.data.id + fun createMangaEntry(json: MangaResponse, lang: String): MangaInfo { + val key = buildMangaUrl(json.data.id) return MangaInfo( key = key, title = cleanString(json.data.attributes.title[lang] ?: json.data.attributes.title["en"]!!), - cover = formThumbUrl(key, lowQualityCovers) + cover = formThumbUrl(key) ) } - fun sessionToken(preferences: PreferencesHelper, mdList: MdList) = preferences.trackToken(mdList).get().nullIfBlank()?.let { + fun getLoginBody(preferences: PreferencesHelper, mdList: MdList) = preferences.trackToken(mdList).get().nullIfBlank()?.let { try { jsonParser.decodeFromString(it) } catch (e: SerializationException) { - xLogD("Unable to load session token") + xLogD("Unable to load login body") null } - }?.session + } - fun refreshToken(preferences: PreferencesHelper, mdList: MdList) = preferences.trackToken(mdList).get().nullIfBlank()?.let { - try { - jsonParser.decodeFromString(it) - } catch (e: SerializationException) { - xLogD("Unable to load session token") - null - } - }?.refresh + fun sessionToken(preferences: PreferencesHelper, mdList: MdList) = getLoginBody(preferences, mdList)?.session + + fun refreshToken(preferences: PreferencesHelper, mdList: MdList) = getLoginBody(preferences, mdList)?.refresh fun updateLoginToken(token: LoginBodyToken, preferences: PreferencesHelper, mdList: MdList) { preferences.trackToken(mdList).set(jsonParser.encodeToString(token)) diff --git a/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt index 8b18fd3e8..c858ef1bc 100644 --- a/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/MangaDexSearchMetadata.kt @@ -44,7 +44,7 @@ class MangaDexSearchMetadata : RaisedSearchMetadata() { // var maxChapterNumber: Int? = null override fun createMangaInfo(manga: MangaInfo): MangaInfo { - val key = mdUuid?.let { "/manga/$it" } + val key = mdUuid?.let { MdUtil.buildMangaUrl(it) } val title = title diff --git a/app/src/main/java/exh/metadata/metadata/base/RaisedSearchMetadata.kt b/app/src/main/java/exh/metadata/metadata/base/RaisedSearchMetadata.kt index 6c522c433..436350c83 100644 --- a/app/src/main/java/exh/metadata/metadata/base/RaisedSearchMetadata.kt +++ b/app/src/main/java/exh/metadata/metadata/base/RaisedSearchMetadata.kt @@ -146,11 +146,11 @@ abstract class RaisedSearchMetadata { const val TAG_TYPE_VIRTUAL = -2 fun MutableList.toGenreString() = - (this).filter { it.type != TAG_TYPE_VIRTUAL } + this.filter { it.type != TAG_TYPE_VIRTUAL } .joinToString { (if (it.namespace != null) "${it.namespace}: " else "") + it.name } fun MutableList.toGenreList() = - (this).filter { it.type != TAG_TYPE_VIRTUAL } + this.filter { it.type != TAG_TYPE_VIRTUAL } .map { (if (it.namespace != null) "${it.namespace}: " else "") + it.name } private val module = SerializersModule {