diff --git a/multisrc/overrides/sinmh/gufengmh/src/Gufengmh.kt b/multisrc/overrides/sinmh/gufengmh/src/Gufengmh.kt new file mode 100644 index 000000000..4eaf4fb24 --- /dev/null +++ b/multisrc/overrides/sinmh/gufengmh/src/Gufengmh.kt @@ -0,0 +1,10 @@ +package eu.kanade.tachiyomi.extension.zh.gufengmh + +import eu.kanade.tachiyomi.multisrc.sinmh.SinMH + +class Gufengmh : SinMH("古风漫画网", "https://www.gufengmh9.com") { + + override val dateSelector = ".pic_zi:nth-of-type(4) > dd" + + override fun chapterListSelector() = ".list li > a" +} diff --git a/multisrc/overrides/sinmh/imitui/src/Imitui.kt b/multisrc/overrides/sinmh/imitui/src/Imitui.kt index b22967962..673351963 100644 --- a/multisrc/overrides/sinmh/imitui/src/Imitui.kt +++ b/multisrc/overrides/sinmh/imitui/src/Imitui.kt @@ -1,23 +1,15 @@ package eu.kanade.tachiyomi.extension.zh.imitui import eu.kanade.tachiyomi.multisrc.sinmh.SinMH -import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.model.Page -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.source.model.SManga import org.jsoup.nodes.Document class Imitui : SinMH("爱米推漫画", "https://www.imitui.com") { - private val mobileUrl = "https://m.imitui.com" - - override fun chapterListRequest(manga: SManga) = GET(mobileUrl + manga.url, headers) - - override fun pageListRequest(chapter: SChapter) = GET(mobileUrl + chapter.url, headers) override fun pageListParse(document: Document): List { val pageCount = document.select("div.image-content > p").text().removePrefix("1/").toInt() val prefix = document.location().removeSuffix(".html") - return (0 until pageCount).map { Page(it, "$prefix-${it + 1}.html") } + return (0 until pageCount).map { Page(it, url = "$prefix-${it + 1}.html") } } override fun imageUrlParse(document: Document): String = diff --git a/multisrc/overrides/sinmh/manhuadui/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/sinmh/manhuadui/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..977fa4f9d Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/sinmh/manhuadui/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..14e1f3d02 Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..bec42bc83 Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..12021be2f Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..1a8abce6f Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/res/web_hi_res_512.png b/multisrc/overrides/sinmh/manhuadui/res/web_hi_res_512.png new file mode 100644 index 000000000..bcaa3f4e4 Binary files /dev/null and b/multisrc/overrides/sinmh/manhuadui/res/web_hi_res_512.png differ diff --git a/multisrc/overrides/sinmh/manhuadui/src/YKMH.kt b/multisrc/overrides/sinmh/manhuadui/src/YKMH.kt new file mode 100644 index 000000000..80f73b304 --- /dev/null +++ b/multisrc/overrides/sinmh/manhuadui/src/YKMH.kt @@ -0,0 +1,31 @@ +package eu.kanade.tachiyomi.extension.zh.manhuadui + +import eu.kanade.tachiyomi.multisrc.sinmh.SinMH +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import org.jsoup.nodes.Document + +class YKMH : SinMH("优酷漫画", "http://www.ykmh.com") { + override val id = 1637952806167036168 + override val mobileUrl = "http://wap.ykmh.com" + + override val comicItemSelector = "li.list-comic" + override val comicItemTitleSelector = "h3 > a, p > a" + + // DMZJ style + override fun mangaDetailsParse(document: Document) = SManga.create().apply { + title = document.selectFirst("h1").text() + val details = document.selectFirst("ul.comic_deCon_liO").children() + author = details[0].selectFirst("a").text() + status = when (details[1].selectFirst("a").text()) { + "连载中" -> SManga.ONGOING + "已完结" -> SManga.COMPLETED + else -> SManga.UNKNOWN + } + genre = (details[2].select("a") + details[3].select("a")).joinToString(", ") { it.text() } + description = document.selectFirst("p.comic_deCon_d").text() + thumbnail_url = document.selectFirst("div.comic_i_img > img").attr("src") + } + + override fun List.sortedDescending() = this +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMH.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMH.kt index 2766c882d..96cd03d18 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMH.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMH.kt @@ -1,9 +1,10 @@ package eu.kanade.tachiyomi.multisrc.sinmh -import android.util.Log +import eu.kanade.tachiyomi.AppInfo import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SManga @@ -13,7 +14,8 @@ import okhttp3.Headers import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element -import kotlin.concurrent.thread +import java.text.SimpleDateFormat +import java.util.Locale /** * 圣樱漫画CMS https://gitee.com/shenl/SinMH-2.0-Guide @@ -26,6 +28,7 @@ abstract class SinMH( override val lang: String = "zh", ) : ParsedHttpSource() { override val baseUrl = _baseUrl + protected open val mobileUrl = _baseUrl.replace("www", "m") override val supportsLatest = true override fun headersBuilder(): Headers.Builder = Headers.Builder() @@ -34,13 +37,12 @@ abstract class SinMH( protected open val nextPageSelector = "ul.pagination > li.next:not(.disabled)" protected open val comicItemSelector = "#contList > li" protected open val comicItemTitleSelector = "p > a" - protected open fun mangaFromElement(element: Element) = - SManga.create().apply { - val titleElement = element.select(comicItemTitleSelector) - title = titleElement.text() - setUrlWithoutDomain(titleElement.attr("abs:href")) - thumbnail_url = element.select("img").attr("abs:src") - } + protected open fun mangaFromElement(element: Element) = SManga.create().apply { + val titleElement = element.selectFirst(comicItemTitleSelector) + title = titleElement.text() + setUrlWithoutDomain(titleElement.attr("abs:href")) + thumbnail_url = element.selectFirst("img").attr("abs:src") + } // Popular @@ -49,6 +51,14 @@ abstract class SinMH( override fun popularMangaSelector() = comicItemSelector override fun popularMangaFromElement(element: Element) = mangaFromElement(element) + override fun popularMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + parseCategories(document) + val mangas = document.select(popularMangaSelector()).map(::popularMangaFromElement) + val hasNextPage = popularMangaNextPageSelector()?.let { document.selectFirst(it) } != null + return MangasPage(mangas, hasNextPage) + } + // Latest override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/list/update/?page=$page", headers) @@ -56,6 +66,14 @@ abstract class SinMH( override fun latestUpdatesSelector() = comicItemSelector override fun latestUpdatesFromElement(element: Element) = mangaFromElement(element) + override fun latestUpdatesParse(response: Response): MangasPage { + val document = response.asJsoup() + parseCategories(document) + val mangas = document.select(latestUpdatesSelector()).map(::latestUpdatesFromElement) + val hasNextPage = latestUpdatesNextPageSelector()?.let { document.selectFirst(it) } != null + return MangasPage(mangas, hasNextPage) + } + // Search override fun searchMangaNextPageSelector(): String? = nextPageSelector @@ -65,34 +83,48 @@ abstract class SinMH( if (query.isNotBlank()) { GET("$baseUrl/search/?keywords=$query&page=$page", headers) } else { - val categories = filters.filterIsInstance() - .joinToString("-", transform = UriPartFilter::toUriPart) + "-" + val categories = filters.filterIsInstance().map { it.toUriPart() } + .filter { it.isNotEmpty() }.joinToString("-") + "-" GET("$baseUrl/list/$categories/", headers) } // Details override fun mangaDetailsParse(document: Document) = SManga.create().apply { - title = document.select(".book-title > h1 > span").text() - author = document.select(".detail-list strong:contains(作者) + a").text() - description = document.select("#intro-all").text().trim() + title = document.selectFirst(".book-title > h1 > span").text() + author = document.selectFirst(".detail-list strong:contains(作者) + a").text() + description = document.selectFirst("#intro-all").text().trim() .removePrefix("漫画简介:").trim() .removePrefix("漫画简介:").trim() // some sources have double prefix - genre = document.select(".detail-list strong:contains(类型) + a").text() + ", " + + genre = document.selectFirst(".detail-list strong:contains(类型) + a").text() + ", " + document.select(".breadcrumb-bar a[href*=/list/]").joinToString(", ") { it.text() } - status = when (document.select(".detail-list strong:contains(状态) + a").text()) { + status = when (document.selectFirst(".detail-list strong:contains(状态) + a").text()) { "连载中" -> SManga.ONGOING "已完结" -> SManga.COMPLETED else -> SManga.UNKNOWN } - thumbnail_url = document.select("p.cover > img").attr("abs:src") - // TODO: can use 更新时间:2022-05-23 to set default upload date + thumbnail_url = document.selectFirst("p.cover > img").attr("abs:src") } // Chapters - override fun chapterListSelector() = ".chapter-body li > a:not([href*=/comic/app/])" - override fun chapterListParse(response: Response) = super.chapterListParse(response).reversed() + override fun chapterListRequest(manga: SManga) = GET(mobileUrl + manga.url, headers) + + protected open val dateSelector = ".date" + + protected open fun List.sortedDescending() = this.asReversed() + + override fun chapterListParse(response: Response): List { + val document = response.asJsoup() + return document.select(chapterListSelector()).map { chapterFromElement(it) }.sortedDescending().apply { + if (isNewDateLogic) { + val date = document.selectFirst(dateSelector).textNodes().last().text() + this[0].date_upload = DATE_FORMAT.parse(date)?.time ?: 0L + } + } + } + + override fun chapterListSelector() = ".chapter-body li > a:not([href^=/comic/app/])" override fun chapterFromElement(element: Element) = SChapter.create().apply { setUrlWithoutDomain(element.attr("abs:href")) name = element.text() @@ -100,13 +132,23 @@ abstract class SinMH( // Pages + override fun pageListRequest(chapter: SChapter) = GET(mobileUrl + chapter.url, headers) + override fun pageListParse(document: Document): List { - val script = document.select("script:containsData(chapterImages)").html() + val script = document.selectFirst("body > script").html() val images = script.substringAfter("chapterImages = [\"").substringBefore("\"]").split("\",\"") val path = script.substringAfter("chapterPath = \"").substringBefore("\";") - // assume cover images are on the same server + // assume cover images are on the page image server val server = script.substringAfter("pageImage = \"").substringBefore("/images/cover") - return images.mapIndexed { i, image -> Page(i, "", "$server/$path/$image") } + return images.mapIndexed { i, image -> + val unescapedImage = image.replace("""\/""", "/") + val imageUrl = if (unescapedImage.startsWith("/")) { + "$server$unescapedImage" + } else { + "$server/$path$unescapedImage" + } + Page(i, imageUrl = imageUrl) + } } override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not Used.") @@ -121,26 +163,11 @@ abstract class SinMH( } private lateinit var categories: List - private var isFetchingCategories = false - private fun tryFetchCategories() { - if (isFetchingCategories) return - isFetchingCategories = true - thread { - try { - fetchCategories() - } catch (e: Exception) { - Log.e("SinMH", "Failed to fetch categories ($e)") - } finally { - isFetchingCategories = false - } - } - } - - protected open fun fetchCategories() { - val document = client.newCall(GET("$baseUrl/list/", headers)).execute().asJsoup() - categories = document.select(".page-main .filter-nav > .filter-item").map { element -> - val name = element.select("label").text() + protected open fun parseCategories(document: Document) { + if (::categories.isInitialized) return + categories = document.selectFirst(".filter-nav").children().map { element -> + val name = element.selectFirst("label").text() val tags = element.select("a") val values = tags.map { it.text() }.toTypedArray() val uriParts = tags.map { it.attr("href").removePrefix("/list/").removeSuffix("/") }.toTypedArray() @@ -152,10 +179,17 @@ abstract class SinMH( if (::categories.isInitialized) FilterList( Filter.Header("如果使用文本搜索,将会忽略分类筛选"), *categories.map(Category::toUriPartFilter).toTypedArray() - ) else { - tryFetchCategories() - FilterList( - Filter.Header("分类尚未获取,请返回上一页后重试") - ) - } + ) else FilterList( + Filter.Header("点击“重置”即可刷新分类,如果失败,"), + Filter.Header("请尝试重新从图源列表点击进入图源"), + ) + + private val DATE_FORMAT = SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH) + private val isNewDateLogic = run { + val commitCount = AppInfo.getVersionName().substringAfter('-', "") + if (commitCount.isNotEmpty()) // Preview + commitCount.toInt() >= 4442 + else // Stable + AppInfo.getVersionCode() >= 81 + } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMHGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMHGenerator.kt index 1a9599089..486602c1c 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMHGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/sinmh/SinMHGenerator.kt @@ -6,7 +6,7 @@ import generator.ThemeSourceGenerator class SinMHGenerator : ThemeSourceGenerator { override val themeClass = "SinMH" override val themePkg = "sinmh" - override val baseVersionCode = 3 + override val baseVersionCode = 4 override val sources = listOf( SingleLang( name = "Gufeng Manhua", baseUrl = "https://www.gufengmh9.com", lang = "zh", @@ -15,7 +15,11 @@ class SinMHGenerator : ThemeSourceGenerator { SingleLang( name = "Imitui Manhua", baseUrl = "https://www.imitui.com", lang = "zh", className = "Imitui", sourceName = "爱米推漫画", overrideVersionCode = 2 - ) + ), + SingleLang( + name = "YKMH", baseUrl = "http://www.ykmh.com", lang = "zh", className = "YKMH", + pkgName = "manhuadui", sourceName = "优酷漫画", overrideVersionCode = 17 + ), ) companion object { diff --git a/src/zh/manhuadui/AndroidManifest.xml b/src/zh/manhuadui/AndroidManifest.xml deleted file mode 100644 index 30deb7f79..000000000 --- a/src/zh/manhuadui/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/zh/manhuadui/build.gradle b/src/zh/manhuadui/build.gradle deleted file mode 100644 index 61ccbbb14..000000000 --- a/src/zh/manhuadui/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'Manhuadui' - pkgNameSuffix = 'zh.manhuadui' - extClass = '.Manhuadui' - extVersionCode = 17 -} - -apply from: "$rootDir/common.gradle" diff --git a/src/zh/manhuadui/res/mipmap-hdpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 1110e132e..000000000 Binary files a/src/zh/manhuadui/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/mipmap-ldpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-ldpi/ic_launcher.png deleted file mode 100644 index 1427b9a3c..000000000 Binary files a/src/zh/manhuadui/res/mipmap-ldpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/mipmap-mdpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index feb33c870..000000000 Binary files a/src/zh/manhuadui/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/mipmap-xhdpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 71c1bf650..000000000 Binary files a/src/zh/manhuadui/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index ad5ca6908..000000000 Binary files a/src/zh/manhuadui/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png b/src/zh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index cb4d7bf1d..000000000 Binary files a/src/zh/manhuadui/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/zh/manhuadui/res/web_hi_res_512.png b/src/zh/manhuadui/res/web_hi_res_512.png deleted file mode 100644 index b2d6624d0..000000000 Binary files a/src/zh/manhuadui/res/web_hi_res_512.png and /dev/null differ diff --git a/src/zh/manhuadui/src/eu/kanade/tachiyomi/extension/zh/manhuadui/Manhuadui.kt b/src/zh/manhuadui/src/eu/kanade/tachiyomi/extension/zh/manhuadui/Manhuadui.kt deleted file mode 100644 index ea661a7f6..000000000 --- a/src/zh/manhuadui/src/eu/kanade/tachiyomi/extension/zh/manhuadui/Manhuadui.kt +++ /dev/null @@ -1,205 +0,0 @@ -package eu.kanade.tachiyomi.extension.zh.manhuadui - -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.Filter -import eu.kanade.tachiyomi.source.model.FilterList -import eu.kanade.tachiyomi.source.model.Page -import eu.kanade.tachiyomi.source.model.SChapter -import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.source.online.ParsedHttpSource -import okhttp3.HttpUrl.Companion.toHttpUrlOrNull -import okhttp3.OkHttpClient -import okhttp3.Request -import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element - -class Manhuadui : ParsedHttpSource() { - - override val name = "漫画堆" - override val baseUrl = "https://ykmh.com" - override val lang = "zh" - override val supportsLatest = true - // Servers can be found from resHost in baseUrl/js/config.js - private val imageServer = arrayOf("https://js.tingliu.cc") - - override val client: OkHttpClient = super.client.newBuilder() - .followRedirects(true) - .build() - - override fun popularMangaSelector() = "li.list-comic" - override fun searchMangaSelector() = popularMangaSelector() - override fun latestUpdatesSelector() = popularMangaSelector() - override fun chapterListSelector() = "ul[id^=chapter-list] > li a" - - override fun searchMangaNextPageSelector() = "li.next a" - override fun popularMangaNextPageSelector() = searchMangaNextPageSelector() - override fun latestUpdatesNextPageSelector() = searchMangaNextPageSelector() - - override fun popularMangaRequest(page: Int) = GET("$baseUrl/list_$page/", headers) - override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/update/$page/", headers) - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - return if (query != "") { - val url = "$baseUrl/search/?keywords=$query&page=$page".toHttpUrlOrNull()?.newBuilder() - GET(url.toString(), headers) - } else { - val params = filters.map { - if (it is UriPartFilter) { - it.toUriPart() - } else "" - }.filter { it != "" }.joinToString("-") - val url = when { - params.isEmpty() -> "$baseUrl/list_$page/".toHttpUrlOrNull()?.newBuilder() - else -> "$baseUrl/list/$params/$page/".toHttpUrlOrNull()?.newBuilder() - } - GET(url.toString(), headers) - } - } - - override fun popularMangaFromElement(element: Element) = mangaFromElement(element) - override fun latestUpdatesFromElement(element: Element) = mangaFromElement(element) - private fun mangaFromElement(element: Element): SManga { - val manga = SManga.create() - element.select("a.comic_img").first().let { - manga.setUrlWithoutDomain(it.attr("href")) - manga.title = it.select("img").attr("alt").trim() - manga.thumbnail_url = if (it.select("img").attr("src").trim().indexOf("http") == -1) - "https:${it.select("img").attr("src").trim()}" - else it.select("img").attr("src").trim() - } - manga.author = element.select("span.comic_list_det > p").first()?.text()?.substring(3) - return manga - } - - override fun searchMangaFromElement(element: Element): SManga { - val manga = SManga.create() - val els = element.select("a.image-link") - if (els.size == 0) { - element.select("li.list-comic").first().let { - manga.setUrlWithoutDomain(it.select("a").attr("href")) - manga.title = it.select("span").attr("title").trim() - manga.thumbnail_url = it.select("a > img").attr("src").trim() - manga.author = it.select("span > p").first().text().split(":")[1].trim() - } - } else { - element.select("a.image-link").first().let { - manga.setUrlWithoutDomain(it.attr("href")) - manga.title = it.attr("title").trim() - manga.thumbnail_url = it.select("img").attr("src").trim() - } - manga.author = element.select("p.auth").text().trim() - } - return manga - } - - override fun chapterFromElement(element: Element): SChapter { - val chapter = SChapter.create() - chapter.setUrlWithoutDomain(element.attr("href")) - chapter.name = element.select("span:nth-child(2)").text().trim() - return chapter - } - - override fun mangaDetailsParse(document: Document): SManga { - val manga = SManga.create() - manga.description = document.select("p.comic_deCon_d").text().trim() - manga.thumbnail_url = document.select("div.comic_i_img > img").attr("src") - manga.status = when (document.select("ul.comic_deCon_liO a")[1].attr("href")) { - "/list/lianzai/" -> SManga.ONGOING - "/list/wanjie/" -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - manga.genre = document.select("ul.comic_deCon_liO li:nth-child(4) a").eachText().joinToString(", ") - return manga - } - - override fun chapterListRequest(manga: SManga) = GET(baseUrl.replace("www", "m") + manga.url) - override fun chapterListParse(response: Response): List { - return super.chapterListParse(response).asReversed() - } - - private val chapterImagesRegex = Regex("""var chapterImages =\s*\["(.*?)"\];""") - private val imgCodeCleanupRegex = Regex("""[\[\]"\\]""") - - override fun pageListParse(document: Document): List { - val html = document.html() - val imgCodeStr = chapterImagesRegex.find(html)?.groups?.get(1)?.value ?: throw Exception("imgCodeStr not found") - val imgCode = imgCodeStr - .replace(imgCodeCleanupRegex, "") - .replace("%", "%25") - return imgCode.split(",").mapIndexed { i, imgStr -> - // The way image urls are processed by the website can be found in - // getChapterImage() in baseUrl/js/common.js - if (imgStr.startsWith("http://images.dmzj.com")) { - Page(i, "", "${imageServer[0]}/showImage.php?url=$imgStr") - } else { - Page(i, "", if (imgStr.indexOf("http") == -1) "${imageServer[0]}$imgStr" else imgStr) - } - } - } - - override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used") - - override fun getFilterList() = FilterList( - CategoryGroup(), - RegionGroup(), - GenreGroup(), - ProgressGroup() - ) - - private class CategoryGroup : UriPartFilter( - "按类型", - arrayOf( - Pair("全部", ""), - Pair("儿童漫画", "ertong"), - Pair("少年漫画", "shaonian"), - Pair("少女漫画", "shaonv"), - Pair("青年漫画", "qingnian") - ) - ) - - private class ProgressGroup : UriPartFilter( - "按进度", - arrayOf( - Pair("全部", ""), - Pair("已完结", "wanjie"), - Pair("连载中", "lianzai") - ) - ) - - private class RegionGroup : UriPartFilter( - "按地区", - arrayOf( - Pair("全部", ""), - Pair("日本", "riben"), - Pair("大陆", "dalu"), - Pair("香港", "hongkong"), - Pair("台湾", "taiwan"), - Pair("欧美", "oumei"), - Pair("韩国", "hanguo"), - Pair("其他", "qita") - ) - ) - - private class GenreGroup : UriPartFilter( - "按剧情", - arrayOf( - Pair("全部", ""), - Pair("热血", "rexue"), - Pair("冒险", "maoxian"), - Pair("玄幻", "xuanhuan"), - Pair("搞笑", "gaoxiao"), - Pair("恋爱", "lianai"), - Pair("宠物", "chongwu"), - Pair("新作", "xinzuo") - ) - ) - - private open class UriPartFilter( - displayName: String, - val vals: Array>, - defaultValue: Int = 0 - ) : - Filter.Select(displayName, vals.map { it.first }.toTypedArray(), defaultValue) { - open fun toUriPart() = vals[state].second - } -}