diff --git a/src/zh/yimmh/AndroidManifest.xml b/src/zh/yimmh/AndroidManifest.xml
deleted file mode 100644
index 30deb7f79..000000000
--- a/src/zh/yimmh/AndroidManifest.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
diff --git a/src/zh/yimmh/build.gradle b/src/zh/yimmh/build.gradle
deleted file mode 100644
index d461af204..000000000
--- a/src/zh/yimmh/build.gradle
+++ /dev/null
@@ -1,11 +0,0 @@
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-
-ext {
- extName = 'Yimmh'
- pkgNameSuffix = 'zh.yimmh'
- extClass = '.Yimmh'
- extVersionCode = 5
-}
-
-apply from: "$rootDir/common.gradle"
diff --git a/src/zh/yimmh/res/mipmap-hdpi/ic_launcher.png b/src/zh/yimmh/res/mipmap-hdpi/ic_launcher.png
deleted file mode 100644
index ce7c14c44..000000000
Binary files a/src/zh/yimmh/res/mipmap-hdpi/ic_launcher.png and /dev/null differ
diff --git a/src/zh/yimmh/res/mipmap-mdpi/ic_launcher.png b/src/zh/yimmh/res/mipmap-mdpi/ic_launcher.png
deleted file mode 100644
index db11a1b4d..000000000
Binary files a/src/zh/yimmh/res/mipmap-mdpi/ic_launcher.png and /dev/null differ
diff --git a/src/zh/yimmh/res/mipmap-xhdpi/ic_launcher.png b/src/zh/yimmh/res/mipmap-xhdpi/ic_launcher.png
deleted file mode 100644
index 142a544db..000000000
Binary files a/src/zh/yimmh/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/zh/yimmh/res/mipmap-xxhdpi/ic_launcher.png b/src/zh/yimmh/res/mipmap-xxhdpi/ic_launcher.png
deleted file mode 100644
index 99bf6f5d5..000000000
Binary files a/src/zh/yimmh/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/zh/yimmh/res/mipmap-xxxhdpi/ic_launcher.png b/src/zh/yimmh/res/mipmap-xxxhdpi/ic_launcher.png
deleted file mode 100644
index 20ab8d0dc..000000000
Binary files a/src/zh/yimmh/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ
diff --git a/src/zh/yimmh/res/web_hi_res_512.png b/src/zh/yimmh/res/web_hi_res_512.png
deleted file mode 100644
index 16ef244bc..000000000
Binary files a/src/zh/yimmh/res/web_hi_res_512.png and /dev/null differ
diff --git a/src/zh/yimmh/src/eu/kanade/tachiyomi/extension/zh/yimmh/Yimmh.kt b/src/zh/yimmh/src/eu/kanade/tachiyomi/extension/zh/yimmh/Yimmh.kt
deleted file mode 100644
index a93e2f2f7..000000000
--- a/src/zh/yimmh/src/eu/kanade/tachiyomi/extension/zh/yimmh/Yimmh.kt
+++ /dev/null
@@ -1,224 +0,0 @@
-package eu.kanade.tachiyomi.extension.zh.yimmh
-
-import android.annotation.SuppressLint
-import android.net.Uri
-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
-import eu.kanade.tachiyomi.source.online.ParsedHttpSource
-import eu.kanade.tachiyomi.util.asJsoup
-import okhttp3.Headers
-import okhttp3.OkHttpClient
-import okhttp3.Request
-import okhttp3.Response
-import org.json.JSONObject
-import org.jsoup.nodes.Document
-import org.jsoup.nodes.Element
-import java.security.cert.X509Certificate
-import javax.net.ssl.SSLContext
-import javax.net.ssl.TrustManager
-import javax.net.ssl.X509TrustManager
-
-class Yimmh : ParsedHttpSource() {
- override val name: String = "忆漫"
- override val lang: String = "zh"
- override val supportsLatest: Boolean = true
- override val baseUrl: String = "https://m.yimmh.com"
- override fun headersBuilder() = Headers.Builder()
- .add("User-Agent", System.getProperty("http.agent")!!)
- override val client: OkHttpClient = getUnsafeOkHttpClient()
-
- // Trusted all certificates
- private fun getUnsafeOkHttpClient(): OkHttpClient {
- // Create a trust manager that does not validate certificate chains
- val trustAllCerts = arrayOf(
- @SuppressLint("CustomX509TrustManager")
- object : X509TrustManager {
- @SuppressLint("TrustAllX509TrustManager")
- override fun checkClientTrusted(chain: Array?, authType: String?) {
- }
- @SuppressLint("TrustAllX509TrustManager")
- override fun checkServerTrusted(chain: Array?, authType: String?) {
- }
-
- override fun getAcceptedIssuers() = arrayOf()
- }
- )
-
- // Install the all-trusting trust manager
- val sslContext = SSLContext.getInstance("SSL")
- sslContext.init(null, trustAllCerts, java.security.SecureRandom())
- // Create an ssl socket factory with our all-trusting manager
- val sslSocketFactory = sslContext.socketFactory
-
- return OkHttpClient.Builder()
- .sslSocketFactory(sslSocketFactory, trustAllCerts[0] as X509TrustManager)
- .hostnameVerifier { _, _ -> true }.build()
- }
-
- // Popular
-
- override fun popularMangaRequest(page: Int) = GET("$baseUrl/rank", headers)
- override fun popularMangaNextPageSelector(): String? = null
- override fun popularMangaSelector(): String = "ul.rank-list > a"
- override fun popularMangaFromElement(element: Element): SManga = SManga.create().apply {
- title = element.select("p.rank-list-info-right-title").text()
- setUrlWithoutDomain(element.attr("abs:href"))
- thumbnail_url = element.select("img").attr("abs:data-original")
- }
-
- // Latest
-
- override fun latestUpdatesParse(response: Response): MangasPage {
- val body = response.body?.string().orEmpty()
- val json = JSONObject(body)
- if (json.getInt("err") != 0) {
- return MangasPage(listOf(), false)
- }
- val mangas = arrayListOf()
- val books = json.getJSONArray("books")
- for (i in 0 until books.length()) {
- val book = books.getJSONObject(i)
- mangas.add(
- SManga.create().apply {
- title = book.getString("book_name")
- url = "/book/${book.getString("unique_id")}"
- thumbnail_url = book.getString("cover_url")
- }
- )
- }
- return MangasPage(mangas, true)
- }
-
- override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/getUpdate?page=${page * 15 - 15}", headers)
- override fun latestUpdatesNextPageSelector(): String? = throw Exception("Not used")
- override fun latestUpdatesSelector() = throw Exception("Not used")
- override fun latestUpdatesFromElement(element: Element) = throw Exception("Not used")
-
- // Search
-
- override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
- val uri = Uri.parse(baseUrl).buildUpon()
- if (query.isNotBlank()) {
- uri.appendPath("search")
- .appendQueryParameter("keyword", query)
- } else {
- uri.appendPath("getBooks")
- filters.forEach {
- if (it is CategoryFilter)
- uri.appendQueryParameter("tag", it.toUri())
- else if (it is StatusFilter)
- uri.appendQueryParameter("end", it.toUri())
- }
- uri.appendQueryParameter("page", (page * 15 - 15).toString())
- }
- return GET(uri.toString(), headers)
- }
-
- override fun searchMangaParse(response: Response): MangasPage {
- return if (response.request.url.toString().startsWith("https://m.yimmh.com/search"))
- super.searchMangaParse(response)
- else
- latestUpdatesParse(response)
- }
-
- override fun searchMangaNextPageSelector(): String? = null
- override fun searchMangaSelector(): String = "ul.book-list > li"
- override fun searchMangaFromElement(element: Element): SManga = SManga.create().apply {
- title = element.select("p.book-list-info-title").text()
- setUrlWithoutDomain(element.select("a").attr("abs:href"))
- thumbnail_url = element.select("img").attr("abs:data-original")
- }
-
- // Details
-
- override fun mangaDetailsParse(document: Document): SManga = SManga.create().apply {
- title = document.select("p.detail-main-info-title").text()
- thumbnail_url = document.select("div.detail-main-cover > img").attr("abs:data-original")
- author = document.select("p.detail-main-info-author:contains(作者:) > a").text()
- artist = author
- genre = document.select("p.detail-main-info-class > span").eachText().joinToString(", ")
- description = document.select("p.detail-desc").text()
- status = when (document.select("span.detail-list-title-1").text()) {
- "连载中" -> SManga.ONGOING
- "已完结" -> SManga.COMPLETED
- else -> SManga.UNKNOWN
- }
- }
-
- // Chapters
-
- override fun chapterListSelector(): String = "ul#detail-list-select > li"
- override fun chapterFromElement(element: Element): SChapter = SChapter.create().apply {
- setUrlWithoutDomain(element.select("a.chapteritem").attr("abs:href"))
- name = element.select("a.chapteritem").text()
- }
- override fun chapterListParse(response: Response): List {
- return super.chapterListParse(response).reversed()
- }
-
- // Pages
-
- override fun pageListParse(document: Document): List = mutableListOf().apply {
- var page = document
- while (true) {
- val images = page.select("div#cp_img > img.lazy")
- images.forEach {
- add(Page(size, "", it.attr("abs:data-src")))
- }
- val nextPage = page.select("a.view-bottom-bar-item:contains(下一页)").attr("href")
- if (nextPage.isNullOrEmpty()) {
- break
- } else {
- page = client.newCall(GET(baseUrl + nextPage, headers))
- .execute().asJsoup()
- }
- }
- }
-
- override fun imageUrlParse(document: Document): String = throw Exception("Not Used")
-
- // Filters
-
- override fun getFilterList() = FilterList(
- Filter.Header("如果使用文本搜索"),
- Filter.Header("过滤器将被忽略"),
- CategoryFilter(),
- StatusFilter()
- )
-
- private class CategoryFilter : UriSelectFilterPath(
- "分类",
- arrayOf(
- Pair("全部", "全部"),
- Pair("耽美", "耽美"),
- Pair("热血", "热血"),
- Pair("大女主", "大女主")
- )
- )
-
- private class StatusFilter : UriSelectFilterPath(
- "进度",
- arrayOf(
- Pair("-1", "全部"),
- Pair("2", "连载中"),
- Pair("1", "已完结")
- )
- )
-
- /**
- * Class that creates a select filter. Each entry in the dropdown has a name and a display name.
- * If an entry is selected it is appended as a query parameter onto the end of the URI.
- */
- // vals:
- private open class UriSelectFilterPath(
- displayName: String,
- val vals: Array>
- ) : Filter.Select(displayName, vals.map { it.second }.toTypedArray()) {
- fun toUri() = vals[state].first
- }
-}