From 87cd9dc9fb7669d521d50a2aca81701408530343 Mon Sep 17 00:00:00 2001 From: stevenyomi <95685115+stevenyomi@users.noreply.github.com> Date: Mon, 14 Jul 2025 08:47:55 +0000 Subject: [PATCH] Update MCCMS sources (#9631) * Add back Manhuawu, closes #1567 * Clean up 6Manhua * Add Miaoqu Manhua, closes #4482 * Add 2 French sources --- .../kanade/tachiyomi/multisrc/mccms/Intl.kt | 77 +++++++++++ .../kanade/tachiyomi/multisrc/mccms/MCCMS.kt | 30 +++-- .../tachiyomi/multisrc/mccms/MCCMSConfig.kt | 2 + .../tachiyomi/multisrc/mccms/MCCMSDto.kt | 10 +- .../tachiyomi/multisrc/mccms/MCCMSFilters.kt | 48 +++---- .../tachiyomi/multisrc/mccms/MCCMSWeb.kt | 57 ++++++--- src/fr/enlignemanga/build.gradle | 9 ++ .../extension/fr/enlignemanga/EnLigneManga.kt | 16 +++ src/fr/frmanga/build.gradle | 9 ++ .../tachiyomi/extension/fr/frmanga/FRManga.kt | 11 ++ src/zh/manhuawu/build.gradle | 9 ++ .../manhuawu/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2637 bytes .../manhuawu/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1511 bytes .../manhuawu/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3326 bytes .../res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 6181 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 8030 bytes .../extension/zh/manhuawu/Manhuawu.kt | 5 + src/zh/miaoqu/build.gradle | 9 ++ src/zh/miaoqu/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2508 bytes src/zh/miaoqu/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1409 bytes .../miaoqu/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3194 bytes .../miaoqu/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 5777 bytes .../miaoqu/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 7435 bytes .../tachiyomi/extension/zh/miaoqu/Miaoqu.kt | 120 ++++++++++++++++++ src/zh/sixmh/build.gradle | 4 +- .../tachiyomi/extension/zh/sixmh/Data.kt | 8 -- .../zh/sixmh/SimpleParsedHttpSource.kt | 27 ---- .../tachiyomi/extension/zh/sixmh/SixMH.kt | 38 ++---- 28 files changed, 371 insertions(+), 118 deletions(-) create mode 100644 lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/Intl.kt create mode 100644 src/fr/enlignemanga/build.gradle create mode 100644 src/fr/enlignemanga/src/eu/kanade/tachiyomi/extension/fr/enlignemanga/EnLigneManga.kt create mode 100644 src/fr/frmanga/build.gradle create mode 100644 src/fr/frmanga/src/eu/kanade/tachiyomi/extension/fr/frmanga/FRManga.kt create mode 100644 src/zh/manhuawu/build.gradle create mode 100644 src/zh/manhuawu/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/zh/manhuawu/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/zh/manhuawu/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/zh/manhuawu/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/zh/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/zh/manhuawu/src/eu/kanade/tachiyomi/extension/zh/manhuawu/Manhuawu.kt create mode 100644 src/zh/miaoqu/build.gradle create mode 100644 src/zh/miaoqu/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/zh/miaoqu/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/zh/miaoqu/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/zh/miaoqu/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/zh/miaoqu/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/zh/miaoqu/src/eu/kanade/tachiyomi/extension/zh/miaoqu/Miaoqu.kt delete mode 100644 src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/Data.kt delete mode 100644 src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SimpleParsedHttpSource.kt diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/Intl.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/Intl.kt new file mode 100644 index 000000000..d5d3e6598 --- /dev/null +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/Intl.kt @@ -0,0 +1,77 @@ +package eu.kanade.tachiyomi.multisrc.mccms + +object Intl { + var lang = "zh" + + val sort + get() = when (lang) { + "zh" -> "排序" + else -> "Sort by" + } + + val popular + get() = when (lang) { + "zh" -> "热门人气" + else -> "Popular" + } + + val latest + get() = when (lang) { + "zh" -> "更新时间" + else -> "Latest" + } + + val score + get() = when (lang) { + "zh" -> "评分" + else -> "Score" + } + + val status + get() = when (lang) { + "zh" -> "进度" + else -> "Status" + } + + val all + get() = when (lang) { + "zh" -> "全部" + else -> "All" + } + + val ongoing + get() = when (lang) { + "zh" -> "连载" + else -> "Ongoing" + } + + val completed + get() = when (lang) { + "zh" -> "完结" + else -> "Completed" + } + + val genreWeb + get() = when (lang) { + "zh" -> "标签" + else -> "Genre" + } + + val genreApi + get() = when (lang) { + "zh" -> "标签(搜索文本时无效)" + else -> "Genre (ignored for text search)" + } + + val categoryWeb + get() = when (lang) { + "zh" -> "分类筛选(搜索时无效)" + else -> "Category filters (ignored for text search)" + } + + val tapReset + get() = when (lang) { + "zh" -> "点击“重置”尝试刷新标签分类" + else -> "Tap 'Reset' to load genres" + } +} diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt index e368ecfd7..01724d1c1 100644 --- a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt @@ -9,15 +9,13 @@ 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.HttpSource -import kotlinx.serialization.json.Json -import kotlinx.serialization.json.decodeFromStream import okhttp3.Headers import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Request import okhttp3.Response import rx.Observable -import uy.kohesive.injekt.injectLazy import java.net.URLEncoder +import keiyoushi.utils.parseAs as parseAsRaw /** * 漫城CMS http://mccms.cn/ @@ -25,16 +23,26 @@ import java.net.URLEncoder open class MCCMS( override val name: String, override val baseUrl: String, - override val lang: String = "zh", + final override val lang: String = "zh", private val config: MCCMSConfig = MCCMSConfig(), ) : HttpSource() { - override val supportsLatest = true + override val supportsLatest get() = true - private val json: Json by injectLazy() + init { + Intl.lang = lang + } override val client by lazy { network.cloudflareClient.newBuilder() .rateLimitHost(baseUrl.toHttpUrl(), 2) + .addInterceptor { chain -> // for thumbnail requests + var request = chain.request() + val referer = request.header("Referer") + if (referer != null && !request.url.toString().startsWith(referer)) { + request = request.newBuilder().removeHeader("Referer").build() + } + chain.proceed(request) + } .build() } @@ -42,12 +50,14 @@ open class MCCMS( .add("User-Agent", System.getProperty("http.agent")!!) .add("Referer", baseUrl) + protected open fun SManga.cleanup(): SManga = this + override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/api/data/comic?page=$page&size=$PAGE_SIZE&order=hits", headers) override fun popularMangaParse(response: Response): MangasPage { val list: List = response.parseAs() - return MangasPage(list.map { it.toSManga() }, list.size >= PAGE_SIZE) + return MangasPage(list.map { it.toSManga().cleanup() }, list.size >= PAGE_SIZE) } override fun latestUpdatesRequest(page: Int): Request = @@ -86,7 +96,7 @@ open class MCCMS( return client.newCall(GET(url, headers)) .asObservableSuccess().map { response -> val list = response.parseAs>() - list.first { it.cleanUrl == mangaUrl }.toSManga() + list.first { it.cleanUrl == mangaUrl }.toSManga().cleanup() } } @@ -120,9 +130,7 @@ open class MCCMS( // Don't send referer override fun imageRequest(page: Page) = GET(page.imageUrl!!, pcHeaders) - private inline fun Response.parseAs(): T = use { - json.decodeFromStream>(it.body.byteStream()).data - } + private inline fun Response.parseAs(): T = parseAsRaw>().data override fun getFilterList(): FilterList { val genreData = config.genreData.also { it.fetchGenres(this) } diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSConfig.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSConfig.kt index e0036b985..68e005ba9 100644 --- a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSConfig.kt +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSConfig.kt @@ -12,6 +12,8 @@ val pcHeaders = Headers.headersOf("User-Agent", "Mozilla/5.0 (Windows NT 10.0; W fun String.removePathPrefix() = removePrefix("/index.php") +fun String.mobileUrl() = replace("//www.", "//m.") + open class MCCMSConfig( hasCategoryPage: Boolean = true, val textSearchOnlyPageOne: Boolean = false, diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt index 8d873ba10..934025dd8 100644 --- a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt @@ -26,11 +26,11 @@ data class MangaDto( title = Entities.unescape(name) author = Entities.unescape(this@MangaDto.author) description = Entities.unescape(content) - genre = tags.joinToString() - status = when { - '连' in serialize || isUpdating(addtime) -> SManga.ONGOING - '完' in serialize -> SManga.COMPLETED - else -> SManga.UNKNOWN + genre = Entities.unescape(tags.joinToString()) + status = when (serialize) { + "连载", "連載中", "En cours", "OnGoing" -> SManga.ONGOING + "完结", "已完結", "Terminé", "Complete", "Complété" -> SManga.COMPLETED + else -> if (isUpdating(addtime)) SManga.ONGOING else SManga.UNKNOWN } thumbnail_url = "$pic#$id" initialized = true diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSFilters.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSFilters.kt index eb20c1faf..3c0a34bc2 100644 --- a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSFilters.kt +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSFilters.kt @@ -18,32 +18,31 @@ open class MCCMSFilter( val query get() = queries[state] } -class SortFilter : MCCMSFilter("排序", SORT_NAMES, SORT_QUERIES) -class WebSortFilter : MCCMSFilter("排序", SORT_NAMES, SORT_QUERIES_WEB) +class SortFilter : MCCMSFilter(Intl.sort, SORT_NAMES, SORT_QUERIES) +class WebSortFilter : MCCMSFilter(Intl.sort, SORT_NAMES, SORT_QUERIES_WEB) -private val SORT_NAMES = arrayOf("热门人气", "更新时间", "评分") -private val SORT_QUERIES = arrayOf("order=hits", "order=addtime", "order=score") -private val SORT_QUERIES_WEB = arrayOf("order/hits", "order/addtime", "order/score") +private val SORT_NAMES get() = arrayOf(Intl.popular, Intl.latest, Intl.score) +private val SORT_QUERIES get() = arrayOf("order=hits", "order=addtime", "order=score") +private val SORT_QUERIES_WEB get() = arrayOf("order/hits", "order/addtime", "order/score") -class StatusFilter : MCCMSFilter("进度", STATUS_NAMES, STATUS_QUERIES) -class WebStatusFilter : MCCMSFilter("进度", STATUS_NAMES, STATUS_QUERIES_WEB) +class StatusFilter : MCCMSFilter(Intl.status, STATUS_NAMES, STATUS_QUERIES) +class WebStatusFilter : MCCMSFilter(Intl.status, STATUS_NAMES, STATUS_QUERIES_WEB) -private val STATUS_NAMES = arrayOf("全部", "连载", "完结") -private val STATUS_QUERIES = arrayOf("", "serialize=连载", "serialize=完结") -private val STATUS_QUERIES_WEB = arrayOf("", "finish/1", "finish/2") +private val STATUS_NAMES get() = arrayOf(Intl.all, Intl.ongoing, Intl.completed) +private val STATUS_QUERIES get() = arrayOf("", "serialize=连载", "serialize=完结") +private val STATUS_QUERIES_WEB get() = arrayOf("", "finish/1", "finish/2") class GenreFilter(private val values: Array, private val queries: Array) { - private val apiQueries get() = queries.run { - Array(size) { i -> "type[tags]=" + this[i] } + Array(size) { i -> "type[tags]=" + this[i] }.apply { this[0] = "" } } private val webQueries get() = queries.run { - Array(size) { i -> "tags/" + this[i] } + Array(size) { i -> "tags/" + this[i] }.apply { this[0] = "" } } - val filter get() = MCCMSFilter("标签(搜索文本时无效)", values, apiQueries, isTypeQuery = true) - val webFilter get() = MCCMSFilter("标签", values, webQueries, isTypeQuery = true) + val filter get() = MCCMSFilter(Intl.genreApi, values, apiQueries, isTypeQuery = true) + val webFilter get() = MCCMSFilter(Intl.genreWeb, values, webQueries, isTypeQuery = true) } class GenreData(hasCategoryPage: Boolean) { @@ -55,7 +54,12 @@ class GenreData(hasCategoryPage: Boolean) { status = FETCHING thread { try { - val response = source.client.newCall(GET("${source.baseUrl}/category/", pcHeaders)).execute() + val request = when (source) { + // Web sources parse listings whenever possible. They call this function for mobile pages. + is MCCMSWeb -> GET("${source.baseUrl.mobileUrl()}/category/", source.headers) + else -> GET("${source.baseUrl}/category/", pcHeaders) + } + val response = source.client.newCall(request).execute() parseGenres(response.asJsoup(), this) } catch (e: Exception) { status = NOT_FETCHED @@ -74,7 +78,7 @@ class GenreData(hasCategoryPage: Boolean) { internal fun parseGenres(document: Document, genreData: GenreData) { if (genreData.status == GenreData.FETCHED || genreData.status == GenreData.NO_DATA) return - val box = document.selectFirst(".cate-selector, .cy_list_l") + val box = document.selectFirst(".cate-selector, .cy_list_l, .ticai, .stui-screen__list") if (box == null || "/tags/" in document.location()) { genreData.status = GenreData.NOT_FETCHED return @@ -85,7 +89,7 @@ internal fun parseGenres(document: Document, genreData: GenreData) { return } val result = buildList(genres.size + 1) { - add(Pair("全部", "")) + add(Pair(Intl.all, "")) genres.mapTo(this) { val tagId = it.attr("href").substringAfterLast('/') Pair(it.text(), tagId) @@ -100,14 +104,14 @@ internal fun parseGenres(document: Document, genreData: GenreData) { internal fun getFilters(genreData: GenreData): FilterList { val list = buildList(4) { - add(StatusFilter()) + if (Intl.lang == "zh") add(StatusFilter()) add(SortFilter()) if (genreData.status == GenreData.NO_DATA) return@buildList add(Filter.Separator()) if (genreData.status == GenreData.FETCHED) { add(genreData.genreFilter.filter) } else { - add(Filter.Header("点击“重置”尝试刷新标签分类")) + add(Filter.Header(Intl.tapReset)) } } return FilterList(list) @@ -115,13 +119,13 @@ internal fun getFilters(genreData: GenreData): FilterList { internal fun getWebFilters(genreData: GenreData): FilterList { val list = buildList(4) { - add(Filter.Header("分类筛选(搜索时无效)")) + add(Filter.Header(Intl.categoryWeb)) add(WebStatusFilter()) add(WebSortFilter()) when (genreData.status) { GenreData.NO_DATA -> return@buildList GenreData.FETCHED -> add(genreData.genreFilter.webFilter) - else -> add(Filter.Header("点击“重置”尝试刷新标签分类")) + else -> add(Filter.Header(Intl.tapReset)) } } return FilterList(list) diff --git a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt index 481d72208..19744c607 100644 --- a/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt +++ b/lib-multisrc/mccms/src/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt @@ -13,39 +13,45 @@ import okhttp3.Headers import okhttp3.HttpUrl.Companion.toHttpUrl import okhttp3.Request import okhttp3.Response +import okio.IOException import org.jsoup.nodes.Document +import org.jsoup.nodes.Element import org.jsoup.select.Evaluator import rx.Observable open class MCCMSWeb( override val name: String, override val baseUrl: String, - override val lang: String = "zh", - private val config: MCCMSConfig = MCCMSConfig(), + final override val lang: String = "zh", + protected val config: MCCMSConfig = MCCMSConfig(), ) : HttpSource() { override val supportsLatest get() = true + init { + Intl.lang = lang + } + override val client by lazy { network.cloudflareClient.newBuilder() .rateLimitHost(baseUrl.toHttpUrl(), 2) + .addInterceptor { chain -> + val response = chain.proceed(chain.request()) + if (response.request.url.encodedPath == "/err/comic") { + throw IOException(response.body.string().substringBefore('\n')) + } + response + } .build() } override fun headersBuilder() = Headers.Builder() .add("User-Agent", System.getProperty("http.agent")!!) - private fun parseListing(document: Document): MangasPage { + open fun parseListing(document: Document): MangasPage { parseGenres(document, config.genreData) - val mangas = document.select(Evaluator.Class("common-comic-item")).map { - SManga.create().apply { - val titleElement = it.selectFirst(Evaluator.Class("comic__title"))!!.child(0) - url = titleElement.attr("href").removePathPrefix() - title = titleElement.ownText() - thumbnail_url = it.selectFirst(Evaluator.Tag("img"))!!.attr("data-original") - } - } + val mangas = document.select(simpleMangaSelector()).map(::simpleMangaFromElement) val hasNextPage = run { // default pagination - val buttons = document.selectFirst(Evaluator.Id("Pagination"))!!.select(Evaluator.Tag("a")) + val buttons = document.selectFirst("#Pagination, .NewPages")!!.select(Evaluator.Tag("a")) val count = buttons.size // Next page != Last page buttons[count - 1].attr("href") != buttons[count - 2].attr("href") @@ -53,6 +59,15 @@ open class MCCMSWeb( return MangasPage(mangas, hasNextPage) } + open fun simpleMangaSelector() = ".common-comic-item" + + open fun simpleMangaFromElement(element: Element) = SManga.create().apply { + val titleElement = element.selectFirst(Evaluator.Class("comic__title"))!!.child(0) + url = titleElement.attr("href").removePathPrefix() + title = titleElement.ownText() + thumbnail_url = element.selectFirst(Evaluator.Tag("img"))!!.attr("data-original") + } + override fun popularMangaRequest(page: Int) = GET("$baseUrl/category/order/hits/page/$page", pcHeaders) override fun popularMangaParse(response: Response) = parseListing(response.asJsoup()) @@ -104,6 +119,8 @@ open class MCCMSWeb( return super.fetchMangaDetails(manga) } + override fun getMangaUrl(manga: SManga) = baseUrl.mobileUrl() + manga.url + override fun mangaDetailsRequest(manga: SManga) = GET(baseUrl + manga.url, pcHeaders) override fun mangaDetailsParse(response: Response): SManga { @@ -127,17 +144,23 @@ open class MCCMSWeb( override fun chapterListRequest(manga: SManga) = GET(baseUrl + manga.url, pcHeaders) override fun chapterListParse(response: Response): List { - return run { - response.asJsoup().selectFirst(Evaluator.Class("chapter__list-box"))!!.children().map { + return getDescendingChapters( + response.asJsoup().select(chapterListSelector()).map { val link = it.child(0) SChapter.create().apply { url = link.attr("href").removePathPrefix() - name = link.ownText() + name = link.text() } - }.asReversed() - } + }, + ) } + open fun chapterListSelector() = ".chapter__list-box > li" + + open fun getDescendingChapters(chapters: List) = chapters.asReversed() + + override fun getChapterUrl(chapter: SChapter) = baseUrl.mobileUrl() + chapter.url + override fun pageListRequest(chapter: SChapter): Request = GET(baseUrl + chapter.url, if (config.useMobilePageList) headers else pcHeaders) diff --git a/src/fr/enlignemanga/build.gradle b/src/fr/enlignemanga/build.gradle new file mode 100644 index 000000000..5809da2d0 --- /dev/null +++ b/src/fr/enlignemanga/build.gradle @@ -0,0 +1,9 @@ +ext { + extName = 'En Ligne Manga' + extClass = '.EnLigneManga' + themePkg = 'mccms' + baseUrl = 'https://www.enlignemanga.com' + overrideVersionCode = 0 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/fr/enlignemanga/src/eu/kanade/tachiyomi/extension/fr/enlignemanga/EnLigneManga.kt b/src/fr/enlignemanga/src/eu/kanade/tachiyomi/extension/fr/enlignemanga/EnLigneManga.kt new file mode 100644 index 000000000..5583d95d5 --- /dev/null +++ b/src/fr/enlignemanga/src/eu/kanade/tachiyomi/extension/fr/enlignemanga/EnLigneManga.kt @@ -0,0 +1,16 @@ +package eu.kanade.tachiyomi.extension.fr.enlignemanga + +import eu.kanade.tachiyomi.multisrc.mccms.MCCMS +import eu.kanade.tachiyomi.multisrc.mccms.MCCMSConfig +import eu.kanade.tachiyomi.source.model.SManga + +class EnLigneManga : MCCMS( + "En Ligne Manga", + "https://www.enlignemanga.com", + "fr", + MCCMSConfig(lazyLoadImageAttr = "src"), +) { + override fun SManga.cleanup() = apply { + title = title.substringBeforeLast(" ligne") + } +} diff --git a/src/fr/frmanga/build.gradle b/src/fr/frmanga/build.gradle new file mode 100644 index 000000000..c38267edc --- /dev/null +++ b/src/fr/frmanga/build.gradle @@ -0,0 +1,9 @@ +ext { + extName = 'FR Manga' + extClass = '.FRManga' + themePkg = 'mccms' + baseUrl = 'https://www.frmanga.com' + overrideVersionCode = 0 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/fr/frmanga/src/eu/kanade/tachiyomi/extension/fr/frmanga/FRManga.kt b/src/fr/frmanga/src/eu/kanade/tachiyomi/extension/fr/frmanga/FRManga.kt new file mode 100644 index 000000000..397f4bf6a --- /dev/null +++ b/src/fr/frmanga/src/eu/kanade/tachiyomi/extension/fr/frmanga/FRManga.kt @@ -0,0 +1,11 @@ +package eu.kanade.tachiyomi.extension.fr.frmanga + +import eu.kanade.tachiyomi.multisrc.mccms.MCCMS +import eu.kanade.tachiyomi.multisrc.mccms.MCCMSConfig + +class FRManga : MCCMS( + "FR Manga", + "https://www.frmanga.com", + "fr", + MCCMSConfig(lazyLoadImageAttr = "src"), +) diff --git a/src/zh/manhuawu/build.gradle b/src/zh/manhuawu/build.gradle new file mode 100644 index 000000000..fc5784415 --- /dev/null +++ b/src/zh/manhuawu/build.gradle @@ -0,0 +1,9 @@ +ext { + extName = 'Manhuawu' + extClass = '.Manhuawu' + themePkg = 'mccms' + baseUrl = 'https://www.mhua5.com' + overrideVersionCode = 0 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/zh/manhuawu/res/mipmap-hdpi/ic_launcher.png b/src/zh/manhuawu/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7f9656e60925d5fb55255ff83be3b470c8787ced GIT binary patch literal 2637 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 literal 0 HcmV?d00001 diff --git a/src/zh/manhuawu/res/mipmap-mdpi/ic_launcher.png b/src/zh/manhuawu/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..2937585cb8fcdfca597833e14bc57210fbd26e25 GIT binary patch literal 1511 zcmVi)QPhZ-`g{uK0#&&yY7Z z8)UI9yjG8x3k=gu!)32izTsNSFxL`hJN>F}2n4=2;qt44^Sm+pTT%qc+LfdO2XFmD zz6SpJrq54bY62jTcF7zk1mQKNuODAIE0SK7?GhXKJ)kz4sf{B^cNBc_0|nMZ4DimP zwQ?BUc7Lb4E9Z@b0Qnh^jEuX7Z2tC%Dktt64{Fo{V+%NJ;(mhUr?}jC59@b5zE^^ zn)$c}ELN!6iof1d<;bv|IwXxy)%^&ECmy3*yo1#k@ko(;4P=efLt!=*rX4F-XVCyoa z!oEy&0?uCgK1<%I%uP+c53=o!<`!2|3x!6f3^3mkKJ&~H_upFJ%e#x*R?(bUj1r+O zY-bsLuof` z8wF<+<&1%IOOnvf@#zm;i67FrLb46d=JAGV?Rca)W55M&+CLKoAmMUL-ho8UNH95SgA^4juaf zx?Ie60x^XN^xpqMaX)KPe-dTw01ehi6=i7{DB$ed6<6`DJ=Fg49OAWEaS`RYjfU5V zv4+tT|Idi;H!D|v8DEQ1hzMEiv0=)ezmpz}-?p>(CudHEm37LHebN*xCodyJS1uRYQ>Q&6LM;}UI zj}K)Y^LZ@da27;R+rN&82T`{ciT`Eq1*Gu|)Sm`Z?_cOzL1<_^`V!Tz9VUw&Dzkzy zc^F7{Ai44rxbkCqk+qL?85A+WnYZwERv9>Y0MzOsC=g;KGi;=~cmX7sMvL?yF9Rk>FW-m}s{*K=Q?1DMZD+1f0=lF5cNk%1auWtf4rpLqWQ>+G#@_;Lau8dMORRjdx36|=rY8+ zkN*mIlh8Vkv@SsNBysGlLC}g+e8y)s^Epgl{S;b5sPZSFQ>ihaJp=Yg=Mz!+>fM-S zA5-@`y%nzkX$F{XZ?uqB2!I%QuWHySn}7*I31^q3V@TEl*a_$y4CKZ71~l(;H2p{r z1P!(ri6(hB2EwVSssFLXNHm366Im4C9yoB|_S2_N|9fF!p;4>VWHYO)p{u2<32@(S ztjfSRa1c1OiFIe9VH_xLWX&qT0S1yERyL{1i3SHyuyNFusGDqI-UcjT{vo?`@HPMd N002ovPDHLkV1i0M$-w{s literal 0 HcmV?d00001 diff --git a/src/zh/manhuawu/res/mipmap-xhdpi/ic_launcher.png b/src/zh/manhuawu/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b4d91407ec2653c6e2ebef621ed3fd066dddb0df GIT binary patch literal 3326 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 IM6N<$f>(4bFaQ7m literal 0 HcmV?d00001 diff --git a/src/zh/manhuawu/res/mipmap-xxhdpi/ic_launcher.png b/src/zh/manhuawu/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..0dcdb829869b97682f36d2f5c018221d9c580231 GIT binary patch literal 6181 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 DDxt$5 literal 0 HcmV?d00001 diff --git a/src/zh/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png b/src/zh/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..7f3305374f0a8b7f080c013f0ea0d225141d9ea5 GIT binary patch literal 8030 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 literal 0 HcmV?d00001 diff --git a/src/zh/miaoqu/res/mipmap-xhdpi/ic_launcher.png b/src/zh/miaoqu/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..882f424a118f5d261e198dc51694c41e00a4a03b GIT binary patch literal 3194 zcmV-=42AQFP)Y zuz46TnBej>@0T$)FB@Wmo#2W@(ypYHcC~vt=W6ea_Rc<~yV9!GojK!&cD1YT`|dgC zo_kl9kVb2?Mr*W2YqUmdv_@;RMr$;`jgY2>S*%*1lNp4NnS_wpgpfIeknc=$n`2@z z)5NAJOz>yz*snM~$AUDpQ%4BTR%#V-eUax*O--#s%tZ8pCbK(zKaOh^ zR*0F2T~npLA0z#bG1vsT@mlwWTHX(0g_sdSUa7Pf%rv{w&+r5IbvxBie^@?TR4hTv z2qAMt5b!-h$ZOSBUl;+tnu!1*9nIZ^SQ0`5N=nY}_o-p1EF$$3f2|Lm5ldDh7l*PB08mu603b*D7X^ zYG26=QhR;}>XRF`r>bAxhSc6QkleX~v*nOJ{SVNysi^k=Cv|&O3q{2O1M;KS8Ss!S z1>Q6SG_`v*Xj4xt?@@U93{nVoj0b-?GmyGJq&-BGE30)32qia9_kQY10JGe{Nz1v) z?Vch5JDmt9nmTb`lsl@H3-VGvfT2i`A3h7&>jxooW(UZ}wt#&21CS2>8Kkatkm_0o zQm1KM>p<@LEA{Vo?0-rZX?R%FVucxLU|KI|ocC~n^ zACj?UAa(u;w8;mcOL5Q@nO?hIVgOGH=;;Il8IlMt2YiwP9u5Deef^ld1*qeL6qMrY z_O7Q?`Ii4N<9$C>{|a9HlmKRlHvGAq_Q?E`n`LD~)s6xDP0(z_P5E{NNJlLq*XN{sd-b=k0_A2mJ00ZXfAIp})+$whqOF<# z8?x69mQxL_Z7oO{==J6EOD+HCGW!%Xr{@Xq0$+ss?Ff)hd>oZpkm0vdNk^$(E{7?f z{jNT}S&Sdqlo$BC>*19zO8t4uGIAiQ9pu@ zCLiAt?HFL!D;NQOl+P^p-~u}xQXOmDN4x>Sx6Awes2?qJp*^YtF{fq{;79qahwNGf z*{hxGbjX}*_2qi}`Tg>IKO-PNdM)U{EGz>2%~qk=5nxgM?iNs=-2)?+0jYZv1sn5j z&~-MB0O{}tLUR5})Gr_33Wk=CstfYl19+FS8l!A=Iw|=l(rg*-S`c2E-J8c0Ef%T()b>e}j8MAOo5q`%3PBDP>2n1R_ zvXPwvGFB^j_tL(S2EWpV#kHhe(B=F-4gyQ>GkfI#uY6nIuZ|6fnlg=M4`AR^0=hS` zLum<`2R}D-#ySldAA@wyHdo~{lMb$@0lx6G%ZRs?wMEv-CKW@jq(#iXMtNJMc$37}| zJyTdQ!0)0fGX^-7j?ve%Ne;s(u6AGqTh71?B#v*cmRB->ZmDxVokmFsgHz!6|uM&|1}r37esTh*5;KX?DUb>-aSD^C8Nx%) z-<{MC$+o2y0)mz(YP~Lq5#S2EU4E~a6X28p51+4&-?dy5m$Wz$klOzT{ub#(i=Fxt ztxI_VqEQP9;)dK}fYZPVEqnD~u~%^f*wyv12bA6yt{rvq`N@to{B6<_w-fk`fO1!Q z*E$A3?rv`&;F+(_UOQyY1?0R&xF8+fOlv*b*CUXBe3=5~Hqy=AJq6lVkBTwiVSn*` zdDqkCML@m8fWa^P0&mH3ve&Hy*ru62^L(dV-_7lmnp6)#*r{PPGYIg^veyr@*{}+0 zJN^b+cFHg90rf@z>k*J28wdn^DFKGLAlEPWPI~@;v}(UA|oKy=pvOu7?pIAKg+P;{c~t_~toC``5ZEo=-2cH+TY^{Jp;suAAF& z1D_EPwIB>ZN)l|DA*PGz)7wEhw1KWV;4O9FJ!<$mdpLs;kn{pSW|ksi%YD^%+43VQlmI&q`R-$1%=yQ}h12)gu=9;-gNStOWO zKC@QLg0|Fa7F6jIl0avpyfU2J@EPkf2@}Ik;L}H<_-oTgmmJie`1jkES-VI+q7<}3 z>h*Mu*Jrw zaq{^f9p1=a0y6!3c<@cDR{})FfUN8_xS}&wVCd`=NT2zaZKgxBomewns>m8vMy1a8 zZI#aq*M-�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 C^pM&B literal 0 HcmV?d00001 diff --git a/src/zh/miaoqu/src/eu/kanade/tachiyomi/extension/zh/miaoqu/Miaoqu.kt b/src/zh/miaoqu/src/eu/kanade/tachiyomi/extension/zh/miaoqu/Miaoqu.kt new file mode 100644 index 000000000..990cfd56b --- /dev/null +++ b/src/zh/miaoqu/src/eu/kanade/tachiyomi/extension/zh/miaoqu/Miaoqu.kt @@ -0,0 +1,120 @@ +package eu.kanade.tachiyomi.extension.zh.miaoqu + +import android.util.Base64 +import eu.kanade.tachiyomi.multisrc.mccms.MCCMSWeb +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservable +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 +import eu.kanade.tachiyomi.util.asJsoup +import keiyoushi.utils.parseAs +import kotlinx.serialization.Serializable +import okhttp3.Response +import org.jsoup.nodes.Document +import rx.Observable +import kotlin.experimental.xor + +// This site shares the same database with 6Manhua (SixMH), but uses manga slug as URL. +class Miaoqu : MCCMSWeb("喵趣漫画", "https://www.miaoqumh.org") { + override fun parseListing(document: Document): MangasPage { + // There's no genre list to parse, so we fetch genres from mobile page in getFilterList() + val entries = document.selectFirst("#mangawrap")!!.children().map { element -> + SManga.create().apply { + val img = element.child(0) + thumbnail_url = img.attr("style").substringBetween("background: url(", ')') + url = img.attr("href") + title = element.selectFirst(".manga-name")!!.text() + author = element.selectFirst(".manga-author")?.text() + } + } + val hasNextPage = run { + val button = document.selectFirst("#next") ?: return@run false + button.attr("href").substringAfterLast('/') != document.location().substringAfterLast('/') + } + return MangasPage(entries, hasNextPage) + } + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + return client.newCall(searchMangaRequest(page, query, filters)).asObservable().map { response -> + if (response.code == 404) { + response.close() + throw Exception("服务器错误,无法搜索") + } + searchMangaParse(response) + } + } + + // Use mobile page + override fun mangaDetailsRequest(manga: SManga) = GET(getMangaUrl(manga), headers) + + override fun mangaDetailsParse(response: Response) = SManga.create().apply { + val document = response.asJsoup() + description = document.selectFirst(".text")!!.text() + + val infobox = document.selectFirst(".infobox")!! + title = infobox.selectFirst(".title")!!.text() + thumbnail_url = infobox.selectFirst("img")!!.attr("src") + + for (element in infobox.select(".tage")) { + val text = element.text() + when (text.substring(0, 3)) { + "作者:" -> author = text.substring(3).trimStart() + "类型:" -> genre = element.select("a").joinToString { it.text() } + "更新于" -> description = "$text\n\n$description" + } + } + } + + override fun chapterListRequest(manga: SManga) = GET(getMangaUrl(manga), headers) + + override fun chapterListSelector() = "ul.list > li" + + // Might return HTTP 500 with page data + override fun fetchPageList(chapter: SChapter): Observable> = + client.newCall(pageListRequest(chapter)).asObservable().map(::pageListParse) + + override fun pageListParse(response: Response): List { + val cid = response.request.url.pathSegments.last().removeSuffix(".html").toInt() + val key = when (cid % 10) { + 0 -> "8-bXd9iN" + 1 -> "8-RXyjry" + 2 -> "8-oYvwVy" + 3 -> "8-4ZY57U" + 4 -> "8-mbJpU7" + 5 -> "8-6MM2Ei" + 6 -> "8-54TiQr" + 7 -> "8-Ph5xx9" + 8 -> "8-bYgePR" + 9 -> "8-Z9A3bW" + else -> throw Exception("Illegal cid: $cid") + }.encodeToByteArray() + check(key.size == 8) + val data = response.body.string().substringBetween("var DATA='", '\'') + val bytes = Base64.decode(data, Base64.DEFAULT) + for (i in bytes.indices) { + bytes[i] = bytes[i] xor key[i and 7] + } + val decrypted = String(Base64.decode(bytes, Base64.DEFAULT)) + return decrypted.parseAs>().mapIndexed { i, image -> Page(i, imageUrl = image.url) } + } + + @Serializable + private class Image(val url: String) + + override fun getFilterList(): FilterList { + config.genreData.fetchGenres(this) + return super.getFilterList() + } +} + +private fun String.substringBetween(left: String, right: Char): String { + val index = indexOf(left) + check(index != -1) { "string doesn't match $left[...]$right" } + val startIndex = index + left.length + val endIndex = indexOf(right, startIndex) + check(endIndex != -1) { "string doesn't match $left[...]$right" } + return substring(startIndex, endIndex) +} diff --git a/src/zh/sixmh/build.gradle b/src/zh/sixmh/build.gradle index 5c517bb89..2dfea4adf 100644 --- a/src/zh/sixmh/build.gradle +++ b/src/zh/sixmh/build.gradle @@ -1,7 +1,9 @@ ext { extName = '6Manhua' extClass = '.SixMH' - extVersionCode = 13 + themePkg = 'mccms' + baseUrl = 'https://www.liumanhua.com' + overrideVersionCode = 7 isNsfw = true } diff --git a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/Data.kt b/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/Data.kt deleted file mode 100644 index 60091e4ae..000000000 --- a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/Data.kt +++ /dev/null @@ -1,8 +0,0 @@ -package eu.kanade.tachiyomi.extension.zh.sixmh - -import kotlinx.serialization.Serializable - -@Serializable -data class Data( - val images: List, -) diff --git a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SimpleParsedHttpSource.kt b/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SimpleParsedHttpSource.kt deleted file mode 100644 index 2e93443ab..000000000 --- a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SimpleParsedHttpSource.kt +++ /dev/null @@ -1,27 +0,0 @@ -package eu.kanade.tachiyomi.extension.zh.sixmh - -import eu.kanade.tachiyomi.source.model.SManga -import eu.kanade.tachiyomi.source.online.ParsedHttpSource -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element - -abstract class SimpleParsedHttpSource : ParsedHttpSource() { - - abstract fun simpleMangaSelector(): String - abstract fun simpleMangaFromElement(element: Element): SManga - abstract fun simpleNextPageSelector(): String? - - override fun popularMangaSelector() = simpleMangaSelector() - override fun popularMangaFromElement(element: Element) = simpleMangaFromElement(element) - override fun popularMangaNextPageSelector() = simpleNextPageSelector() - - override fun latestUpdatesSelector() = simpleMangaSelector() - override fun latestUpdatesFromElement(element: Element) = simpleMangaFromElement(element) - override fun latestUpdatesNextPageSelector() = simpleNextPageSelector() - - override fun searchMangaSelector() = simpleMangaSelector() - override fun searchMangaFromElement(element: Element) = simpleMangaFromElement(element) - override fun searchMangaNextPageSelector() = simpleNextPageSelector() - - override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException() -} diff --git a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SixMH.kt b/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SixMH.kt index f3d524fcc..de005d3f7 100644 --- a/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SixMH.kt +++ b/src/zh/sixmh/src/eu/kanade/tachiyomi/extension/zh/sixmh/SixMH.kt @@ -1,35 +1,19 @@ package eu.kanade.tachiyomi.extension.zh.sixmh -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.FilterList +import eu.kanade.tachiyomi.multisrc.mccms.MCCMSWeb 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.util.asJsoup import keiyoushi.utils.parseAs -import okhttp3.HttpUrl.Companion.toHttpUrl -import okhttp3.Request +import kotlinx.serialization.Serializable import okhttp3.Response -import org.jsoup.nodes.Document import org.jsoup.nodes.Element -class SixMH : SimpleParsedHttpSource() { +class SixMH : MCCMSWeb("六漫画", "https://www.liumanhua.com") { private val paramsRegex = Regex("params = '([A-Za-z0-9+/=]+)'") override val versionId get() = 3 - override val name: String = "六漫画" - override val lang: String = "zh" - override val supportsLatest: Boolean = true - override val baseUrl: String = "https://www.liumanhua.com" - override fun popularMangaRequest(page: Int) = GET("$baseUrl/category/order/hits/page/$page", headers) - override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/category/order/addtime/page/$page", headers) - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - val url = "$baseUrl/index.php/search".toHttpUrl().newBuilder() - .addQueryParameter("key", query) - .build() - return GET(url, headers) - } - - override fun simpleNextPageSelector(): String? = null override fun simpleMangaSelector(): String = "div.cy_list_mh ul" override fun simpleMangaFromElement(element: Element): SManga = SManga.create().apply { title = element.selectFirst("li.title > a")!!.text() @@ -38,7 +22,9 @@ class SixMH : SimpleParsedHttpSource() { } // Details - override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply { + override fun mangaDetailsParse(response: Response): SManga = SManga.create().apply { + val document = response.asJsoup() + val element = document.selectFirst("div.cy_info")!! title = element.selectFirst("div.cy_title")!!.text() thumbnail_url = element.selectFirst("div.cy_info_cover > a > img.pic")?.absUrl("src") @@ -47,15 +33,12 @@ class SixMH : SimpleParsedHttpSource() { val infoElements = element.select("div.cy_xinxi") author = infoElements[0].selectFirst("span:first-child > a")?.text() status = parseStatus(infoElements[0].selectFirst("span:nth-child(2)")?.text()) - genre = infoElements[1].selectFirst("span:first-child > a")?.text() + genre = infoElements[1].select("span:first-child > a").joinToString { it.text() } } // Chapters override fun chapterListSelector(): String = "ul#mh-chapter-list-ol-0 li.chapter__item" - override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply { - setUrlWithoutDomain(element.selectFirst("a")!!.absUrl("href")) - name = element.selectFirst("a > p")!!.text() - } + override fun getDescendingChapters(chapters: List) = chapters // Pages override fun pageListParse(response: Response): List { @@ -67,7 +50,8 @@ class SixMH : SimpleParsedHttpSource() { return images.mapIndexed { index, url -> Page(index, imageUrl = url) } } - override fun pageListParse(document: Document): List = throw UnsupportedOperationException() + @Serializable + private class Data(val images: List) private fun parseStatus(status: String?): Int { return when {