Mangadex: Add support for MDLists url intent (#11024)

* Update build.gradle

* Added list support

* Add error message for empty list

* Update AndroidManifest.xml
This commit is contained in:
jopejoe1 2022-03-07 03:48:27 +13:00 committed by GitHub
parent 2998330d4e
commit 2b5359ca26
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 29 deletions

View File

@ -15,25 +15,15 @@
<category android:name="android.intent.category.BROWSABLE" />
<data android:host="mangadex.org" />
<data android:scheme="https" />
<data
android:pathPattern="/title/..*"
android:scheme="https" />
<data
android:pathPattern="/manga/..*"
android:scheme="https" />
<data
android:pathPattern="/chapter/..*"
android:scheme="https" />
<data
android:pathPattern="/group/..*"
android:scheme="https" />
<data
android:pathPattern="/author/..*"
android:scheme="https" />
<data
android:pathPattern="/user/..*"
android:scheme="https" />
<data android:pathPattern="/title/..*" />
<data android:pathPattern="/manga/..*" />
<data android:pathPattern="/chapter/..*" />
<data android:pathPattern="/group/..*" />
<data android:pathPattern="/author/..*" />
<data android:pathPattern="/user/..*" />
<data android:pathPattern="/list/..*" />
</intent-filter>
</activity>
</application>

View File

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

View File

@ -24,6 +24,7 @@ object MDConstants {
const val apiUrl = "https://api.mangadex.org"
const val apiMangaUrl = "$apiUrl/manga"
const val apiChapterUrl = "$apiUrl/chapter"
const val apiListUrl = "$apiUrl/list"
const val atHomePostUrl = "https://api.mangadex.network/report"
val whitespaceRegex = "\\s".toRegex()
@ -37,6 +38,7 @@ object MDConstants {
const val prefixGrpSearch = "grp:"
const val prefixAuthSearch = "author:"
const val prefixUsrSearch = "usr:"
const val prefixListSearch = "list:"
const val coverQualityPref = "thumbnailQuality"

View File

@ -12,6 +12,7 @@ import eu.kanade.tachiyomi.extension.all.mangadex.dto.AggregateDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.AtHomeDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ChapterListDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.ListDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaDto
import eu.kanade.tachiyomi.extension.all.mangadex.dto.MangaListDto
import eu.kanade.tachiyomi.network.GET
@ -191,17 +192,22 @@ abstract class MangaDex(override val lang: String, val dexLang: String) :
// SEARCH section
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
if (query.startsWith(MDConstants.prefixChSearch)) {
return getMangaIdFromChapterId(query.removePrefix(MDConstants.prefixChSearch)).flatMap { manga_id ->
super.fetchSearchManga(page, MDConstants.prefixIdSearch + manga_id, filters)
}
when {
query.startsWith(MDConstants.prefixChSearch) ->
return getMangaIdFromChapterId(query.removePrefix(MDConstants.prefixChSearch)).flatMap { manga_id ->
super.fetchSearchManga(page, MDConstants.prefixIdSearch + manga_id, filters)
}
query.startsWith(MDConstants.prefixUsrSearch) ->
return client.newCall(searchMangaUploaderRequest(page, query.removePrefix(MDConstants.prefixUsrSearch)))
.asObservableSuccess()
.map { latestUpdatesParse(it) }
query.startsWith(MDConstants.prefixListSearch) ->
return client.newCall(GET(MDConstants.apiListUrl + "/" + query.removePrefix(MDConstants.prefixListSearch), headers, CacheControl.FORCE_NETWORK))
.asObservableSuccess()
.map { searchMangaListRequest(it, page) }
else ->
return super.fetchSearchManga(page, query, filters)
}
if (query.startsWith(MDConstants.prefixUsrSearch)) {
return client.newCall(searchMangaUploaderRequest(page, query.removePrefix(MDConstants.prefixUsrSearch)))
.asObservableSuccess()
.map { latestUpdatesParse(it) }
}
return super.fetchSearchManga(page, query, filters)
}
private fun getMangaIdFromChapterId(id: String): Observable<String> {
@ -277,6 +283,54 @@ abstract class MangaDex(override val lang: String, val dexLang: String) :
override fun searchMangaParse(response: Response): MangasPage = popularMangaParse(response)
private fun searchMangaListRequest(response: Response, page: Int): MangasPage {
if (response.isSuccessful.not()) {
throw Exception("HTTP ${response.code}")
}
val listDto = helper.json.decodeFromString<ListDto>(response.body!!.string())
val listDtoFiltered = listDto.data.relationships.filter { it.type != "Manga" }
val amount = listDtoFiltered.count()
if (amount < 1){
throw Exception("No Manga in List")
}
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)
}
listDtoFiltered.forEachIndexed() { index, relationshipDto ->
if (index >= minIndex && index < (minIndex + MDConstants.mangaLimit)) {
url.addQueryParameter("ids[]", relationshipDto.id)
}
}
val request = client.newCall(GET(url.build().toString(), headers, CacheControl.FORCE_NETWORK))
val mangaList = searchMangaListParse(request.execute())
return MangasPage(mangaList, amount.toFloat() / MDConstants.mangaLimit - (page.toFloat() - 1) > 1)
}
private fun searchMangaListParse(response: Response): List<SManga> {
if (response.isSuccessful.not()) {
throw Exception("HTTP ${response.code}")
}
val mangaListDto = helper.json.decodeFromString<MangaListDto>(response.body!!.string())
val coverSuffix = preferences.getString(MDConstants.getCoverQualityPreferenceKey(dexLang), "")
val mangaList = mangaListDto.data.map { mangaDataDto ->
val fileName = mangaDataDto.relationships.firstOrNull { relationshipDto ->
relationshipDto.type.equals(MDConstants.coverArt, true)
}?.attributes?.fileName
helper.createBasicManga(mangaDataDto, fileName, coverSuffix, dexLang)
}
return mangaList
}
private fun searchMangaUploaderRequest(page: Int, uploader: String): Request {
val url = MDConstants.apiChapterUrl.toHttpUrlOrNull()!!.newBuilder().apply {
addQueryParameter("offset", helper.getLatestChapterOffset(page))

View File

@ -31,6 +31,7 @@ class MangadexUrlActivity : Activity() {
equals("group") -> putExtra("query", "${MDConstants.prefixGrpSearch}$titleid")
equals("user") -> putExtra("query", "${MDConstants.prefixUsrSearch}$titleid")
equals("author") -> putExtra("query", "${MDConstants.prefixAuthSearch}$titleid")
equals("list") -> putExtra("query", "${MDConstants.prefixListSearch}$titleid")
else -> putExtra("query", "${MDConstants.prefixIdSearch}$titleid")
}
}

View File

@ -0,0 +1,25 @@
package eu.kanade.tachiyomi.extension.all.mangadex.dto
import kotlinx.serialization.Serializable
@Serializable
data class ListDto(
val result: String,
val response: String,
val data: ListDataDto,
)
@Serializable
data class ListDataDto(
val id: String,
val type: String,
val attributes: ListAttributesDto,
val relationships: List<RelationshipDto>,
)
@Serializable
data class ListAttributesDto(
val name: String,
val visibility: String,
val version: Int,
)