diff --git a/multisrc/overrides/mccms/haoman6/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/mccms/haoman6/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index 244552949..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/mccms/haoman6/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index 177f76bc9..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/mccms/haoman6/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index abf8ee911..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/mccms/haoman6/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 8462b7bdb..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/mccms/haoman6/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 8ba646a3a..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/res/web_hi_res_512.png b/multisrc/overrides/mccms/haoman6/res/web_hi_res_512.png
deleted file mode 100644
index 7f1d38eb1..000000000
Binary files a/multisrc/overrides/mccms/haoman6/res/web_hi_res_512.png and /dev/null differ
diff --git a/multisrc/overrides/mccms/haoman6/src/Haoman6.kt b/multisrc/overrides/mccms/haoman6/src/Haoman6.kt
deleted file mode 100644
index 0f67d99ff..000000000
--- a/multisrc/overrides/mccms/haoman6/src/Haoman6.kt
+++ /dev/null
@@ -1,18 +0,0 @@
-package eu.kanade.tachiyomi.extension.zh.haoman6
-
-import eu.kanade.tachiyomi.multisrc.mccms.MCCMSWeb
-import eu.kanade.tachiyomi.network.GET
-import eu.kanade.tachiyomi.source.model.SChapter
-import eu.kanade.tachiyomi.source.model.SManga
-
-class Haoman6 : MCCMSWeb("好漫6", "https://www.haoman6.com") {
-    override fun SManga.cleanup() = apply {
-        description = description?.substringBefore(title)
-        title = title.removeSuffix("(最新在线)").removeSuffix("-")
-    }
-
-    override fun pageListRequest(chapter: SChapter) =
-        GET(baseUrl + chapter.url, headers)
-
-    override val lazyLoadImageAttr = "mob-ec"
-}
diff --git a/multisrc/overrides/mccms/haoman8/src/Haoman8.kt b/multisrc/overrides/mccms/haoman8/src/Haoman8.kt
index 35fe914e7..f3e4d26a5 100644
--- a/multisrc/overrides/mccms/haoman8/src/Haoman8.kt
+++ b/multisrc/overrides/mccms/haoman8/src/Haoman8.kt
@@ -1,7 +1,3 @@
 package eu.kanade.tachiyomi.extension.zh.haoman8
 
-import eu.kanade.tachiyomi.multisrc.mccms.MCCMS
-
-class Haoman8 : MCCMS("好漫8", "https://caiji.haoman8.com", hasCategoryPage = true) {
-    override val lazyLoadImageAttr = "data-original"
-}
+class Haoman8 : MCCMSAcgn("好漫8", "https://www.haoman8.com", hasCategoryPage = false)
diff --git a/multisrc/overrides/mccms/haoman8/src/MCCMSAcgn.kt b/multisrc/overrides/mccms/haoman8/src/MCCMSAcgn.kt
new file mode 100644
index 000000000..3da0c9e93
--- /dev/null
+++ b/multisrc/overrides/mccms/haoman8/src/MCCMSAcgn.kt
@@ -0,0 +1,117 @@
+package eu.kanade.tachiyomi.extension.zh.haoman8
+
+import eu.kanade.tachiyomi.multisrc.mccms.MCCMSWeb
+import eu.kanade.tachiyomi.source.model.FilterList
+import eu.kanade.tachiyomi.source.model.MangasPage
+import eu.kanade.tachiyomi.source.model.SChapter
+import eu.kanade.tachiyomi.source.model.SManga
+import eu.kanade.tachiyomi.util.asJsoup
+import kotlinx.serialization.Serializable
+import kotlinx.serialization.decodeFromString
+import kotlinx.serialization.json.Json
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.nodes.Document
+import org.jsoup.select.Evaluator
+import uy.kohesive.injekt.injectLazy
+import java.text.SimpleDateFormat
+import java.util.Locale
+
+// TODO: Category page
+open class MCCMSAcgn(
+    name: String,
+    baseUrl: String,
+    lang: String = "zh",
+    hasCategoryPage: Boolean = true,
+) : MCCMSWeb(name, baseUrl, lang, hasCategoryPage) {
+
+    override fun parseListing(document: Document): MangasPage {
+        if (document.location().contains("search")) {
+            return searchMangaParse(document)
+        }
+        val list = document.selectFirst(Evaluator.Class("acgn-comic-list"))
+            ?: return MangasPage(emptyList(), false)
+        val mangas = list.children().map {
+            SManga.create().apply {
+                val titleElement = it.selectFirst(Evaluator.Tag("h3"))!!.child(0)
+                url = titleElement.attr("href")
+                title = titleElement.ownText()
+                thumbnail_url = it.selectFirst(Evaluator.Tag("img"))!!
+                    .attr("style").split("'")[1]
+            }.cleanup()
+        }
+        val hasNextPage = run { // default pagination
+            val pagination = document.selectFirst(Evaluator.Class("acgn-pages"))!!
+            pagination.children().last()!!.tagName() == "a"
+        }
+        return MangasPage(mangas, hasNextPage)
+    }
+
+    override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
+        val request = super.searchMangaRequest(page, query, filters)
+        return if (query.isNotBlank()) {
+            // TODO: Fix Captcha
+            throw Exception("暂不支持搜索,请等待后续插件更新")
+            // request.newBuilder().headers(headers).build()
+        } else {
+            request
+        }
+    }
+
+    private fun searchMangaParse(document: Document): MangasPage {
+        val entries = document.select(Evaluator.Class("comic-list-item")).map {
+            SManga.create().apply {
+                val titleElement = it.selectFirst(Evaluator.Class("comic-name"))!!.child(0)
+                url = titleElement.attr("href")
+                title = titleElement.ownText()
+                author = it.selectFirst(Evaluator.Class("comic-author"))?.ownText()
+                genre = it.selectFirst(Evaluator.Class("comic-tags"))?.run {
+                    children().joinToString { it.ownText() }
+                }
+                thumbnail_url = it.selectFirst(Evaluator.Tag("img"))!!.attr("src")
+            }.cleanup()
+        }
+        return MangasPage(entries, false)
+    }
+
+    override fun mangaDetailsParse(response: Response) = SManga.create().apply {
+        val document = response.asJsoup().selectFirst(Evaluator.Class("acgn-model-detail-frontcover"))!!
+        title = document.selectFirst(Evaluator.Tag("h1"))!!.ownText()
+        description = document.selectFirst(Evaluator.Class("desc-content"))?.ownText()
+        genre = document.select("ul.tags > a[href]").joinToString { it.ownText() }
+        thumbnail_url = document.selectFirst(Evaluator.Tag("img"))?.attr("src")
+    }
+
+    override fun chapterListParse(response: Response): List<SChapter> {
+        val document = response.asJsoup()
+        val scripts = document.select(Evaluator.Tag("script"))
+        val js = scripts[scripts.size - 2].data()
+        val start = js.indexOf('[')
+        val end = js.lastIndexOf(']') + 1
+        val replaced = js.substring(start, end).replace('\'', '"')
+        val list: List<AcgnChapter> = json.decodeFromString(replaced)
+        val dateFormat = dateFormat
+        return list.asReversed().map { it.toSChapter(dateFormat) }
+    }
+
+    override val lazyLoadImageAttr get() = "data-echo"
+
+    @Serializable
+    class AcgnChapter(
+        private val name: String,
+        private val url: String,
+        private val time: String,
+    ) {
+        fun toSChapter(dateFormat: SimpleDateFormat) = SChapter.create().apply {
+            url = this@AcgnChapter.url
+            name = this@AcgnChapter.name
+            date_upload = dateFormat.parse(time)?.time ?: 0
+        }
+    }
+
+    private val json: Json by injectLazy()
+
+    private val dateFormat by lazy {
+        SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH)
+    }
+}
diff --git a/multisrc/overrides/mccms/kuaikuai3/src/Kuaikuai3.kt b/multisrc/overrides/mccms/kuaikuai3/src/Kuaikuai3.kt
new file mode 100644
index 000000000..d5992be4d
--- /dev/null
+++ b/multisrc/overrides/mccms/kuaikuai3/src/Kuaikuai3.kt
@@ -0,0 +1,7 @@
+package eu.kanade.tachiyomi.extension.zh.kuaikuai3
+
+class Kuaikuai3 : MCCMSReduced("快快漫画3", "https://mobile3.manhuaorg.com") {
+
+    override fun headersBuilder() = super.headersBuilder()
+        .set("User-Agent", "okhttp/3.14.7")
+}
diff --git a/multisrc/overrides/mccms/kuaikuai3/src/MCCMSReduced.kt b/multisrc/overrides/mccms/kuaikuai3/src/MCCMSReduced.kt
new file mode 100644
index 000000000..278022b98
--- /dev/null
+++ b/multisrc/overrides/mccms/kuaikuai3/src/MCCMSReduced.kt
@@ -0,0 +1,105 @@
+package eu.kanade.tachiyomi.extension.zh.kuaikuai3
+
+import eu.kanade.tachiyomi.multisrc.mccms.DecryptInterceptor
+import eu.kanade.tachiyomi.network.GET
+import eu.kanade.tachiyomi.network.interceptor.rateLimitHost
+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.source.online.HttpSource
+import eu.kanade.tachiyomi.util.asJsoup
+import okhttp3.HttpUrl.Companion.toHttpUrl
+import okhttp3.Request
+import okhttp3.Response
+import org.jsoup.select.Evaluator
+
+open class MCCMSReduced(
+    override val name: String,
+    override val baseUrl: String,
+) : HttpSource() {
+    override val lang = "zh"
+    override val supportsLatest get() = false
+
+    override val client by lazy {
+        network.client.newBuilder()
+            .rateLimitHost(baseUrl.toHttpUrl(), 2)
+            .addInterceptor(DecryptInterceptor)
+            .build()
+    }
+
+    private fun searchOnly(): Nothing = throw Exception("此图源只支持搜索")
+    private val noWebView = "https://stevenyomi.github.io/echo#本图源不支持网页查看"
+
+    override fun popularMangaRequest(page: Int) = searchOnly()
+    override fun popularMangaParse(response: Response) = searchOnly()
+    override fun latestUpdatesRequest(page: Int) = searchOnly()
+    override fun latestUpdatesParse(response: Response) = searchOnly()
+
+    override fun getMangaUrl(manga: SManga) = noWebView
+    override fun getChapterUrl(chapter: SChapter) = noWebView
+
+    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 searchMangaParse(response: Response): MangasPage {
+        val document = response.asJsoup()
+        val placeholder = "$baseUrl/template/pc/default/images/bg_loadimg_3x4.png"
+        val entries = document.select(Evaluator.Tag("a")).map { link ->
+            SManga.create().apply {
+                url = link.attr("href")
+                title = link.ownText()
+                thumbnail_url = placeholder
+            }
+        }
+        return MangasPage(entries, false)
+    }
+
+    override fun mangaDetailsParse(response: Response): SManga {
+        val document = response.asJsoup()
+        val metaProperties = HashMap<String, String>()
+        for (element in document.head().children()) {
+            if (element.tagName() == "meta" && element.hasAttr("property")) {
+                val key = element.attr("property").removePrefix("og:")
+                metaProperties[key] = element.attr("content")
+            }
+        }
+        return SManga.create().apply {
+            title = metaProperties["title"]!!
+            author = metaProperties["novel:author"]
+            description = metaProperties["description"]
+            val statusText = metaProperties["novel:status"]
+            status = when {
+                statusText == null -> SManga.UNKNOWN
+                '连' in statusText -> SManga.ONGOING
+                '完' in statusText -> SManga.COMPLETED
+                else -> SManga.UNKNOWN
+            }
+            thumbnail_url = metaProperties["image"]
+        }
+    }
+
+    override fun chapterListParse(response: Response): List<SChapter> {
+        val document = response.asJsoup()
+        return document.select(Evaluator.Class("j-chapter-link")).asReversed().map { link ->
+            SChapter.create().apply {
+                url = link.attr("href")
+                name = link.ownText()
+            }
+        }
+    }
+
+    override fun pageListParse(response: Response): List<Page> {
+        val document = response.asJsoup()
+        return document.select(Evaluator.Tag("img")).mapIndexed { index, img ->
+            Page(index, imageUrl = img.attr("data-original"))
+        }
+    }
+
+    override fun imageUrlParse(response: Response) = throw UnsupportedOperationException()
+}
diff --git a/multisrc/overrides/mccms/manhuawu/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/mccms/manhuawu/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 000000000..7f9656e60
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/mccms/manhuawu/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 000000000..2937585cb
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/mccms/manhuawu/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..b4d91407e
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/mccms/manhuawu/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 000000000..0dcdb8298
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/mccms/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 000000000..7f3305374
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/res/web_hi_res_512.png b/multisrc/overrides/mccms/manhuawu/res/web_hi_res_512.png
new file mode 100644
index 000000000..bd1b52ea4
Binary files /dev/null and b/multisrc/overrides/mccms/manhuawu/res/web_hi_res_512.png differ
diff --git a/multisrc/overrides/mccms/manhuawu/src/Manhuawu.kt b/multisrc/overrides/mccms/manhuawu/src/Manhuawu.kt
new file mode 100644
index 000000000..d3138e9aa
--- /dev/null
+++ b/multisrc/overrides/mccms/manhuawu/src/Manhuawu.kt
@@ -0,0 +1,11 @@
+package eu.kanade.tachiyomi.extension.zh.manhuawu
+
+import eu.kanade.tachiyomi.multisrc.mccms.MCCMS
+import eu.kanade.tachiyomi.multisrc.mccms.MangaDto
+
+class Manhuawu : MCCMS("漫画屋", "https://www.mhua5.com", hasCategoryPage = true) {
+
+    override fun MangaDto.prepare() = copy(url = "/comic-$id.html")
+
+    override fun getMangaId(url: String) = url.substringAfterLast('-').substringBeforeLast('.')
+}
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/DecryptInterceptor.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/DecryptInterceptor.kt
index b2098f511..c0021b3dc 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/DecryptInterceptor.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/DecryptInterceptor.kt
@@ -1,5 +1,6 @@
 package eu.kanade.tachiyomi.multisrc.mccms
 
+import android.util.Base64
 import okhttp3.Interceptor
 import okhttp3.MediaType.Companion.toMediaType
 import okhttp3.Response
@@ -12,25 +13,38 @@ object DecryptInterceptor : Interceptor {
     override fun intercept(chain: Interceptor.Chain): Response {
         val request = chain.request()
         val response = chain.proceed(request)
-        val key = when (request.url.topPrivateDomain()) {
-            "bcebos.com" -> key1
-            null -> key2
+        val host = request.url.host
+        val type = when {
+            host.endsWith("bcebos.com") -> 1
+            host.endsWith("mhrsrc.com") -> 2
             else -> return response
         }
-        val data = decrypt(response.body.bytes(), key)
+        val data = decrypt(response.body.bytes(), type)
         val body = data.toResponseBody("image/jpeg".toMediaType())
         return response.newBuilder().body(body).build()
     }
 
     @Synchronized
-    private fun decrypt(input: ByteArray, key: SecretKeySpec): ByteArray {
+    private fun decrypt(input: ByteArray, type: Int): ByteArray {
         val cipher = cipher
-        cipher.init(Cipher.DECRYPT_MODE, key, iv)
-        return cipher.doFinal(input)
+        val decodedInput: ByteArray
+        when (type) {
+            1 -> {
+                decodedInput = input
+                cipher.init(Cipher.DECRYPT_MODE, key1, iv)
+            }
+            2 -> {
+                decodedInput = Base64.decode(input, Base64.DEFAULT)
+                cipher.init(Cipher.DECRYPT_MODE, key2, iv2)
+            }
+            else -> return input
+        }
+        return cipher.doFinal(decodedInput)
     }
 
     private val cipher by lazy(LazyThreadSafetyMode.NONE) { Cipher.getInstance("DESede/CBC/PKCS5Padding") }
     private val key1 by lazy(LazyThreadSafetyMode.NONE) { SecretKeySpec("OW84U8Eerdb99rtsTXWSILDO".toByteArray(), "DESede") }
-    private val key2 by lazy(LazyThreadSafetyMode.NONE) { SecretKeySpec("OW84U8Eerdb99rtsTXWSILEC".toByteArray(), "DESede") }
+    private val key2 by lazy(LazyThreadSafetyMode.NONE) { SecretKeySpec("ys6n2GvmgEyB3rELDX1gaTBf".toByteArray(), "DESede") }
     private val iv by lazy(LazyThreadSafetyMode.NONE) { IvParameterSpec("SK8bncVu".toByteArray()) }
+    private val iv2 by lazy(LazyThreadSafetyMode.NONE) { IvParameterSpec("2pnB3NI2".toByteArray()) }
 }
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt
index cabad627b..393448915 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMS.kt
@@ -18,7 +18,6 @@ import okhttp3.HttpUrl.Companion.toHttpUrl
 import okhttp3.Request
 import okhttp3.Response
 import rx.Observable
-import rx.Single
 import uy.kohesive.injekt.injectLazy
 import kotlin.concurrent.thread
 
@@ -49,13 +48,14 @@ open class MCCMS(
         .add("Referer", baseUrl)
 
     protected open fun SManga.cleanup(): SManga = this
+    protected open fun MangaDto.prepare(): MangaDto = 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<MangaDto> = response.parseAs()
-        return MangasPage(list.map { it.toSManga().cleanup() }, list.size >= PAGE_SIZE)
+        return MangasPage(list.map { it.prepare().toSManga().cleanup() }, list.size >= PAGE_SIZE)
     }
 
     override fun latestUpdatesRequest(page: Int): Request =
@@ -91,14 +91,14 @@ open class MCCMS(
             .toString()
         return client.newCall(GET(url, headers))
             .asObservableSuccess().map { response ->
-                val list: List<MangaDto> = response.parseAs()
+                val list = response.parseAs<List<MangaDto>>().map { it.prepare() }
                 list.find { it.url == manga.url }!!.toSManga().cleanup()
             }
     }
 
-    override fun mangaDetailsParse(response: Response) = throw UnsupportedOperationException("Not used.")
+    override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException("Not used.")
 
-    override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Single.create<List<SChapter>> { subscriber ->
+    override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> = Observable.fromCallable {
         val id = getMangaId(manga.url)
         val dataResponse = client.newCall(GET("$baseUrl/api/data/chapter?mid=$id", headers)).execute()
         val dataList: List<ChapterDataDto> = dataResponse.parseAs() // unordered
@@ -107,12 +107,12 @@ open class MCCMS(
         val response = client.newCall(GET("$baseUrl/api/comic/chapter?mid=$id", headers)).execute()
         val list: List<ChapterDto> = response.parseAs()
         val result = list.map { it.toSChapter(date = dateMap[it.id.toInt()] ?: 0) }.asReversed()
-        subscriber.onSuccess(result)
-    }.toObservable()
+        result
+    }
 
     protected open fun getMangaId(url: String) = url.substringAfterLast('/')
 
-    override fun chapterListParse(response: Response) = throw UnsupportedOperationException("Not used.")
+    override fun chapterListParse(response: Response): List<SChapter> = throw UnsupportedOperationException("Not used.")
 
     override fun pageListRequest(chapter: SChapter): Request =
         GET(baseUrl + chapter.url, pcHeaders)
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt
index ac7da6577..739982867 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSDto.kt
@@ -9,7 +9,8 @@ import java.util.Locale
 internal const val PAGE_SIZE = 30
 
 @Serializable
-class MangaDto(
+data class MangaDto(
+    val id: String,
     private val name: String,
     private val pic: String,
     private val serialize: String,
@@ -28,8 +29,8 @@ class MangaDto(
         val date = dateFormat.parse(addtime)?.time ?: 0
         val isUpdating = System.currentTimeMillis() - date <= 30L * 24 * 3600 * 1000 // a month
         status = when {
-            serialize.startsWith('连') || isUpdating -> SManga.ONGOING
-            serialize.startsWith('完') -> SManga.COMPLETED
+            '连' in serialize || isUpdating -> SManga.ONGOING
+            '完' in serialize -> SManga.COMPLETED
             else -> SManga.UNKNOWN
         }
         thumbnail_url = pic
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSGenerator.kt
index 88b2aad20..1c30f3e5b 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSGenerator.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSGenerator.kt
@@ -6,24 +6,8 @@ import generator.ThemeSourceGenerator
 class MCCMSGenerator : ThemeSourceGenerator {
     override val themeClass = "MCCMS"
     override val themePkg = "mccms"
-    override val baseVersionCode = 5
+    override val baseVersionCode = 6
     override val sources = listOf(
-        SingleLang(
-            name = "Haoman6",
-            baseUrl = "https://www.haoman6.com",
-            lang = "zh",
-            className = "Haoman6",
-            sourceName = "好漫6",
-            overrideVersionCode = 3,
-        ),
-        SingleLang( // previously: app2.haoman6.com, app2.haomanwu.com
-            name = "Haomanwu",
-            baseUrl = "https://move.bookcomic.org",
-            lang = "zh",
-            className = "Haomanwu",
-            sourceName = "好漫屋",
-            overrideVersionCode = 3,
-        ),
         SingleLang( // same as: www.haoman6.cc
             name = "Haoman6 (g-lens)",
             baseUrl = "https://www.g-lens.com",
@@ -32,58 +16,31 @@ class MCCMSGenerator : ThemeSourceGenerator {
             sourceName = "好漫6 (g-lens)",
             overrideVersionCode = 0,
         ),
-        SingleLang( // same as: www.haoman8.com
+        SingleLang( // same as: caiji.haoman8.com
             name = "Haoman8",
-            baseUrl = "https://caiji.haoman8.com",
+            baseUrl = "https://www.haoman8.com",
             lang = "zh",
             className = "Haoman8",
             sourceName = "好漫8",
             overrideVersionCode = 0,
         ),
         SingleLang(
-            name = "Kuaikuai Manhua",
-            baseUrl = "https://mobile.manhuaorg.com",
+            name = "Kuaikuai Manhua 3",
+            baseUrl = "https://mobile3.manhuaorg.com",
             lang = "zh",
-            className = "Kuaikuai",
-            sourceName = "快快漫画",
+            className = "Kuaikuai3",
+            sourceName = "快快漫画3",
             overrideVersionCode = 0,
         ),
         SingleLang(
-            name = "bz Manhua",
-            baseUrl = "https://www2.pupumanhua.com",
+            name = "Manhuawu",
+            baseUrl = "https://www.mhua5.com",
             lang = "zh",
-            className = "bzManhua",
-            sourceName = "包子漫画搬运",
+            className = "Manhuawu",
+            sourceName = "漫画屋",
             overrideVersionCode = 0,
         ),
         // The following sources are from https://www.yy123.cyou/ and are configured to use MCCMSNsfw
-        SingleLang( // 103=寄宿日记, same as: www.hanman.top (different URL format)
-            name = "Damao Manhua",
-            baseUrl = "https://www.hanman.cyou",
-            lang = "zh",
-            isNsfw = true,
-            className = "DamaoManhua",
-            sourceName = "大猫漫画",
-            overrideVersionCode = 0,
-        ),
-        SingleLang( // 103=诡秘的姐妹
-            name = "Heihei Manhua",
-            baseUrl = "https://www.hhmh.cyou",
-            lang = "zh",
-            isNsfw = true,
-            className = "HHMH",
-            sourceName = "嘿嘿漫画",
-            overrideVersionCode = 0,
-        ),
-        SingleLang( // 103=望月仙女傳說, same as: www.hanman.men
-            name = "Tudou Manhua",
-            baseUrl = "https://www.ptcomic.com",
-            lang = "zh",
-            isNsfw = true,
-            className = "PtComic",
-            sourceName = "土豆漫画",
-            overrideVersionCode = 0,
-        ),
         SingleLang( // 103=校园梦精记, same as: www.hmanwang.com, www.quanman8.com, www.lmmh.cc, www.xinmanba.com
             name = "Dida Manhua",
             baseUrl = "https://www.didamanhua.com",
diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt
index c0c7d3483..78dc6a174 100644
--- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt
+++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/mccms/MCCMSWeb.kt
@@ -21,7 +21,7 @@ open class MCCMSWeb(
     hasCategoryPage: Boolean = true,
 ) : MCCMS(name, baseUrl, lang, hasCategoryPage) {
 
-    fun parseListing(document: Document): MangasPage {
+    protected open fun parseListing(document: Document): MangasPage {
         val mangas = document.select(Evaluator.Class("common-comic-item")).map {
             SManga.create().apply {
                 val titleElement = it.selectFirst(Evaluator.Class("comic__title"))!!.child(0)
@@ -84,6 +84,12 @@ open class MCCMSWeb(
     override fun fetchMangaDetails(manga: SManga): Observable<SManga> {
         if (manga.url == "/index.php/search") return Observable.just(manga)
         return client.newCall(GET(baseUrl + manga.url, pcHeaders)).asObservableSuccess().map { response ->
+            mangaDetailsParse(response)
+        }
+    }
+
+    override fun mangaDetailsParse(response: Response): SManga {
+        return run {
             SManga.create().apply {
                 val document = response.asJsoup().selectFirst(Evaluator.Class("de-info__box"))!!
                 title = document.selectFirst(Evaluator.Class("comic-title"))!!.ownText()
@@ -98,6 +104,12 @@ open class MCCMSWeb(
     override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
         if (manga.url == "/index.php/search") return Observable.just(emptyList())
         return client.newCall(GET(baseUrl + manga.url, pcHeaders)).asObservableSuccess().map { response ->
+            chapterListParse(response)
+        }
+    }
+
+    override fun chapterListParse(response: Response): List<SChapter> {
+        return run {
             response.asJsoup().selectFirst(Evaluator.Class("chapter__list-box"))!!.children().map {
                 val link = it.child(0)
                 SChapter.create().apply {