Refactor the MangaDex code a bit. (#13703)
This commit is contained in:
parent
9b7e28848b
commit
c8adaa2f2a
|
@ -6,7 +6,7 @@ ext {
|
|||
extName = 'MangaDex'
|
||||
pkgNameSuffix = 'all.mangadex'
|
||||
extClass = '.MangaDexFactory'
|
||||
extVersionCode = 168
|
||||
extVersionCode = 169
|
||||
isNsfw = true
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ object MDConstants {
|
|||
const val prefixUsrSearch = "usr:"
|
||||
const val prefixListSearch = "list:"
|
||||
|
||||
const val coverQualityPref = "thumbnailQuality"
|
||||
private const val coverQualityPref = "thumbnailQuality"
|
||||
|
||||
fun getCoverQualityPreferenceKey(dexLang: String): String {
|
||||
return "${coverQualityPref}_$dexLang"
|
||||
|
@ -53,7 +53,7 @@ object MDConstants {
|
|||
|
||||
fun getCoverQualityPreferenceDefaultValue() = getCoverQualityPreferenceEntryValues()[0]
|
||||
|
||||
const val dataSaverPref = "dataSaverV5"
|
||||
private const val dataSaverPref = "dataSaverV5"
|
||||
|
||||
fun getDataSaverPreferenceKey(dexLang: String): String {
|
||||
return "${dataSaverPref}_$dexLang"
|
||||
|
@ -108,9 +108,9 @@ object MDConstants {
|
|||
return "${hasSanitizedUuidsPref}_$dexLang"
|
||||
}
|
||||
|
||||
const val tagGroupContent = "content"
|
||||
const val tagGroupFormat = "format"
|
||||
const val tagGroupGenre = "genre"
|
||||
const val tagGroupTheme = "theme"
|
||||
private const val tagGroupContent = "content"
|
||||
private const val tagGroupFormat = "format"
|
||||
private const val tagGroupGenre = "genre"
|
||||
private const val tagGroupTheme = "theme"
|
||||
val tagGroupsOrder = arrayOf(tagGroupContent, tagGroupFormat, tagGroupGenre, tagGroupTheme)
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
|
|||
HttpSource() {
|
||||
|
||||
override val name = MangaDexIntl.MANGADEX_NAME
|
||||
|
||||
override val baseUrl = "https://mangadex.org"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
@ -71,36 +72,14 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
|
|||
// POPULAR Manga Section
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply {
|
||||
addQueryParameter("order[followedCount]", "desc")
|
||||
addQueryParameter("availableTranslatedLanguage[]", dexLang)
|
||||
addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
addQueryParameter("offset", helper.getMangaListOffset(page))
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
|
||||
addQueryParameter(
|
||||
"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
|
||||
)
|
||||
}
|
||||
}
|
||||
val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
|
||||
.addQueryParameter("order[followedCount]", "desc")
|
||||
.addQueryParameter("availableTranslatedLanguage[]", dexLang)
|
||||
.addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
.addQueryParameter("offset", helper.getMangaListOffset(page))
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
.addQueryParameter("contentRating[]", preferences.contentRating)
|
||||
.addQueryParameter("originalLanguage[]", preferences.originalLanguages)
|
||||
|
||||
return GET(
|
||||
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 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 fileName = mangaDataDto.relationships.firstOrNull { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.coverArt, true)
|
||||
}?.attributes?.fileName
|
||||
val fileName = mangaDataDto.relationships
|
||||
.firstOrNull { it.type.equals(MDConstants.coverArt, true) }
|
||||
?.attributes?.fileName
|
||||
helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang)
|
||||
}
|
||||
|
||||
|
@ -141,20 +120,11 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
|
|||
.distinct()
|
||||
.toSet()
|
||||
|
||||
val mangaUrl = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder().apply {
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
addQueryParameter("limit", mangaIds.size.toString())
|
||||
|
||||
addQueryParameter(
|
||||
"contentRating[]",
|
||||
preferences.getStringSet(
|
||||
MDConstants.getContentRatingPrefKey(dexLang),
|
||||
MDConstants.contentRatingPrefDefaults
|
||||
)
|
||||
)
|
||||
|
||||
addQueryParameter("ids[]", mangaIds)
|
||||
}
|
||||
val mangaUrl = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
.addQueryParameter("limit", mangaIds.size.toString())
|
||||
.addQueryParameter("contentRating[]", preferences.contentRating)
|
||||
.addQueryParameter("ids[]", mangaIds)
|
||||
|
||||
val mangaRequest = GET(mangaUrl.build().toString(), headers, CacheControl.FORCE_NETWORK)
|
||||
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 coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
|
||||
val coverSuffix = preferences.coverQuality
|
||||
|
||||
val mangaList = mangaIds.mapNotNull { mangaDtoMap[it] }.map { mangaDataDto ->
|
||||
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.coverArt, true)
|
||||
relationshipDto.type.equals(MDConstants.coverArt, true)
|
||||
}?.attributes?.fileName
|
||||
val fileName = mangaDataDto.relationships
|
||||
.firstOrNull { it.type.equals(MDConstants.coverArt, true) }
|
||||
?.attributes?.fileName
|
||||
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 {
|
||||
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply {
|
||||
addQueryParameter("offset", helper.getLatestChapterOffset(page))
|
||||
addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
|
||||
addQueryParameter("translatedLanguage[]", dexLang)
|
||||
addQueryParameter("order[publishAt]", "desc")
|
||||
addQueryParameter("includeFutureUpdates", "0")
|
||||
|
||||
val originalLanguages = preferences.getStringSet(
|
||||
MDConstants.getOriginalLanguagePrefKey(dexLang),
|
||||
MDConstants.originalLanguagePrefDefaults
|
||||
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("offset", helper.getLatestChapterOffset(page))
|
||||
.addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
|
||||
.addQueryParameter("translatedLanguage[]", dexLang)
|
||||
.addQueryParameter("order[publishAt]", "desc")
|
||||
.addQueryParameter("includeFutureUpdates", "0")
|
||||
.addQueryParameter("originalLanguage[]", preferences.originalLanguages)
|
||||
.addQueryParameter("contentRating[]", preferences.contentRating)
|
||||
.addQueryParameter(
|
||||
"excludedGroups[]",
|
||||
MDConstants.defaultBlockedGroups + preferences.blockedGroups
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
.addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
|
||||
|
||||
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 {
|
||||
val tempUrl = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply {
|
||||
addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
addQueryParameter("offset", helper.getMangaListOffset(page))
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
}
|
||||
val tempUrl = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
|
||||
.addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
.addQueryParameter("offset", helper.getMangaListOffset(page))
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
|
||||
when {
|
||||
query.startsWith(MDConstants.prefixIdSearch) -> {
|
||||
val url = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder().apply {
|
||||
addQueryParameter("ids[]", query.removePrefix(MDConstants.prefixIdSearch))
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
addQueryParameter("contentRating[]", "safe")
|
||||
addQueryParameter("contentRating[]", "suggestive")
|
||||
addQueryParameter("contentRating[]", "erotica")
|
||||
addQueryParameter("contentRating[]", "pornographic")
|
||||
}
|
||||
val url = MDConstants.apiMangaUrl.toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("ids[]", query.removePrefix(MDConstants.prefixIdSearch))
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
.addQueryParameter("contentRating[]", "safe")
|
||||
.addQueryParameter("contentRating[]", "suggestive")
|
||||
.addQueryParameter("contentRating[]", "erotica")
|
||||
.addQueryParameter("contentRating[]", "pornographic")
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
tempUrl.apply {
|
||||
addQueryParameter("group", groupID)
|
||||
}
|
||||
tempUrl.addQueryParameter("group", groupID)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
tempUrl.apply {
|
||||
addQueryParameter("authors[]", authorID)
|
||||
addQueryParameter("artists[]", authorID)
|
||||
}
|
||||
tempUrl
|
||||
.addQueryParameter("authors[]", authorID)
|
||||
.addQueryParameter("artists[]", authorID)
|
||||
}
|
||||
|
||||
else -> {
|
||||
tempUrl.apply {
|
||||
val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
|
||||
if (actualQuery.isNotBlank()) {
|
||||
addQueryParameter("title", actualQuery)
|
||||
}
|
||||
val actualQuery = query.replace(MDConstants.whitespaceRegex, " ")
|
||||
|
||||
if (actualQuery.isNotBlank()) {
|
||||
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 url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder().apply {
|
||||
addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
addQueryParameter("offset", "0")
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
}
|
||||
val url = MDConstants.apiMangaUrl.toHttpUrl().newBuilder()
|
||||
.addQueryParameter("limit", MDConstants.mangaLimit.toString())
|
||||
.addQueryParameter("offset", "0")
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
|
||||
val ids = listDtoFiltered
|
||||
.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 coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
|
||||
val coverSuffix = preferences.coverQuality
|
||||
|
||||
val mangaList = mangaListDto.data.map { mangaDataDto ->
|
||||
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.coverArt, true)
|
||||
}?.attributes?.fileName
|
||||
val fileName = mangaDataDto.relationships
|
||||
.firstOrNull { it.type.equals(MDConstants.coverArt, true) }
|
||||
?.attributes?.fileName
|
||||
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 {
|
||||
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply {
|
||||
addQueryParameter("offset", helper.getLatestChapterOffset(page))
|
||||
addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
|
||||
addQueryParameter("translatedLanguage[]", dexLang)
|
||||
addQueryParameter("order[publishAt]", "desc")
|
||||
addQueryParameter("includeFutureUpdates", "0")
|
||||
addQueryParameter("uploader", uploader)
|
||||
|
||||
val originalLanguages = preferences.getStringSet(
|
||||
MDConstants.getOriginalLanguagePrefKey(dexLang),
|
||||
MDConstants.originalLanguagePrefDefaults
|
||||
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder()
|
||||
.addQueryParameter("offset", helper.getLatestChapterOffset(page))
|
||||
.addQueryParameter("limit", MDConstants.latestChapterLimit.toString())
|
||||
.addQueryParameter("translatedLanguage[]", dexLang)
|
||||
.addQueryParameter("order[publishAt]", "desc")
|
||||
.addQueryParameter("includeFutureUpdates", "0")
|
||||
.addQueryParameter("uploader", uploader)
|
||||
.addQueryParameter("originalLanguage[]", preferences.originalLanguages)
|
||||
.addQueryParameter("contentRating[]", preferences.contentRating)
|
||||
.addQueryParameter(
|
||||
"excludedGroups[]",
|
||||
MDConstants.defaultBlockedGroups + preferences.blockedGroups
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
.addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
val url = (MDConstants.apiUrl + manga.url).toHttpUrl().newBuilder().apply {
|
||||
addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
addQueryParameter("includes[]", MDConstants.author)
|
||||
addQueryParameter("includes[]", MDConstants.artist)
|
||||
}
|
||||
val url = (MDConstants.apiUrl + manga.url).toHttpUrl().newBuilder()
|
||||
.addQueryParameter("includes[]", MDConstants.coverArt)
|
||||
.addQueryParameter("includes[]", MDConstants.author)
|
||||
.addQueryParameter("includes[]", MDConstants.artist)
|
||||
|
||||
return GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK)
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val manga = response.parseAs<MangaDto>()
|
||||
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
|
||||
|
||||
return helper.createManga(
|
||||
manga.data,
|
||||
fetchSimpleChapterList(manga, 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.
|
||||
* uses the 'aggregate' endpoint
|
||||
* @see MangaDexHelper.getPublicationStatus
|
||||
* @see MangaDexHelper.doubleCheckChapters
|
||||
* @see AggregateDto
|
||||
*/
|
||||
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
|
||||
*/
|
||||
private fun actualChapterListRequest(mangaId: String, offset: Int): Request {
|
||||
val url = helper.getChapterEndpoint(mangaId, offset, dexLang).toHttpUrlOrNull()!!.newBuilder().apply {
|
||||
addQueryParameter("contentRating[]", "safe")
|
||||
addQueryParameter("contentRating[]", "suggestive")
|
||||
addQueryParameter("contentRating[]", "erotica")
|
||||
addQueryParameter("contentRating[]", "pornographic")
|
||||
|
||||
val excludedGroups = preferences
|
||||
.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)
|
||||
}
|
||||
val url = helper.getChapterEndpoint(mangaId, offset, dexLang).toHttpUrl().newBuilder()
|
||||
.addQueryParameter("contentRating[]", "safe")
|
||||
.addQueryParameter("contentRating[]", "suggestive")
|
||||
.addQueryParameter("contentRating[]", "erotica")
|
||||
.addQueryParameter("contentRating[]", "pornographic")
|
||||
.addQueryParameter("excludedGroups[]", preferences.blockedGroups)
|
||||
.addQueryParameter("excludedUploaders[]", preferences.blockedUploaders)
|
||||
|
||||
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 usingStandardHTTPS =
|
||||
preferences.getBoolean(MDConstants.getStandardHttpsPreferenceKey(dexLang), false)
|
||||
val atHomeRequestUrl = if (usingStandardHTTPS) {
|
||||
val atHomeRequestUrl = if (preferences.forceStandardHttps) {
|
||||
"${MDConstants.apiUrl}/at-home/server/$chapterId?forcePort443=true"
|
||||
} else {
|
||||
"${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 atHomeDto = response.parseAs<AtHomeDto>()
|
||||
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
|
||||
val now = Date().time
|
||||
|
||||
val hash = atHomeDto.chapter.hash
|
||||
val pageSuffix = if (usingDataSaver) {
|
||||
val pageSuffix = if (preferences.useDataSaver) {
|
||||
atHomeDto.chapter.dataSaver.map { "/data-saver/$hash/$it" }
|
||||
} else {
|
||||
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 = ""
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
val coverQualityPref = ListPreference(screen.context).apply {
|
||||
key = MDConstants.getCoverQualityPreferenceKey(dexLang)
|
||||
|
@ -733,7 +596,7 @@ abstract class MangaDex(final override val lang: String, private val dexLang: St
|
|||
MDConstants.originalLanguagePrefValChinese,
|
||||
MDConstants.originalLanguagePrefValKorean
|
||||
)
|
||||
setDefaultValue(setOf<String>())
|
||||
setDefaultValue(MDConstants.originalLanguagePrefDefaults)
|
||||
|
||||
setOnPreferenceChangeListener { _, newValue ->
|
||||
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())
|
||||
}
|
||||
|
||||
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() {
|
||||
if (getBoolean(MDConstants.getHasSanitizedUuidsPrefKey(dexLang), false)) {
|
||||
return
|
||||
|
|
|
@ -7,21 +7,23 @@ import okhttp3.HttpUrl
|
|||
|
||||
class MangaDexFilters {
|
||||
|
||||
internal fun getMDFilterList(preferences: SharedPreferences, dexLang: String, intl: MangaDexIntl): FilterList {
|
||||
return FilterList(
|
||||
HasAvailableChaptersFilter(intl),
|
||||
OriginalLanguageList(intl, getOriginalLanguage(preferences, dexLang, intl)),
|
||||
ContentRatingList(intl, getContentRating(preferences, dexLang, intl)),
|
||||
DemographicList(intl, getDemographics(intl)),
|
||||
StatusList(intl, getStatus(intl)),
|
||||
SortFilter(intl, getSortables(intl)),
|
||||
TagsFilter(intl, getTagFilters(intl)),
|
||||
TagList(intl.content, getContents(intl)),
|
||||
TagList(intl.format, getFormats(intl)),
|
||||
TagList(intl.genre, getGenres(intl)),
|
||||
TagList(intl.theme, getThemes(intl)),
|
||||
)
|
||||
}
|
||||
internal fun getMDFilterList(
|
||||
preferences: SharedPreferences,
|
||||
dexLang: String,
|
||||
intl: MangaDexIntl
|
||||
): FilterList = FilterList(
|
||||
HasAvailableChaptersFilter(intl),
|
||||
OriginalLanguageList(intl, getOriginalLanguage(preferences, dexLang, intl)),
|
||||
ContentRatingList(intl, getContentRating(preferences, dexLang, intl)),
|
||||
DemographicList(intl, getDemographics(intl)),
|
||||
StatusList(intl, getStatus(intl)),
|
||||
SortFilter(intl, getSortables(intl)),
|
||||
TagsFilter(intl, getTagFilters(intl)),
|
||||
TagList(intl.content, getContents(intl)),
|
||||
TagList(intl.format, getFormats(intl)),
|
||||
TagList(intl.genre, getGenres(intl)),
|
||||
TagList(intl.theme, getThemes(intl)),
|
||||
)
|
||||
|
||||
private interface UrlQueryFilter {
|
||||
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(
|
||||
MDConstants.getOriginalLanguagePrefKey(dexLang),
|
||||
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(
|
||||
MDConstants.getContentRatingPrefKey(dexLang),
|
||||
MDConstants.contentRatingPrefDefaults
|
||||
)
|
||||
|
||||
return listOf(
|
||||
ContentRating(intl.contentRatingSafe, MDConstants.contentRatingPrefValSafe).apply {
|
||||
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(
|
||||
Tag("b29d6a3d-1569-4e7a-8caf-7557bc92cd5d", intl.contentGore),
|
||||
Tag("97893a4c-12af-4dac-b6be-0dffb353568e", intl.contentSexualViolence),
|
||||
|
@ -221,7 +232,7 @@ class MangaDexFilters {
|
|||
return tags.sortIfTranslated(intl)
|
||||
}
|
||||
|
||||
internal fun getFormats(intl: MangaDexIntl): List<Tag> {
|
||||
private fun getFormats(intl: MangaDexIntl): List<Tag> {
|
||||
val tags = listOf(
|
||||
Tag("b11fda93-8f1d-4bef-b2ed-8803d3733170", intl.formatFourKoma),
|
||||
Tag("f4122d1c-3b44-44d0-9936-ff7502c39ad3", intl.formatAdaptation),
|
||||
|
@ -240,7 +251,7 @@ class MangaDexFilters {
|
|||
return tags.sortIfTranslated(intl)
|
||||
}
|
||||
|
||||
internal fun getGenres(intl: MangaDexIntl): List<Tag> {
|
||||
private fun getGenres(intl: MangaDexIntl): List<Tag> {
|
||||
val tags = listOf(
|
||||
Tag("391b0423-d847-456f-aff0-8b0cfc03066b", intl.genreAction),
|
||||
Tag("87cc87cd-a395-47af-b27a-93258283bbc6", intl.genreAdventure),
|
||||
|
@ -271,7 +282,7 @@ class MangaDexFilters {
|
|||
return tags.sortIfTranslated(intl)
|
||||
}
|
||||
|
||||
internal fun getThemes(intl: MangaDexIntl): List<Tag> {
|
||||
private fun getThemes(intl: MangaDexIntl): List<Tag> {
|
||||
val tags = listOf(
|
||||
Tag("e64f6742-c834-471d-8d72-dd51fc02b835", intl.themeAliens),
|
||||
Tag("3de8c75d-8ee3-48ff-98ee-e20a65c86451", intl.themeAnimals),
|
||||
|
|
|
@ -78,13 +78,14 @@ class MangaDexHelper(private val lang: String) {
|
|||
/**
|
||||
* 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
|
||||
* characters. For example ♥ will show ♥
|
||||
*/
|
||||
fun cleanString(string: String): String {
|
||||
private fun cleanString(string: String): String {
|
||||
return Parser.unescapeEntities(string, false)
|
||||
.substringBefore("---")
|
||||
.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
|
||||
|
||||
// chapter url where we get the token, last request time
|
||||
|
@ -170,8 +171,8 @@ class MangaDexHelper(private val lang: String) {
|
|||
headers: Headers,
|
||||
cacheControl: CacheControl,
|
||||
): String {
|
||||
val response =
|
||||
client.newCall(mdAtHomeRequest(tokenRequestUrl, headers, cacheControl)).execute()
|
||||
val request = mdAtHomeRequest(tokenRequestUrl, headers, cacheControl)
|
||||
val response = client.newCall(request).execute()
|
||||
|
||||
// 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.
|
||||
|
@ -216,7 +217,7 @@ class MangaDexHelper(private val lang: String) {
|
|||
?: mangaDataDto.attributes.altTitles.jsonArray
|
||||
.find {
|
||||
val altTitle = it.asMdMap()
|
||||
altTitle[lang] ?: altTitle["en"] != null
|
||||
(altTitle[lang] ?: altTitle["en"]) != null
|
||||
}?.asMdMap()?.values?.singleOrNull()
|
||||
?: titleMap["ja"] // romaji titles are sometimes ja (and are not altTitles)
|
||||
?: 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 nonGenres = listOf(
|
||||
(attr.publicationDemographic ?: "").capitalize(Locale.US),
|
||||
(attr.publicationDemographic ?: "")
|
||||
.replaceFirstChar { it.uppercase(Locale.US) },
|
||||
contentRating,
|
||||
Locale(attr.originalLanguage ?: "")
|
||||
.getDisplayLanguage(dexLocale)
|
||||
.capitalize(dexLocale)
|
||||
.replaceFirstChar { it.uppercase(dexLocale) }
|
||||
)
|
||||
|
||||
val authors = mangaDataDto.relationships
|
||||
.filter { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.author, true)
|
||||
}
|
||||
.mapNotNull { it.attributes!!.name }.distinct()
|
||||
.filter { it.type.equals(MDConstants.author, true) }
|
||||
.mapNotNull { it.attributes!!.name }
|
||||
.distinct()
|
||||
|
||||
val artists = mangaDataDto.relationships
|
||||
.filter { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.artist, true)
|
||||
}
|
||||
.mapNotNull { it.attributes!!.name }.distinct()
|
||||
.filter { it.type.equals(MDConstants.artist, true) }
|
||||
.mapNotNull { it.attributes!!.name }
|
||||
.distinct()
|
||||
|
||||
val coverFileName = mangaDataDto.relationships
|
||||
.firstOrNull { relationshipDto ->
|
||||
relationshipDto.type.equals(MDConstants.coverArt, true)
|
||||
}
|
||||
?.attributes
|
||||
?.fileName
|
||||
.firstOrNull { it.type.equals(MDConstants.coverArt, true) }
|
||||
?.attributes?.fileName
|
||||
|
||||
val tags = mdFilters.getTags(intl)
|
||||
|
||||
|
@ -320,23 +317,15 @@ class MangaDexHelper(private val lang: String) {
|
|||
try {
|
||||
val attr = chapterDataDto.attributes
|
||||
|
||||
val groups = chapterDataDto.relationships.filter { relationshipDto ->
|
||||
relationshipDto.type.equals(
|
||||
MDConstants.scanlator,
|
||||
true
|
||||
)
|
||||
}.filterNot { it.id == MDConstants.legacyNoGroupId } // 'no group' left over from MDv3
|
||||
val groups = chapterDataDto.relationships
|
||||
.filter { it.type.equals(MDConstants.scanlator, true) }
|
||||
.filterNot { it.id == MDConstants.legacyNoGroupId } // 'no group' left over from MDv3
|
||||
.mapNotNull { it.attributes!!.name }
|
||||
.joinToString(" & ")
|
||||
.ifEmpty {
|
||||
// fall back to uploader name if no group
|
||||
val users = chapterDataDto.relationships
|
||||
.filter { relationshipDto ->
|
||||
relationshipDto.type.equals(
|
||||
MDConstants.uploader,
|
||||
true
|
||||
)
|
||||
}
|
||||
.filter { it.type.equals(MDConstants.uploader, true) }
|
||||
.mapNotNull { it.attributes!!.username }
|
||||
if (users.isNotEmpty()) intl.uploadedBy(users) else ""
|
||||
}
|
||||
|
@ -375,7 +364,7 @@ class MangaDexHelper(private val lang: String) {
|
|||
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 {
|
||||
url = "/chapter/${chapterDataDto.id}"
|
||||
|
|
|
@ -5,7 +5,7 @@ import kotlinx.serialization.Serializable
|
|||
@Serializable
|
||||
data class AggregateDto(
|
||||
val result: String,
|
||||
val volumes: Map<String, AggregateVolume>
|
||||
val volumes: Map<String, AggregateVolume>?
|
||||
)
|
||||
|
||||
@Serializable
|
||||
|
|
|
@ -47,7 +47,7 @@ data class MangaAttributesDto(
|
|||
val title: JsonElement,
|
||||
val altTitles: JsonElement,
|
||||
val description: JsonElement,
|
||||
val originalLanguage: String,
|
||||
val originalLanguage: String?,
|
||||
val lastVolume: String?,
|
||||
val lastChapter: String?,
|
||||
val contentRating: String?,
|
||||
|
|
Loading…
Reference in New Issue