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 {