Fix Baozimh.org and rename to GoDa Manhua (#3087)
* Fix Baozimh * Cleanup * Fix author info * Use parent request * Bump versionID * Update * Update code * Rename source to GoDa Manhua and update icon (to distinguish from the "legit" Baozi Manhua) * Add English source * Update * Update * Keep the Chinese source only for now * Add comments to explain why the English source is not added * Error message on old chapter keys --------- Co-authored-by: stevenyomi <95685115+stevenyomi@users.noreply.github.com>
@ -1,7 +1,7 @@
|
||||
ext {
|
||||
extName = 'Baozimh.org'
|
||||
extClass = '.BaozimhOrg'
|
||||
extVersionCode = 28
|
||||
extName = 'GoDa'
|
||||
extClass = '.GoDaManhua'
|
||||
extVersionCode = 29
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
||||
|
Before Width: | Height: | Size: 3.4 KiB After Width: | Height: | Size: 2.3 KiB |
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.3 KiB |
Before Width: | Height: | Size: 5.0 KiB After Width: | Height: | Size: 2.9 KiB |
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5.2 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 6.7 KiB |
@ -1,10 +1,6 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import android.app.Application
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.Filter
|
||||
import eu.kanade.tachiyomi.source.model.FilterList
|
||||
import eu.kanade.tachiyomi.source.model.MangasPage
|
||||
@ -13,140 +9,133 @@ import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import eu.kanade.tachiyomi.source.model.SManga
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import org.jsoup.select.Evaluator
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import org.jsoup.nodes.Entities
|
||||
import rx.Observable
|
||||
|
||||
// Uses WPManga + GeneratePress/Blocksy Child
|
||||
class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
open class BaozimhOrg(
|
||||
override val name: String,
|
||||
override val baseUrl: String,
|
||||
override val lang: String,
|
||||
) : HttpSource() {
|
||||
|
||||
override val name get() = "包子漫画导航"
|
||||
override val lang get() = "zh"
|
||||
override val supportsLatest get() = true
|
||||
|
||||
override val baseUrl: String
|
||||
private val baseHttpUrl: HttpUrl
|
||||
private val enableGenres: Boolean
|
||||
private val enableGenres = true
|
||||
|
||||
init {
|
||||
val mirrors = MIRRORS
|
||||
val mirrorIndex = Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
.getString(MIRROR_PREF, "0")!!.toInt().coerceAtMost(mirrors.size - 1)
|
||||
baseUrl = "https://" + mirrors[mirrorIndex]
|
||||
baseHttpUrl = baseUrl.toHttpUrl()
|
||||
enableGenres = mirrorIndex == 0
|
||||
}
|
||||
override fun headersBuilder() = super.headersBuilder().add("Referer", "$baseUrl/")
|
||||
|
||||
override val client = network.client.newBuilder()
|
||||
.addInterceptor(UrlInterceptor)
|
||||
.build()
|
||||
override val client = network.cloudflareClient
|
||||
|
||||
private fun getKey(link: String): String {
|
||||
val pathSegments = baseHttpUrl.resolve(link)!!.pathSegments
|
||||
val fromIndex = if (pathSegments[0] == "manga") 1 else 0
|
||||
val toIndex = if (pathSegments.last().isEmpty()) pathSegments.size - 1 else pathSegments.size
|
||||
val list = pathSegments.subList(fromIndex, toIndex).toMutableList()
|
||||
list[0] = list[0].split("-").take(2).joinToString("-")
|
||||
return list.joinToString("/")
|
||||
return link.substringAfter("/manga/").removeSuffix("/")
|
||||
}
|
||||
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/hots/page/$page/", headers)
|
||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/hots/page/$page", headers)
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup().also(::parseGenres)
|
||||
val mangas = document.select("article.wp-manga").map { element ->
|
||||
val mangas = document.select(".cardlist .pb-2 a").map { element ->
|
||||
SManga.create().apply {
|
||||
val link = element.selectFirst(Evaluator.Tag("h2"))!!.child(0)
|
||||
url = getKey(link.attr("href"))
|
||||
title = link.ownText()
|
||||
thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.imgSrc
|
||||
val imgSrc = element.selectFirst("img")!!.attr("src")
|
||||
url = getKey(element.attr("href"))
|
||||
title = element.selectFirst("h3")!!.ownText()
|
||||
thumbnail_url = if ("url=" in imgSrc) imgSrc.toHttpUrl().queryParameter("url")!! else imgSrc
|
||||
}
|
||||
}
|
||||
val hasNextPage = document.selectFirst(Evaluator.Class("next"))?.tagName() == "a" ||
|
||||
document.selectFirst(".gb-button[aria-label=Next page]") != null
|
||||
val nextPage = if (lang == "zh") "下一頁" else "NEXT"
|
||||
val hasNextPage = document.selectFirst("a[aria-label=$nextPage] button") != null
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/newss/page/$page/", headers)
|
||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/newss/page/$page", headers)
|
||||
|
||||
override fun latestUpdatesParse(response: Response) = popularMangaParse(response)
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
if (query.isNotEmpty()) {
|
||||
val url = "$baseUrl/page/$page/".toHttpUrl().newBuilder()
|
||||
.addQueryParameter("s", query)
|
||||
return Request.Builder().url(url.build()).headers(headers).build()
|
||||
val url = "$baseUrl/s".toHttpUrl().newBuilder()
|
||||
.addPathSegment(query)
|
||||
.addEncodedQueryParameter("page", "$page")
|
||||
.build()
|
||||
return GET(url, headers)
|
||||
}
|
||||
for (filter in filters) {
|
||||
if (filter is UriPartFilter) return GET(baseUrl + filter.toUriPart() + "page/$page/", headers)
|
||||
if (filter is UriPartFilter) return GET(baseUrl + filter.toUriPart() + "/page/$page", headers)
|
||||
}
|
||||
return popularMangaRequest(page)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response) = popularMangaParse(response)
|
||||
|
||||
override fun getMangaUrl(manga: SManga) = "$baseUrl/manga/${manga.url}"
|
||||
|
||||
override fun mangaDetailsRequest(manga: SManga): Request {
|
||||
val url = manga.url
|
||||
if (url[0] == '/') throw Exception(MIGRATE)
|
||||
return GET("$baseUrl/manga/$url/", headers)
|
||||
return GET(getMangaUrl(manga), headers)
|
||||
}
|
||||
|
||||
private fun Document.getMangaId() = selectFirst("#mangachapters")!!.attr("data-mid")
|
||||
|
||||
override fun mangaDetailsParse(response: Response) = SManga.create().apply {
|
||||
val document = response.asJsoup()
|
||||
title = document.selectFirst(Evaluator.Tag("h1"))!!.ownText()
|
||||
author = document.selectFirst(Evaluator.Class("author-content"))!!.children().joinToString { it.ownText() }
|
||||
description = document.selectFirst(".descrip_manga_info, .wp-block-stackable-text")!!.text()
|
||||
thumbnail_url = document.selectFirst("img.wp-post-image")!!.imgSrc
|
||||
val titleElement = document.selectFirst("h1")!!
|
||||
val elements = titleElement.parent()!!.parent()!!.children()
|
||||
check(elements.size == 6)
|
||||
|
||||
val genreList = document.selectFirst(Evaluator.Class("genres-content"))!!
|
||||
.children().eachText().toMutableSet()
|
||||
if ("连载中" in genreList) {
|
||||
genreList.remove("连载中")
|
||||
status = SManga.ONGOING
|
||||
} else if ("已完结" in genreList) {
|
||||
genreList.remove("已完结")
|
||||
status = SManga.COMPLETED
|
||||
}
|
||||
genre = genreList.joinToString()
|
||||
title = titleElement.ownText()
|
||||
status = SManga.UNKNOWN // Everything is marked as ongoing
|
||||
author = Entities.unescape(elements[1].children().drop(1).joinToString { it.text().removeSuffix(" ,") })
|
||||
genre = buildList {
|
||||
elements[2].children().drop(1).mapTo(this) { it.text().removeSuffix(" ,") }
|
||||
elements[3].children().mapTo(this) { it.text().removePrefix("#") }
|
||||
}.joinToString()
|
||||
description = elements[4].text() + "\n\nID: ${document.getMangaId()}"
|
||||
thumbnail_url = document.selectFirst("img.object-cover")!!.attr("src")
|
||||
}
|
||||
|
||||
override fun chapterListRequest(manga: SManga): Request {
|
||||
val url = manga.url
|
||||
if (url[0] == '/') throw Exception(MIGRATE)
|
||||
return GET("$baseUrl/chapterlist/$url/", headers)
|
||||
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.fromCallable {
|
||||
val mangaId = manga.description
|
||||
?.substringAfterLast("\nID: ", "")
|
||||
?.takeIf { it.isNotEmpty() && it.all(Character::isDigit) }
|
||||
?: client.newCall(mangaDetailsRequest(manga)).execute().asJsoup().getMangaId()
|
||||
|
||||
fetchChapterList(mangaId)
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
return document.selectFirst(Evaluator.Class("version-chaps"))!!.children().map {
|
||||
throw UnsupportedOperationException()
|
||||
}
|
||||
|
||||
open fun fetchChapterList(mangaId: String): List<SChapter> {
|
||||
val response = client.newCall(GET("$baseUrl/manga/get?mid=$mangaId&mode=all", headers)).execute()
|
||||
|
||||
return response.asJsoup().select(".chapteritem").asReversed().map { element ->
|
||||
val anchor = element.selectFirst("a")!!
|
||||
SChapter.create().apply {
|
||||
url = getKey(it.attr("href"))
|
||||
name = it.ownText()
|
||||
date_upload = parseChapterDate(it.child(0).text())
|
||||
url = getKey(anchor.attr("href")) + "#$mangaId/" + anchor.attr("data-cs")
|
||||
name = anchor.attr("data-ct")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun getChapterUrl(chapter: SChapter) = "$baseUrl/manga/" + chapter.url.substringBeforeLast('#')
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
val url = chapter.url
|
||||
if (url[0] == '/') throw Exception(MIGRATE)
|
||||
return GET("$baseUrl/manga/$url/", headers)
|
||||
val id = chapter.url.substringAfterLast('#', "")
|
||||
val mangaId = id.substringBefore('/')
|
||||
val chapterId = id.substringAfter('/')
|
||||
return pageListRequest(mangaId, chapterId)
|
||||
}
|
||||
|
||||
open fun pageListRequest(mangaId: String, chapterId: String) = GET("$baseUrl/chapter/getcontent?m=$mangaId&c=$chapterId", headers)
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
// Jsoup won't ignore duplicates inside <noscript> tag
|
||||
document.select(Evaluator.Tag("noscript")).remove()
|
||||
return document.select("img[decoding=async]").mapIndexed { index, element ->
|
||||
Page(index, imageUrl = element.imgSrc)
|
||||
return document.select("noscript > img").mapIndexed { index, element ->
|
||||
Page(index, imageUrl = element.attr("src"))
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,26 +145,23 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
|
||||
private fun parseGenres(document: Document) {
|
||||
if (!enableGenres || genres.isNotEmpty()) return
|
||||
val box = document.selectFirst(Evaluator.Class("wp-block-navigation__container")) ?: return
|
||||
val items = box.children()
|
||||
genres = buildList(items.size + 1) {
|
||||
add(Pair("全部", "/allmanga/"))
|
||||
items.mapTo(this) {
|
||||
val link = it.child(0)
|
||||
Pair(link.text(), link.attr("href"))
|
||||
}
|
||||
}.toTypedArray()
|
||||
val box = document.selectFirst("h2")?.parent()?.parent() ?: return
|
||||
val items = box.select("a")
|
||||
genres = Array(items.size) { i ->
|
||||
val item = items[i]
|
||||
Pair(item.text().removePrefix("#"), item.attr("href"))
|
||||
}
|
||||
}
|
||||
|
||||
override fun getFilterList(): FilterList =
|
||||
if (!enableGenres) {
|
||||
FilterList()
|
||||
} else if (genres.isEmpty()) {
|
||||
FilterList(listOf(Filter.Header("点击“重置”刷新分类")))
|
||||
FilterList(listOf(Filter.Header(if (lang == "zh") "点击“重置”刷新分类" else "Tap 'Reset' to load genres")))
|
||||
} else {
|
||||
val list = listOf(
|
||||
Filter.Header("分类(搜索文本时无效)"),
|
||||
UriPartFilter("分类", genres),
|
||||
Filter.Header(if (lang == "zh") "分类(搜索文本时无效)" else "Filters are ignored when using text search."),
|
||||
UriPartFilter(if (lang == "zh") "分类" else "Genre", genres),
|
||||
)
|
||||
FilterList(list)
|
||||
}
|
||||
@ -184,33 +170,4 @@ class BaozimhOrg : HttpSource(), ConfigurableSource {
|
||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||
fun toUriPart() = vals[state].second
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
ListPreference(screen.context).apply {
|
||||
val mirrors = MIRRORS
|
||||
key = MIRROR_PREF
|
||||
title = "镜像网址"
|
||||
summary = "%s\n重启生效,暂未适配GoDa漫画的分类筛选功能"
|
||||
entries = mirrors
|
||||
entryValues = Array(mirrors.size) { it.toString() }
|
||||
setDefaultValue("0")
|
||||
}.let(screen::addPreference)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MIRROR_PREF = "MIRROR"
|
||||
private val MIRRORS get() = arrayOf("baozimh.org", "cn.godamanga.com")
|
||||
|
||||
const val MIGRATE = "请将此漫画重新迁移到本图源"
|
||||
|
||||
val Element.imgSrc: String get() = attr("data-src").ifEmpty { attr("src") }
|
||||
|
||||
private val dateFormat by lazy { SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) }
|
||||
|
||||
fun parseChapterDate(text: String): Long = try {
|
||||
dateFormat.parse(text)!!.time
|
||||
} catch (_: Throwable) {
|
||||
0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,61 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import kotlinx.serialization.Serializable
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Locale
|
||||
import java.util.TimeZone
|
||||
|
||||
@Serializable
|
||||
class ResponseDto<T>(val data: T)
|
||||
|
||||
@Serializable
|
||||
class ChapterListDto(
|
||||
private val id: Int,
|
||||
private val slug: String,
|
||||
private val chapters: List<ChapterDto>,
|
||||
) {
|
||||
fun toChapterList(): List<SChapter> {
|
||||
val mangaId = id.toString()
|
||||
val mangaSlug = slug
|
||||
return chapters.asReversed().map { it.toSChapter(mangaSlug, mangaId) }
|
||||
}
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class ChapterDto(
|
||||
private val id: Int,
|
||||
private val attributes: AttributesDto,
|
||||
) {
|
||||
fun toSChapter(mangaSlug: String, mangaId: String) = attributes.toSChapter(mangaSlug, mangaId, id.toString())
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class AttributesDto(
|
||||
private val title: String,
|
||||
private val slug: String,
|
||||
private val updatedAt: String,
|
||||
) {
|
||||
fun toSChapter(mangaSlug: String, mangaId: String, chapterId: String) = SChapter.create().apply {
|
||||
url = "$mangaSlug/$slug#$mangaId/$chapterId"
|
||||
name = title
|
||||
date_upload = dateFormat.parse(updatedAt)!!.time
|
||||
}
|
||||
}
|
||||
|
||||
// Static field, no need for lazy
|
||||
private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US).apply {
|
||||
timeZone = TimeZone.getTimeZone("UTC")
|
||||
}
|
||||
|
||||
@Serializable
|
||||
class PageListDto(val info: PageListInfoDto)
|
||||
|
||||
@Serializable
|
||||
class PageListInfoDto(val images: List<ImageDto>)
|
||||
|
||||
@Serializable
|
||||
class ImageDto(private val url: String, private val order: Int) {
|
||||
fun toPage() = Page(order, imageUrl = url)
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import eu.kanade.tachiyomi.source.SourceFactory
|
||||
|
||||
// This is not used because ideally the extension language should be updated to "Multi" (all).
|
||||
// Chinese users don't receive status updates from Discord, so I'll keep the package name unchanged for now.
|
||||
class GoDaFactory : SourceFactory {
|
||||
override fun createSources() = listOf(
|
||||
GoDaManhua(),
|
||||
BaozimhOrg("Goda", "https://manhuascans.org", "en"),
|
||||
)
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import android.app.Application
|
||||
import androidx.preference.ListPreference
|
||||
import androidx.preference.PreferenceScreen
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import eu.kanade.tachiyomi.source.model.Page
|
||||
import eu.kanade.tachiyomi.source.model.SChapter
|
||||
import kotlinx.serialization.decodeFromString
|
||||
import kotlinx.serialization.json.Json
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import okio.IOException
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
||||
class GoDaManhua : BaozimhOrg("GoDa漫画", "", "zh"), ConfigurableSource {
|
||||
|
||||
override val id get() = 774030471139699415
|
||||
|
||||
override val baseUrl: String
|
||||
|
||||
init {
|
||||
val mirrors = MIRRORS
|
||||
if (System.getenv("CI") == "true") {
|
||||
baseUrl = mirrors.joinToString("#, ") { "https://$it" }
|
||||
} else {
|
||||
val mirrorIndex = Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||
.getString(MIRROR_PREF, "0")!!.toInt().coerceAtMost(mirrors.size - 1)
|
||||
baseUrl = "https://" + mirrors[mirrorIndex]
|
||||
}
|
||||
}
|
||||
|
||||
override val client = super.client.newBuilder().addInterceptor(NotFoundInterceptor()).build()
|
||||
|
||||
private val json: Json = Injekt.get()
|
||||
|
||||
override fun fetchChapterList(mangaId: String): List<SChapter> {
|
||||
val response = client.newCall(GET("https://api-get.mgsearcher.com/api/manga/get?mid=$mangaId&mode=all", headers)).execute()
|
||||
return json.decodeFromString<ResponseDto<ChapterListDto>>(response.body.string()).data.toChapterList()
|
||||
}
|
||||
|
||||
override fun pageListRequest(mangaId: String, chapterId: String): Request {
|
||||
if (mangaId.isEmpty() || chapterId.isEmpty()) throw Exception("请刷新漫画")
|
||||
return GET("https://api-get.mgsearcher.com/api/chapter/getinfo?m=$mangaId&c=$chapterId", headers)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
return json.decodeFromString<ResponseDto<PageListDto>>(response.body.string()).data.info.images.map { it.toPage() }
|
||||
}
|
||||
|
||||
override fun setupPreferenceScreen(screen: PreferenceScreen) {
|
||||
ListPreference(screen.context).apply {
|
||||
val mirrors = MIRRORS
|
||||
key = MIRROR_PREF
|
||||
title = "镜像网址"
|
||||
summary = "%s\n重启生效"
|
||||
entries = mirrors
|
||||
entryValues = Array(mirrors.size, Int::toString)
|
||||
setDefaultValue("0")
|
||||
}.let(screen::addPreference)
|
||||
}
|
||||
}
|
||||
|
||||
private const val MIRROR_PREF = "MIRROR"
|
||||
|
||||
// https://nav.telltome.net/
|
||||
private val MIRRORS get() = arrayOf("baozimh.org", "godamh.com", "m.baozimh.one")
|
||||
|
||||
private class NotFoundInterceptor : Interceptor {
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val response = chain.proceed(chain.request())
|
||||
if (response.code != 404) return response
|
||||
response.close()
|
||||
throw IOException("请将此漫画重新迁移到本图源")
|
||||
}
|
||||
}
|
@ -1,32 +0,0 @@
|
||||
package eu.kanade.tachiyomi.extension.zh.baozimhorg
|
||||
|
||||
import okhttp3.Interceptor
|
||||
import okhttp3.Response
|
||||
|
||||
// Temporary interceptor to handle URL redirections
|
||||
object UrlInterceptor : Interceptor {
|
||||
|
||||
override fun intercept(chain: Interceptor.Chain): Response {
|
||||
val request = chain.request()
|
||||
val url = request.url
|
||||
val (type, slug) = url.pathSegments
|
||||
when (type) {
|
||||
"manga", "chapterlist" -> {}
|
||||
else -> return chain.proceed(request)
|
||||
}
|
||||
|
||||
val mangaUrl = "/manga/$slug/"
|
||||
val headRequest = request.newBuilder()
|
||||
.head()
|
||||
.url(url.resolve(mangaUrl)!!)
|
||||
.build()
|
||||
// might redirect multiple times
|
||||
val headResponse = chain.proceed(headRequest)
|
||||
if (headResponse.priorResponse == null) return chain.proceed(request)
|
||||
|
||||
val realSlug = headResponse.request.url.pathSegments[1]
|
||||
val newUrl = url.newBuilder().setEncodedPathSegment(1, realSlug).build()
|
||||
val newRequest = request.newBuilder().url(newUrl).build()
|
||||
return chain.proceed(newRequest)
|
||||
}
|
||||
}
|