Refactor the MangaDex code a bit. (#13703)

This commit is contained in:
Alessandro Jean 2022-10-03 18:35:21 -03:00 committed by GitHub
parent 9b7e28848b
commit c8adaa2f2a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 203 additions and 291 deletions

View File

@ -6,7 +6,7 @@ ext {
extName = 'MangaDex' extName = 'MangaDex'
pkgNameSuffix = 'all.mangadex' pkgNameSuffix = 'all.mangadex'
extClass = '.MangaDexFactory' extClass = '.MangaDexFactory'
extVersionCode = 168 extVersionCode = 169
isNsfw = true isNsfw = true
} }

View File

@ -40,7 +40,7 @@ object MDConstants {
const val prefixUsrSearch = "usr:" const val prefixUsrSearch = "usr:"
const val prefixListSearch = "list:" const val prefixListSearch = "list:"
const val coverQualityPref = "thumbnailQuality" private const val coverQualityPref = "thumbnailQuality"
fun getCoverQualityPreferenceKey(dexLang: String): String { fun getCoverQualityPreferenceKey(dexLang: String): String {
return "${coverQualityPref}_$dexLang" return "${coverQualityPref}_$dexLang"
@ -53,7 +53,7 @@ object MDConstants {
fun getCoverQualityPreferenceDefaultValue() = getCoverQualityPreferenceEntryValues()[0] fun getCoverQualityPreferenceDefaultValue() = getCoverQualityPreferenceEntryValues()[0]
const val dataSaverPref = "dataSaverV5" private const val dataSaverPref = "dataSaverV5"
fun getDataSaverPreferenceKey(dexLang: String): String { fun getDataSaverPreferenceKey(dexLang: String): String {
return "${dataSaverPref}_$dexLang" return "${dataSaverPref}_$dexLang"
@ -108,9 +108,9 @@ object MDConstants {
return "${hasSanitizedUuidsPref}_$dexLang" return "${hasSanitizedUuidsPref}_$dexLang"
} }
const val tagGroupContent = "content" private const val tagGroupContent = "content"
const val tagGroupFormat = "format" private const val tagGroupFormat = "format"
const val tagGroupGenre = "genre" private const val tagGroupGenre = "genre"
const val tagGroupTheme = "theme" private const val tagGroupTheme = "theme"
val tagGroupsOrder = arrayOf(tagGroupContent, tagGroupFormat, tagGroupGenre, tagGroupTheme) val tagGroupsOrder = arrayOf(tagGroupContent, tagGroupFormat, tagGroupGenre, tagGroupTheme)
} }

View File

@ -45,6 +45,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
HttpSource() { HttpSource() {
override val name = MangaDexIntl.MANGADEX_NAME override val name = MangaDexIntl.MANGADEX_NAME
override val baseUrl = "https://mangadex.org" override val baseUrl = "https://mangadex.org"
override val supportsLatest = true override val supportsLatest = true
@ -71,36 +72,14 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
// POPULAR Manga Section // POPULAR Manga Section
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply { val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
addQueryParameter("order[followedCount]", "desc") .addQueryParameter("order[followedCount]", "desc")
addQueryParameter("availableTranslatedLanguage[]", dexLang) .addQueryParameter("availableTranslatedLanguage[]", dexLang)
addQueryParameter("limit", MDConstants.mangaLimit.toString()) .addQueryParameter("limit", MDConstants.mangaLimit.toString())
addQueryParameter("offset", helper.getMangaListOffset(page)) .addQueryParameter("offset", helper.getMangaListOffset(page))
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
.addQueryParameter("contentRating[]", preferences.contentRating)
addQueryParameter( .addQueryParameter("originalLanguage[]", preferences.originalLanguages)
"contentRating[]",
preferences.getStringSet(
MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults
)
)
val originalLanguages = preferences.getStringSet(
MDConstants.getOriginalLanguagePrefKey(dexLang),
MDConstants.originalLanguagePrefDefaults
)
addQueryParameter("originalLanguage[]", originalLanguages)
// Dex has zh and zh-hk for Chinese manhua
if (MDConstants.originalLanguagePrefValChinese in originalLanguages!!) {
addQueryParameter(
"originalLanguage[]",
MDConstants.originalLanguagePrefValChineseHk
)
}
}
return GET( return GET(
url = url.build().toString(), url = url.build().toString(),
@ -117,12 +96,12 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
val mangaListDto = response.parseAs<MangaListDto>() val mangaListDto = response.parseAs<MangaListDto>()
val hasMoreResults = mangaListDto.limit + mangaListDto.offset < mangaListDto.total val hasMoreResults = mangaListDto.limit + mangaListDto.offset < mangaListDto.total
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "") val coverSuffix = preferences.coverQuality
val mangaList = mangaListDto.data.map { mangaDataDto -> val mangaList = mangaListDto.data.map { mangaDataDto ->
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto -> val fileName = mangaDataDto.relationships
relationshipDto.type.equals(MDConstants.coverArt, true) .firstOrNull { it.type.equals(MDConstants.coverArt, true) }
}?.attributes?.fileName ?.attributes?.fileName
helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang) helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang)
} }
@ -141,20 +120,11 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
.distinct() .distinct()
.toSet() .toSet()
val mangaUrl = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder().apply { val mangaUrl = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder()
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
addQueryParameter("limit", mangaIds.size.toString()) .addQueryParameter("limit", mangaIds.size.toString())
.addQueryParameter("contentRating[]", preferences.contentRating)
addQueryParameter( .addQueryParameter("ids[]", mangaIds)
"contentRating[]",
preferences.getStringSet(
MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults
)
)
addQueryParameter("ids[]", mangaIds)
}
val mangaRequest = GET(mangaUrl.build().toString(), headers, CacheControl.FORCE_NETWORK) val mangaRequest = GET(mangaUrl.build().toString(), headers, CacheControl.FORCE_NETWORK)
val mangaResponse = client.newCall(mangaRequest).execute() val mangaResponse = client.newCall(mangaRequest).execute()
@ -162,13 +132,12 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
val mangaDtoMap = mangaListDto.data.associateBy({ it.id }, { it }) val mangaDtoMap = mangaListDto.data.associateBy({ it.id }, { it })
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "") val coverSuffix = preferences.coverQuality
val mangaList = mangaIds.mapNotNull { mangaDtoMap[it] }.map { mangaDataDto -> val mangaList = mangaIds.mapNotNull { mangaDtoMap[it] }.map { mangaDataDto ->
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto -> val fileName = mangaDataDto.relationships
relationshipDto.type.equals(MDConstants.coverArt, true) .firstOrNull { it.type.equals(MDConstants.coverArt, true) }
relationshipDto.type.equals(MDConstants.coverArt, true) ?.attributes?.fileName
}?.attributes?.fileName
helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang) helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang)
} }
@ -176,56 +145,19 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
} }
override fun latestUpdatesRequest(page: Int): Request { override fun latestUpdatesRequest(page: Int): Request {
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply { val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder()
addQueryParameter("offset", helper.getLatestChapterOffset(page)) .addQueryParameter("offset", helper.getLatestChapterOffset(page))
addQueryParameter("limit", MDConstants.latestChapterLimit.toString()) .addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
addQueryParameter("translatedLanguage[]", dexLang) .addQueryParameter("translatedLanguage[]", dexLang)
addQueryParameter("order[publishAt]", "desc") .addQueryParameter("order[publishAt]", "desc")
addQueryParameter("includeFutureUpdates", "0") .addQueryParameter("includeFutureUpdates", "0")
.addQueryParameter("originalLanguage[]", preferences.originalLanguages)
val originalLanguages = preferences.getStringSet( .addQueryParameter("contentRating[]", preferences.contentRating)
MDConstants.getOriginalLanguagePrefKey(dexLang), .addQueryParameter(
MDConstants.originalLanguagePrefDefaults "excludedGroups[]",
MDConstants.defaultBlockedGroups + preferences.blockedGroups
) )
.addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
addQueryParameter("originalLanguage[]", originalLanguages)
// Dex has zh and zh-hk for Chinese manhua
if (MDConstants.originalLanguagePrefValChinese in originalLanguages!!) {
addQueryParameter(
"originalLanguage[]",
MDConstants.originalLanguagePrefValChineseHk
)
}
addQueryParameter(
"contentRating[]",
preferences.getStringSet(
MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults
)
)
val excludedGroups = MDConstants.defaultBlockedGroups +
preferences.getString(MDConstants.getBlockedGroupsPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
.orEmpty()
addQueryParameter("excludedGroups[]", excludedGroups)
val excludedUploaders = preferences
.getString(MDConstants.getBlockedUploaderPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
?.toSet()
addQueryParameter("excludedUploaders[]", excludedUploaders)
}
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK) return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
} }
@ -268,22 +200,20 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
} }
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val tempUrl = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply { val tempUrl = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
addQueryParameter("limit", MDConstants.mangaLimit.toString()) .addQueryParameter("limit", MDConstants.mangaLimit.toString())
addQueryParameter("offset", helper.getMangaListOffset(page)) .addQueryParameter("offset", helper.getMangaListOffset(page))
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
}
when { when {
query.startsWith(MDConstants.prefixIdSearch) -> { query.startsWith(MDConstants.prefixIdSearch) -> {
val url = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder().apply { val url = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder()
addQueryParameter("ids[]", query.removePrefix(MDConstants.prefixIdSearch)) .addQueryParameter("ids[]", query.removePrefix(MDConstants.prefixIdSearch))
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
addQueryParameter("contentRating[]", "safe") .addQueryParameter("contentRating[]", "safe")
addQueryParameter("contentRating[]", "suggestive") .addQueryParameter("contentRating[]", "suggestive")
addQueryParameter("contentRating[]", "erotica") .addQueryParameter("contentRating[]", "erotica")
addQueryParameter("contentRating[]", "pornographic") .addQueryParameter("contentRating[]", "pornographic")
}
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK) return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
} }
@ -294,9 +224,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
throw Exception(helper.intl.invalidGroupId) throw Exception(helper.intl.invalidGroupId)
} }
tempUrl.apply { tempUrl.addQueryParameter("group", groupID)
addQueryParameter("group", groupID)
}
} }
query.startsWith(MDConstants.prefixAuthSearch) -> { query.startsWith(MDConstants.prefixAuthSearch) -> {
@ -305,18 +233,16 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
throw Exception(helper.intl.invalidAuthorId) throw Exception(helper.intl.invalidAuthorId)
} }
tempUrl.apply { tempUrl
addQueryParameter("authors[]", authorID) .addQueryParameter("authors[]", authorID)
addQueryParameter("artists[]", authorID) .addQueryParameter("artists[]", authorID)
}
} }
else -> { else -> {
tempUrl.apply { val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
if (actualQuery.isNotBlank()) { if (actualQuery.isNotBlank()) {
addQueryParameter("title", actualQuery) tempUrl.addQueryParameter("title", actualQuery)
}
} }
} }
} }
@ -339,11 +265,10 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
val minIndex = (page - 1) * MDConstants.mangaLimit val minIndex = (page - 1) * MDConstants.mangaLimit
val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply { val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
addQueryParameter("limit", MDConstants.mangaLimit.toString()) .addQueryParameter("limit", MDConstants.mangaLimit.toString())
addQueryParameter("offset", "0") .addQueryParameter("offset", "0")
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
}
val ids = listDtoFiltered val ids = listDtoFiltered
.filterIndexed { i, _ -> i >= minIndex && i < (minIndex + MDConstants.mangaLimit) } .filterIndexed { i, _ -> i >= minIndex && i < (minIndex + MDConstants.mangaLimit) }
@ -368,12 +293,12 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
val mangaListDto = response.parseAs<MangaListDto>() val mangaListDto = response.parseAs<MangaListDto>()
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "") val coverSuffix = preferences.coverQuality
val mangaList = mangaListDto.data.map { mangaDataDto -> val mangaList = mangaListDto.data.map { mangaDataDto ->
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto -> val fileName = mangaDataDto.relationships
relationshipDto.type.equals(MDConstants.coverArt, true) .firstOrNull { it.type.equals(MDConstants.coverArt, true) }
}?.attributes?.fileName ?.attributes?.fileName
helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang) helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang)
} }
@ -381,57 +306,20 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
} }
private fun searchMangaUploaderRequest(page: Int, uploader: String): Request { private fun searchMangaUploaderRequest(page: Int, uploader: String): Request {
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply { val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder()
addQueryParameter("offset", helper.getLatestChapterOffset(page)) .addQueryParameter("offset", helper.getLatestChapterOffset(page))
addQueryParameter("limit", MDConstants.latestChapterLimit.toString()) .addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
addQueryParameter("translatedLanguage[]", dexLang) .addQueryParameter("translatedLanguage[]", dexLang)
addQueryParameter("order[publishAt]", "desc") .addQueryParameter("order[publishAt]", "desc")
addQueryParameter("includeFutureUpdates", "0") .addQueryParameter("includeFutureUpdates", "0")
addQueryParameter("uploader", uploader) .addQueryParameter("uploader", uploader)
.addQueryParameter("originalLanguage[]", preferences.originalLanguages)
val originalLanguages = preferences.getStringSet( .addQueryParameter("contentRating[]", preferences.contentRating)
MDConstants.getOriginalLanguagePrefKey(dexLang), .addQueryParameter(
MDConstants.originalLanguagePrefDefaults "excludedGroups[]",
MDConstants.defaultBlockedGroups + preferences.blockedGroups
) )
.addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
addQueryParameter("originalLanguage[]", originalLanguages)
// Dex has zh and zh-hk for Chinese manhua
if (MDConstants.originalLanguagePrefValChinese in originalLanguages!!) {
addQueryParameter(
"originalLanguage[]",
MDConstants.originalLanguagePrefValChineseHk
)
}
addQueryParameter(
"contentRating[]",
preferences.getStringSet(
MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults
)
)
val excludedGroups = MDConstants.defaultBlockedGroups +
preferences.getString(MDConstants.getBlockedGroupsPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
.orEmpty()
addQueryParameter("excludedGroups[]", excludedGroups)
val excludedUploaders = preferences
.getString(MDConstants.getBlockedUploaderPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
?.toSet()
addQueryParameter("excludedUploaders[]", excludedUploaders)
}
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK) return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
} }
@ -463,24 +351,22 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
throw Exception(helper.intl.migrateWarning) throw Exception(helper.intl.migrateWarning)
} }
val url = (MDConstants.apiUrl + manga.url).toHttpUrl().newBuilder().apply { val url = (MDConstants.apiUrl + manga.url).toHttpUrl().newBuilder()
addQueryParameter("includes[]", MDConstants.coverArt) .addQueryParameter("includes[]", MDConstants.coverArt)
addQueryParameter("includes[]", MDConstants.author) .addQueryParameter("includes[]", MDConstants.author)
addQueryParameter("includes[]", MDConstants.artist) .addQueryParameter("includes[]", MDConstants.artist)
}
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK) return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
} }
override fun mangaDetailsParse(response: Response): SManga { override fun mangaDetailsParse(response: Response): SManga {
val manga = response.parseAs<MangaDto>() val manga = response.parseAs<MangaDto>()
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
return helper.createManga( return helper.createManga(
manga.data, manga.data,
fetchSimpleChapterList(manga, dexLang), fetchSimpleChapterList(manga, dexLang),
dexLang, dexLang,
coverSuffix preferences.coverQuality
) )
} }
@ -488,7 +374,6 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
* get a quick-n-dirty list of the chapters to be used in determining the manga status. * get a quick-n-dirty list of the chapters to be used in determining the manga status.
* uses the 'aggregate' endpoint * uses the 'aggregate' endpoint
* @see MangaDexHelper.getPublicationStatus * @see MangaDexHelper.getPublicationStatus
* @see MangaDexHelper.doubleCheckChapters
* @see AggregateDto * @see AggregateDto
*/ */
private fun fetchSimpleChapterList(manga: MangaDto, langCode: String): List<String> { private fun fetchSimpleChapterList(manga: MangaDto, langCode: String): List<String> {
@ -525,32 +410,13 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
* Required because api is paged * Required because api is paged
*/ */
private fun actualChapterListRequest(mangaId: String, offset: Int): Request { private fun actualChapterListRequest(mangaId: String, offset: Int): Request {
val url = helper.getChapterEndpoint(mangaId, offset, dexLang).toHttpUrlOrNull()!!.newBuilder().apply { val url = helper.getChapterEndpoint(mangaId, offset, dexLang).toHttpUrl().newBuilder()
addQueryParameter("contentRating[]", "safe") .addQueryParameter("contentRating[]", "safe")
addQueryParameter("contentRating[]", "suggestive") .addQueryParameter("contentRating[]", "suggestive")
addQueryParameter("contentRating[]", "erotica") .addQueryParameter("contentRating[]", "erotica")
addQueryParameter("contentRating[]", "pornographic") .addQueryParameter("contentRating[]", "pornographic")
.addQueryParameter("excludedGroups[]", preferences.blockedGroups)
val excludedGroups = preferences .addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
.getString(MDConstants.getBlockedGroupsPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
?.toSet()
addQueryParameter("excludedGroups[]", excludedGroups)
val excludedUploaders = preferences
.getString(MDConstants.getBlockedUploaderPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
?.toSet()
addQueryParameter("excludedUploaders[]", excludedUploaders)
}
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK) return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
} }
@ -602,9 +468,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
} }
val chapterId = chapter.url.substringAfter("/chapter/") val chapterId = chapter.url.substringAfter("/chapter/")
val usingStandardHTTPS = val atHomeRequestUrl = if (preferences.forceStandardHttps) {
preferences.getBoolean(MDConstants.getStandardHttpsPreferenceKey(dexLang), false)
val atHomeRequestUrl = if (usingStandardHTTPS) {
"${MDConstants.apiUrl}/at-home/server/$chapterId?forcePort443=true" "${MDConstants.apiUrl}/at-home/server/$chapterId?forcePort443=true"
} else { } else {
"${MDConstants.apiUrl}/at-home/server/$chapterId" "${MDConstants.apiUrl}/at-home/server/$chapterId"
@ -617,14 +481,12 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
val atHomeRequestUrl = response.request.url val atHomeRequestUrl = response.request.url
val atHomeDto = response.parseAs<AtHomeDto>() val atHomeDto = response.parseAs<AtHomeDto>()
val host = atHomeDto.baseUrl val host = atHomeDto.baseUrl
val usingDataSaver =
preferences.getBoolean(MDConstants.getDataSaverPreferenceKey(dexLang), false)
// have to add the time, and url to the page because pages timeout within 30mins now // have to add the time, and url to the page because pages timeout within 30mins now
val now = Date().time val now = Date().time
val hash = atHomeDto.chapter.hash val hash = atHomeDto.chapter.hash
val pageSuffix = if (usingDataSaver) { val pageSuffix = if (preferences.useDataSaver) {
atHomeDto.chapter.dataSaver.map { "/data-saver/$hash/$it" } atHomeDto.chapter.dataSaver.map { "/data-saver/$hash/$it" }
} else { } else {
atHomeDto.chapter.data.map { "/data/$hash/$it" } atHomeDto.chapter.data.map { "/data/$hash/$it" }
@ -642,6 +504,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
override fun imageUrlParse(response: Response): String = "" override fun imageUrlParse(response: Response): String = ""
@Suppress("UNCHECKED_CAST")
override fun setupPreferenceScreen(screen: PreferenceScreen) { override fun setupPreferenceScreen(screen: PreferenceScreen) {
val coverQualityPref = ListPreference(screen.context).apply { val coverQualityPref = ListPreference(screen.context).apply {
key = MDConstants.getCoverQualityPreferenceKey(dexLang) key = MDConstants.getCoverQualityPreferenceKey(dexLang)
@ -733,7 +596,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
MDConstants.originalLanguagePrefValChinese, MDConstants.originalLanguagePrefValChinese,
MDConstants.originalLanguagePrefValKorean MDConstants.originalLanguagePrefValKorean
) )
setDefaultValue(setOf<String>()) setDefaultValue(MDConstants.originalLanguagePrefDefaults)
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
val checkValue = newValue as Set<String> val checkValue = newValue as Set<String>
@ -792,6 +655,55 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
helper.json.decodeFromString(body?.string().orEmpty()) helper.json.decodeFromString(body?.string().orEmpty())
} }
private val SharedPreferences.contentRating
get() = getStringSet(
MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults
)
private val SharedPreferences.originalLanguages: Set<String>
get() {
val prefValues = getStringSet(
MDConstants.getOriginalLanguagePrefKey(dexLang),
MDConstants.originalLanguagePrefDefaults
)
val originalLanguages = prefValues.orEmpty().toMutableSet()
if (MDConstants.originalLanguagePrefValChinese in originalLanguages) {
originalLanguages.add(MDConstants.originalLanguagePrefValChineseHk)
}
return originalLanguages
}
private val SharedPreferences.coverQuality
get() = getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
private val SharedPreferences.blockedGroups
get() = getString(MDConstants.getBlockedGroupsPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
.orEmpty()
.toSet()
private val SharedPreferences.blockedUploaders
get() = getString(MDConstants.getBlockedUploaderPrefKey(dexLang), "")
?.split(",")
?.map(String::trim)
?.filter(String::isNotEmpty)
?.sorted()
.orEmpty()
.toSet()
private val SharedPreferences.forceStandardHttps
get() = getBoolean(MDConstants.getStandardHttpsPreferenceKey(dexLang), false)
private val SharedPreferences.useDataSaver
get() = getBoolean(MDConstants.getDataSaverPreferenceKey(dexLang), false)
private fun SharedPreferences.sanitizeExistingUuidPrefs() { private fun SharedPreferences.sanitizeExistingUuidPrefs() {
if (getBoolean(MDConstants.getHasSanitizedUuidsPrefKey(dexLang), false)) { if (getBoolean(MDConstants.getHasSanitizedUuidsPrefKey(dexLang), false)) {
return return

View File

@ -7,21 +7,23 @@ import okhttp3.HttpUrl
class MangaDexFilters { class MangaDexFilters {
internal fun getMDFilterList(preferences: SharedPreferences, dexLang: String, intl: MangaDexIntl): FilterList { internal fun getMDFilterList(
return FilterList( preferences: SharedPreferences,
HasAvailableChaptersFilter(intl), dexLang: String,
OriginalLanguageList(intl, getOriginalLanguage(preferences, dexLang, intl)), intl: MangaDexIntl
ContentRatingList(intl, getContentRating(preferences, dexLang, intl)), ): FilterList = FilterList(
DemographicList(intl, getDemographics(intl)), HasAvailableChaptersFilter(intl),
StatusList(intl, getStatus(intl)), OriginalLanguageList(intl, getOriginalLanguage(preferences, dexLang, intl)),
SortFilter(intl, getSortables(intl)), ContentRatingList(intl, getContentRating(preferences, dexLang, intl)),
TagsFilter(intl, getTagFilters(intl)), DemographicList(intl, getDemographics(intl)),
TagList(intl.content, getContents(intl)), StatusList(intl, getStatus(intl)),
TagList(intl.format, getFormats(intl)), SortFilter(intl, getSortables(intl)),
TagList(intl.genre, getGenres(intl)), TagsFilter(intl, getTagFilters(intl)),
TagList(intl.theme, getThemes(intl)), TagList(intl.content, getContents(intl)),
) TagList(intl.format, getFormats(intl)),
} TagList(intl.genre, getGenres(intl)),
TagList(intl.theme, getThemes(intl)),
)
private interface UrlQueryFilter { private interface UrlQueryFilter {
fun addQueryParameter(url: HttpUrl.Builder, dexLang: String) fun addQueryParameter(url: HttpUrl.Builder, dexLang: String)
@ -61,7 +63,11 @@ class MangaDexFilters {
} }
} }
private fun getOriginalLanguage(preferences: SharedPreferences, dexLang: String, intl: MangaDexIntl): List<OriginalLanguage> { private fun getOriginalLanguage(
preferences: SharedPreferences,
dexLang: String,
intl: MangaDexIntl
): List<OriginalLanguage> {
val originalLanguages = preferences.getStringSet( val originalLanguages = preferences.getStringSet(
MDConstants.getOriginalLanguagePrefKey(dexLang), MDConstants.getOriginalLanguagePrefKey(dexLang),
setOf() setOf()
@ -91,11 +97,16 @@ class MangaDexFilters {
} }
} }
private fun getContentRating(preferences: SharedPreferences, dexLang: String, intl: MangaDexIntl): List<ContentRating> { private fun getContentRating(
preferences: SharedPreferences,
dexLang: String,
intl: MangaDexIntl
): List<ContentRating> {
val contentRatings = preferences.getStringSet( val contentRatings = preferences.getStringSet(
MDConstants.getContentRatingPrefKey(dexLang), MDConstants.getContentRatingPrefKey(dexLang),
MDConstants.contentRatingPrefDefaults MDConstants.contentRatingPrefDefaults
) )
return listOf( return listOf(
ContentRating(intl.contentRatingSafe, MDConstants.contentRatingPrefValSafe).apply { ContentRating(intl.contentRatingSafe, MDConstants.contentRatingPrefValSafe).apply {
state = contentRatings state = contentRatings
@ -212,7 +223,7 @@ class MangaDexFilters {
} }
} }
internal fun getContents(intl: MangaDexIntl): List<Tag> { private fun getContents(intl: MangaDexIntl): List<Tag> {
val tags = listOf( val tags = listOf(
Tag("b29d6a3d-1569-4e7a-8caf-7557bc92cd5d", intl.contentGore), Tag("b29d6a3d-1569-4e7a-8caf-7557bc92cd5d", intl.contentGore),
Tag("97893a4c-12af-4dac-b6be-0dffb353568e", intl.contentSexualViolence), Tag("97893a4c-12af-4dac-b6be-0dffb353568e", intl.contentSexualViolence),
@ -221,7 +232,7 @@ class MangaDexFilters {
return tags.sortIfTranslated(intl) return tags.sortIfTranslated(intl)
} }
internal fun getFormats(intl: MangaDexIntl): List<Tag> { private fun getFormats(intl: MangaDexIntl): List<Tag> {
val tags = listOf( val tags = listOf(
Tag("b11fda93-8f1d-4bef-b2ed-8803d3733170", intl.formatFourKoma), Tag("b11fda93-8f1d-4bef-b2ed-8803d3733170", intl.formatFourKoma),
Tag("f4122d1c-3b44-44d0-9936-ff7502c39ad3", intl.formatAdaptation), Tag("f4122d1c-3b44-44d0-9936-ff7502c39ad3", intl.formatAdaptation),
@ -240,7 +251,7 @@ class MangaDexFilters {
return tags.sortIfTranslated(intl) return tags.sortIfTranslated(intl)
} }
internal fun getGenres(intl: MangaDexIntl): List<Tag> { private fun getGenres(intl: MangaDexIntl): List<Tag> {
val tags = listOf( val tags = listOf(
Tag("391b0423-d847-456f-aff0-8b0cfc03066b", intl.genreAction), Tag("391b0423-d847-456f-aff0-8b0cfc03066b", intl.genreAction),
Tag("87cc87cd-a395-47af-b27a-93258283bbc6", intl.genreAdventure), Tag("87cc87cd-a395-47af-b27a-93258283bbc6", intl.genreAdventure),
@ -271,7 +282,7 @@ class MangaDexFilters {
return tags.sortIfTranslated(intl) return tags.sortIfTranslated(intl)
} }
internal fun getThemes(intl: MangaDexIntl): List<Tag> { private fun getThemes(intl: MangaDexIntl): List<Tag> {
val tags = listOf( val tags = listOf(
Tag("e64f6742-c834-471d-8d72-dd51fc02b835", intl.themeAliens), Tag("e64f6742-c834-471d-8d72-dd51fc02b835", intl.themeAliens),
Tag("3de8c75d-8ee3-48ff-98ee-e20a65c86451", intl.themeAnimals), Tag("3de8c75d-8ee3-48ff-98ee-e20a65c86451", intl.themeAnimals),

View File

@ -78,13 +78,14 @@ class MangaDexHelper(private val lang: String) {
/** /**
* Get the latest chapter offset pages are 1 based, so subtract 1 * Get the latest chapter offset pages are 1 based, so subtract 1
*/ */
fun getLatestChapterOffset(page: Int): String = (MDConstants.latestChapterLimit * (page - 1)).toString() fun getLatestChapterOffset(page: Int): String =
(MDConstants.latestChapterLimit * (page - 1)).toString()
/** /**
* Remove any HTML characters in description or chapter name to actual * Remove any HTML characters in description or chapter name to actual
* characters. For example &hearts; will show * characters. For example &hearts; will show
*/ */
fun cleanString(string: String): String { private fun cleanString(string: String): String {
return Parser.unescapeEntities(string, false) return Parser.unescapeEntities(string, false)
.substringBefore("---") .substringBefore("---")
.replace(markdownLinksRegex, "$1") .replace(markdownLinksRegex, "$1")
@ -116,7 +117,7 @@ class MangaDexHelper(private val lang: String) {
} }
} }
fun parseDate(dateAsString: String): Long = private fun parseDate(dateAsString: String): Long =
MDConstants.dateFormatter.parse(dateAsString)?.time ?: 0 MDConstants.dateFormatter.parse(dateAsString)?.time ?: 0
// chapter url where we get the token, last request time // chapter url where we get the token, last request time
@ -170,8 +171,8 @@ class MangaDexHelper(private val lang: String) {
headers: Headers, headers: Headers,
cacheControl: CacheControl, cacheControl: CacheControl,
): String { ): String {
val response = val request = mdAtHomeRequest(tokenRequestUrl, headers, cacheControl)
client.newCall(mdAtHomeRequest(tokenRequestUrl, headers, cacheControl)).execute() val response = client.newCall(request).execute()
// This check is for the error that causes pages to fail to load. // This check is for the error that causes pages to fail to load.
// It should never be entered, but in case it is, we retry the request. // It should never be entered, but in case it is, we retry the request.
@ -216,7 +217,7 @@ class MangaDexHelper(private val lang: String) {
?: mangaDataDto.attributes.altTitles.jsonArray ?: mangaDataDto.attributes.altTitles.jsonArray
.find { .find {
val altTitle = it.asMdMap() val altTitle = it.asMdMap()
altTitle[lang] ?: altTitle["en"] != null (altTitle[lang] ?: altTitle["en"]) != null
}?.asMdMap()?.values?.singleOrNull() }?.asMdMap()?.values?.singleOrNull()
?: titleMap["ja"] // romaji titles are sometimes ja (and are not altTitles) ?: titleMap["ja"] // romaji titles are sometimes ja (and are not altTitles)
?: titleMap.values.firstOrNull() // use literally anything from title as a last resort ?: titleMap.values.firstOrNull() // use literally anything from title as a last resort
@ -256,31 +257,27 @@ class MangaDexHelper(private val lang: String) {
val dexLocale = Locale.forLanguageTag(lang) val dexLocale = Locale.forLanguageTag(lang)
val nonGenres = listOf( val nonGenres = listOf(
(attr.publicationDemographic ?: "").capitalize(Locale.US), (attr.publicationDemographic ?: "")
.replaceFirstChar { it.uppercase(Locale.US) },
contentRating, contentRating,
Locale(attr.originalLanguage ?: "") Locale(attr.originalLanguage ?: "")
.getDisplayLanguage(dexLocale) .getDisplayLanguage(dexLocale)
.capitalize(dexLocale) .replaceFirstChar { it.uppercase(dexLocale) }
) )
val authors = mangaDataDto.relationships val authors = mangaDataDto.relationships
.filter { relationshipDto -> .filter { it.type.equals(MDConstants.author, true) }
relationshipDto.type.equals(MDConstants.author, true) .mapNotNull { it.attributes!!.name }
} .distinct()
.mapNotNull { it.attributes!!.name }.distinct()
val artists = mangaDataDto.relationships val artists = mangaDataDto.relationships
.filter { relationshipDto -> .filter { it.type.equals(MDConstants.artist, true) }
relationshipDto.type.equals(MDConstants.artist, true) .mapNotNull { it.attributes!!.name }
} .distinct()
.mapNotNull { it.attributes!!.name }.distinct()
val coverFileName = mangaDataDto.relationships val coverFileName = mangaDataDto.relationships
.firstOrNull { relationshipDto -> .firstOrNull { it.type.equals(MDConstants.coverArt, true) }
relationshipDto.type.equals(MDConstants.coverArt, true) ?.attributes?.fileName
}
?.attributes
?.fileName
val tags = mdFilters.getTags(intl) val tags = mdFilters.getTags(intl)
@ -320,23 +317,15 @@ class MangaDexHelper(private val lang: String) {
try { try {
val attr = chapterDataDto.attributes val attr = chapterDataDto.attributes
val groups = chapterDataDto.relationships.filter { relationshipDto -> val groups = chapterDataDto.relationships
relationshipDto.type.equals( .filter { it.type.equals(MDConstants.scanlator, true) }
MDConstants.scanlator, .filterNot { it.id == MDConstants.legacyNoGroupId } // 'no group' left over from MDv3
true
)
}.filterNot { it.id == MDConstants.legacyNoGroupId } // 'no group' left over from MDv3
.mapNotNull { it.attributes!!.name } .mapNotNull { it.attributes!!.name }
.joinToString(" & ") .joinToString(" & ")
.ifEmpty { .ifEmpty {
// fall back to uploader name if no group // fall back to uploader name if no group
val users = chapterDataDto.relationships val users = chapterDataDto.relationships
.filter { relationshipDto -> .filter { it.type.equals(MDConstants.uploader, true) }
relationshipDto.type.equals(
MDConstants.uploader,
true
)
}
.mapNotNull { it.attributes!!.username } .mapNotNull { it.attributes!!.username }
if (users.isNotEmpty()) intl.uploadedBy(users) else "" if (users.isNotEmpty()) intl.uploadedBy(users) else ""
} }
@ -375,7 +364,7 @@ class MangaDexHelper(private val lang: String) {
chapterName.add("Oneshot") chapterName.add("Oneshot")
} }
// In future calculate [END] if non mvp api doesnt provide it // In future calculate [END] if non mvp api doesn't provide it
return SChapter.create().apply { return SChapter.create().apply {
url = "/chapter/${chapterDataDto.id}" url = "/chapter/${chapterDataDto.id}"

View File

@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable
@Serializable @Serializable
data class AggregateDto( data class AggregateDto(
val result: String, val result: String,
val volumes: Map<String, AggregateVolume> val volumes: Map<String, AggregateVolume>?
) )
@Serializable @Serializable

View File

@ -47,7 +47,7 @@ data class MangaAttributesDto(
val title: JsonElement, val title: JsonElement,
val altTitles: JsonElement, val altTitles: JsonElement,
val description: JsonElement, val description: JsonElement,
val originalLanguage: String, val originalLanguage: String?,
val lastVolume: String?, val lastVolume: String?,
val lastChapter: String?, val lastChapter: String?,
val contentRating: String?, val contentRating: String?,