Mangadex fixes

This commit is contained in:
Jobobby04 2021-05-17 12:45:33 -04:00
parent bc871cd2ee
commit 33a590d895
16 changed files with 135 additions and 111 deletions

View File

@ -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
}
}

View File

@ -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<MangasPage> =
urlImportFetchSearchManga(context, query) {
importIdToMdId(query) {
@ -114,28 +133,28 @@ class MangaDex(delegate: HttpSource, val context: Context) :
}*/
override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
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<List<SChapter>> {
return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).fetchChapterListObservable(manga)
return mangaHandler.fetchChapterListObservable(manga)
}
override suspend fun getChapterList(manga: MangaInfo): List<ChapterInfo> {
return MangaHandler(baseHttpClient, headers, mdLang.lang, preferences.mangaDexForceLatestCovers().get()).getChapterList(manga)
return mangaHandler.getChapterList(manga)
}
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
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<Response> {
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<Pair<SManga, MangaDexSearchMetadata>> {
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<Track, MangaDexSearchMetadata?> {
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

View File

@ -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<EXHSavedSearch>): List<Chip> {
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<Chip> = 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() {

View File

@ -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)

View File

@ -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<ChapterResponse>, groupMap: Map<String, String>): List<ChapterInfo> {
val now = Date().time
val now = System.currentTimeMillis()
return chapterListResponse.asSequence()
.map {

View File

@ -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<ResultResponse>(MdUtil.jsonParser)
body.result == "ok"
}
}

View File

@ -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<MangaInfo, List<ChapterInfo>> {
suspend fun fetchMangaAndChapterDetails(manga: MangaInfo, sourceId: Long, forceLatestCovers: Boolean): Pair<MangaInfo, List<ChapterInfo>> {
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<ApiCovers>(MdUtil.jsonParser)
return covers.data.map { it.url }
} else {*/
return emptyList<String>()
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<SManga> {
fun fetchMangaDetailsObservable(manga: SManga, sourceId: Long, forceLatestCovers: Boolean): Observable<SManga> {
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<Track, MangaDexSearchMetadata?> {
suspend fun getTrackingInfo(track: Track, mdList: MdList): Pair<Track, MangaDexSearchMetadata?> {
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
}

View File

@ -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<List<Page>> {
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)
}
}

View File

@ -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<MangasPage> {
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<MangaListResponse>(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)
}
}

View File

@ -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<MangasPage> {
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<MangaResponse>(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<MangaListResponse>(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)
}

View File

@ -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<SimilarMangaResponse>().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)

View File

@ -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

View File

@ -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<LogoutResponse>(MdUtil.jsonParser)
val body = response.parseAs<ResultResponse>(MdUtil.jsonParser)
return body.result == "ok"
}
}

View File

@ -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<String> {
if (scanlators.isNullOrBlank()) return emptyList()
return scanlators.split(scanlatorSeparator).distinct()
fun getScanlators(scanlators: String?): Set<String> {
if (scanlators.isNullOrBlank()) return emptySet()
return scanlators.split(scanlatorSeparator).toSet()
}
fun getScanlatorString(scanlators: Set<String>): 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<LoginBodyToken>(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<LoginBodyToken>(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))

View File

@ -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

View File

@ -146,11 +146,11 @@ abstract class RaisedSearchMetadata {
const val TAG_TYPE_VIRTUAL = -2
fun MutableList<RaisedTag>.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<RaisedTag>.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 {