Tsuki Mangas: Fix page ordering and chapter WebView (#742)
* Tsuki Mangas: Fix page ordering and chapter WebView * bump version
This commit is contained in:
parent
3b998e9766
commit
37866f48f2
|
@ -1,7 +1,7 @@
|
||||||
ext {
|
ext {
|
||||||
extName = 'Tsuki Mangás'
|
extName = 'Tsuki Mangás'
|
||||||
extClass = '.TsukiMangas'
|
extClass = '.TsukiMangas'
|
||||||
extVersionCode = 1
|
extVersionCode = 2
|
||||||
isNsfw = true
|
isNsfw = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ class TsukiMangas : HttpSource() {
|
||||||
|
|
||||||
override val baseUrl = "https://tsuki-mangas.com"
|
override val baseUrl = "https://tsuki-mangas.com"
|
||||||
|
|
||||||
private val API_URL = baseUrl + API_PATH
|
private val apiUrl = baseUrl + API_PATH
|
||||||
|
|
||||||
override val lang = "pt-BR"
|
override val lang = "pt-BR"
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ class TsukiMangas : HttpSource() {
|
||||||
private val json: Json by injectLazy()
|
private val json: Json by injectLazy()
|
||||||
|
|
||||||
// ============================== Popular ===============================
|
// ============================== Popular ===============================
|
||||||
override fun popularMangaRequest(page: Int) = GET("$API_URL/mangas?page=$page&filter=0", headers)
|
override fun popularMangaRequest(page: Int) = GET("$apiUrl/mangas?page=$page&filter=0", headers)
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
override fun popularMangaParse(response: Response): MangasPage {
|
||||||
val item = response.parseAs<MangaListDto>()
|
val item = response.parseAs<MangaListDto>()
|
||||||
|
@ -70,7 +70,7 @@ class TsukiMangas : HttpSource() {
|
||||||
// Yes, "lastests". High IQ move.
|
// Yes, "lastests". High IQ move.
|
||||||
// Also yeah, there's a "?format=0" glued to the page number. Without this,
|
// Also yeah, there's a "?format=0" glued to the page number. Without this,
|
||||||
// the request will blow up with a HTTP 500.
|
// the request will blow up with a HTTP 500.
|
||||||
override fun latestUpdatesRequest(page: Int) = GET("$API_URL/home/lastests?page=$page%3Fformat%3D0", headers)
|
override fun latestUpdatesRequest(page: Int) = GET("$apiUrl/home/lastests?page=$page%3Fformat%3D0", headers)
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response) = popularMangaParse(response)
|
override fun latestUpdatesParse(response: Response) = popularMangaParse(response)
|
||||||
|
|
||||||
|
@ -78,7 +78,7 @@ class TsukiMangas : HttpSource() {
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
||||||
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
|
return if (query.startsWith(PREFIX_SEARCH)) { // URL intent handler
|
||||||
val id = query.removePrefix(PREFIX_SEARCH)
|
val id = query.removePrefix(PREFIX_SEARCH)
|
||||||
client.newCall(GET("$API_URL/mangas/$id", headers))
|
client.newCall(GET("$apiUrl/mangas/$id", headers))
|
||||||
.asObservableSuccess()
|
.asObservableSuccess()
|
||||||
.map(::searchMangaByIdParse)
|
.map(::searchMangaByIdParse)
|
||||||
} else {
|
} else {
|
||||||
|
@ -95,7 +95,7 @@ class TsukiMangas : HttpSource() {
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
val params = TsukiMangasFilters.getSearchParameters(filters)
|
val params = TsukiMangasFilters.getSearchParameters(filters)
|
||||||
val url = "$API_URL/mangas".toHttpUrl().newBuilder()
|
val url = "$apiUrl/mangas".toHttpUrl().newBuilder()
|
||||||
.addQueryParameter("page", page.toString())
|
.addQueryParameter("page", page.toString())
|
||||||
.addQueryParameter("title", query.trim())
|
.addQueryParameter("title", query.trim())
|
||||||
.addIfNotBlank("filter", params.filter)
|
.addIfNotBlank("filter", params.filter)
|
||||||
|
@ -115,7 +115,7 @@ class TsukiMangas : HttpSource() {
|
||||||
// =========================== Manga Details ============================
|
// =========================== Manga Details ============================
|
||||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||||
val id = manga.url.getMangaId()
|
val id = manga.url.getMangaId()
|
||||||
return GET("$API_URL/mangas/$id", headers)
|
return GET("$apiUrl/mangas/$id", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
|
override fun getMangaUrl(manga: SManga) = baseUrl + manga.url
|
||||||
|
@ -145,12 +145,17 @@ class TsukiMangas : HttpSource() {
|
||||||
|
|
||||||
// ============================== Chapters ==============================
|
// ============================== Chapters ==============================
|
||||||
override fun chapterListRequest(manga: SManga): Request {
|
override fun chapterListRequest(manga: SManga): Request {
|
||||||
val id = manga.url.getMangaId()
|
val split = manga.url.split("/").reversed()
|
||||||
return GET("$API_URL/chapters/$id/all", headers)
|
val slug = split[0]
|
||||||
|
val id = split[1]
|
||||||
|
|
||||||
|
return GET("$apiUrl/chapters/$id/all#$slug", headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
val parsed = response.parseAs<ChapterListDto>()
|
val parsed = response.parseAs<ChapterListDto>()
|
||||||
|
val mangaSlug = response.request.url.fragment!!
|
||||||
|
val mangaId = response.request.url.pathSegments.reversed()[1]
|
||||||
|
|
||||||
return parsed.chapters.reversed().map {
|
return parsed.chapters.reversed().map {
|
||||||
SChapter.create().apply {
|
SChapter.create().apply {
|
||||||
|
@ -159,7 +164,7 @@ class TsukiMangas : HttpSource() {
|
||||||
// which could ruin the automatic chapter number recognition system.
|
// which could ruin the automatic chapter number recognition system.
|
||||||
chapter_number = it.number.trim { char -> !char.isDigit() }.toFloatOrNull() ?: 1F
|
chapter_number = it.number.trim { char -> !char.isDigit() }.toFloatOrNull() ?: 1F
|
||||||
|
|
||||||
url = "$API_PATH/chapter/versions/${it.versionId}"
|
url = "/leitor/$mangaId/${it.versionId}/$mangaSlug/${it.number}"
|
||||||
|
|
||||||
date_upload = it.created_at.orEmpty().toDate()
|
date_upload = it.created_at.orEmpty().toDate()
|
||||||
}
|
}
|
||||||
|
@ -167,9 +172,17 @@ class TsukiMangas : HttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// =============================== Pages ================================
|
// =============================== Pages ================================
|
||||||
|
override fun getChapterUrl(chapter: SChapter) = baseUrl + chapter.url
|
||||||
|
|
||||||
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
val versionId = chapter.url.split("/")[3]
|
||||||
|
|
||||||
|
return GET("$apiUrl/chapter/versions/$versionId", headers)
|
||||||
|
}
|
||||||
|
|
||||||
override fun pageListParse(response: Response): List<Page> {
|
override fun pageListParse(response: Response): List<Page> {
|
||||||
val data = response.parseAs<PageListDto>()
|
val data = response.parseAs<PageListDto>()
|
||||||
val sortedPages = data.pages.sortedBy { it.url.substringAfterLast("/") }
|
val sortedPages = data.pages.sortedBy { it.url.extractPageNumber() }
|
||||||
val host = getImageHost(sortedPages.first().url)
|
val host = getImageHost(sortedPages.first().url)
|
||||||
|
|
||||||
return sortedPages.mapIndexed { index, item ->
|
return sortedPages.mapIndexed { index, item ->
|
||||||
|
@ -212,6 +225,14 @@ class TsukiMangas : HttpSource() {
|
||||||
.getOrNull() ?: 0L
|
.getOrNull() ?: 0L
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val pageNumberRegex = Regex("""(\d+)\.(png|jpg|jpeg|gif|webp)$""")
|
||||||
|
|
||||||
|
private fun String.extractPageNumber() = pageNumberRegex
|
||||||
|
.find(substringBefore("?"))
|
||||||
|
?.groupValues
|
||||||
|
?.get(1)
|
||||||
|
?.toInt() ?: 0
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This may sound stupid (because it is), but a similar approach exists
|
* This may sound stupid (because it is), but a similar approach exists
|
||||||
* in the source itself, because they somehow don't know to which server
|
* in the source itself, because they somehow don't know to which server
|
||||||
|
@ -247,6 +268,6 @@ class TsukiMangas : HttpSource() {
|
||||||
|
|
||||||
private const val MAIN_CDN = "https://cdn.tsuki-mangas.com/tsuki"
|
private const val MAIN_CDN = "https://cdn.tsuki-mangas.com/tsuki"
|
||||||
private const val SECONDARY_CDN = "https://cdn2.tsuki-mangas.com"
|
private const val SECONDARY_CDN = "https://cdn2.tsuki-mangas.com"
|
||||||
private const val API_PATH = "/api/v2"
|
private const val API_PATH = "/api/d1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue