From eacb84dbf8ba262f109b7460818aef4ee2d6a943 Mon Sep 17 00:00:00 2001 From: John Bi Date: Sat, 25 Sep 2021 18:20:08 +0800 Subject: [PATCH] feat: wnacg extension change (#9214) 1. code format 2. add category filter 3. manga detail add description parse 4. add nsfw 5. change extVersionCode 6. fix next page selector logic Co-authored-by: John Bi <869384236@qq.com> --- src/zh/wnacg/build.gradle | 3 +- .../tachiyomi/extension/zh/wnacg/wnacg.kt | 93 ++++++++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/src/zh/wnacg/build.gradle b/src/zh/wnacg/build.gradle index 54205fc3d..dff174619 100644 --- a/src/zh/wnacg/build.gradle +++ b/src/zh/wnacg/build.gradle @@ -5,7 +5,8 @@ ext { extName = 'WNACG' pkgNameSuffix = 'zh.wnacg' extClass = '.wnacg' - extVersionCode = 5 + extVersionCode = 6 + containsNsfw = true } apply from: "$rootDir/common.gradle" diff --git a/src/zh/wnacg/src/eu/kanade/tachiyomi/extension/zh/wnacg/wnacg.kt b/src/zh/wnacg/src/eu/kanade/tachiyomi/extension/zh/wnacg/wnacg.kt index 5748f9978..53ede5942 100644 --- a/src/zh/wnacg/src/eu/kanade/tachiyomi/extension/zh/wnacg/wnacg.kt +++ b/src/zh/wnacg/src/eu/kanade/tachiyomi/extension/zh/wnacg/wnacg.kt @@ -1,7 +1,11 @@ package eu.kanade.tachiyomi.extension.zh.wnacg +import eu.kanade.tachiyomi.annotations.Nsfw import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservableSuccess +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 @@ -12,7 +16,9 @@ import okhttp3.Request import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element +import rx.Observable +@Nsfw class wnacg : ParsedHttpSource() { override val name = "紳士漫畫" override val baseUrl = "https://www.wnacg.org" @@ -24,7 +30,7 @@ class wnacg : ParsedHttpSource() { override fun searchMangaSelector() = popularMangaSelector() override fun chapterListSelector() = "div.f_left > a" - override fun popularMangaNextPageSelector() = "a:containsOwn(後頁)" + override fun popularMangaNextPageSelector() = "span.thispage + a" override fun latestUpdatesNextPageSelector() = throw Exception("Not used") override fun searchMangaNextPageSelector() = popularMangaNextPageSelector() @@ -34,6 +40,30 @@ class wnacg : ParsedHttpSource() { override fun latestUpdatesRequest(page: Int) = throw Exception("Not used") + override fun fetchSearchManga( + page: Int, + query: String, + filters: FilterList + ): Observable { + // ps: this web don't support category search and sort + var req: Request? = null + if (query.isNotBlank()) { + req = this.searchMangaRequest(page, query, filters) + } else if (filters.isNotEmpty()) { + filters.forEach { filter -> + if (filter is CategoryFilter) { + req = GET("$baseUrl/" + filter.toUriPart().format(page)) + } + } + } + if (req != null) { + return client.newCall(req!!) + .asObservableSuccess() + .map { response -> queryParse(response) } + } + return super.fetchSearchManga(page, query, filters) + } + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { return GET("$baseUrl/search/index.php?q=$query&p=$page", headers) } @@ -46,7 +76,10 @@ class wnacg : ParsedHttpSource() { .set("referer", baseUrl) .set("sec-fetch-mode", "no-cors") .set("sec-fetch-site", "cross-site") - .set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36") + .set( + "User-Agent", + "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36" + ) override fun popularMangaFromElement(element: Element) = mangaFromElement(element) override fun latestUpdatesFromElement(element: Element) = throw Exception("Not used") @@ -63,6 +96,14 @@ class wnacg : ParsedHttpSource() { return manga } + private fun queryParse(response: Response): MangasPage { + val document = response.asJsoup() + val mangas = document.select(searchMangaSelector()) + .map { element -> searchMangaFromElement(element) } + val nextPage = document.select(searchMangaNextPageSelector()).first() != null + return MangasPage(mangas, nextPage) + } + override fun chapterListParse(response: Response): List { val document = response.asJsoup() val chapters = mutableListOf() @@ -83,14 +124,25 @@ class wnacg : ParsedHttpSource() { manga.title = document.select("h2")?.text()?.trim() ?: "Unknown" manga.artist = document.select("div.uwuinfo p")?.first()?.text()?.trim() ?: "Unknown" manga.author = document.select("div.uwuinfo p")?.first()?.text()?.trim() ?: "Unknown" - manga.thumbnail_url = "https://" + document.select("div.uwthumb img").first().attr("src").replace("//", "") + manga.thumbnail_url = + "https://" + document.select("div.uwthumb img").first().attr("src").replace("//", "") + manga.description = + document.select("div.asTBcell p")?.first()?.html()?.replace("
", "\n") + return manga } override fun pageListParse(document: Document): List { val regex = "\\/\\/\\S*(jpg|png)".toRegex() - val slideaid = client.newCall(GET(baseUrl + document.select("a.btn:containsOwn(下拉閱讀)").attr("href"), headers)).execute().asJsoup() - val galleryaid = client.newCall(GET(baseUrl + slideaid.select("script[src$=html]").attr("src"), headers)).execute().asJsoup().toString() + val slideaid = client.newCall( + GET( + baseUrl + document.select("a.btn:containsOwn(下拉閱讀)").attr("href"), + headers + ) + ).execute().asJsoup() + val galleryaid = + client.newCall(GET(baseUrl + slideaid.select("script[src$=html]").attr("src"), headers)) + .execute().asJsoup().toString() val matchresult = regex.findAll(galleryaid).map { it.value }.toList() val pages = mutableListOf() for (i in matchresult.indices) { @@ -102,4 +154,35 @@ class wnacg : ParsedHttpSource() { override fun chapterFromElement(element: Element) = throw Exception("Not used") override fun imageUrlRequest(page: Page) = throw Exception("Not used") override fun imageUrlParse(document: Document) = throw Exception("Not used") + + // >>> Filters >>> + + override fun getFilterList() = FilterList( + Filter.Header("注意:分类不支持搜索"), + CategoryFilter() + ) + + private class CategoryFilter : UriPartFilter( + "分类", + arrayOf( + Pair("更新", "albums-index-page-%d.html"), + Pair("同人志-汉化", "albums-index-page-%d-cate-1.html"), + Pair("同人志-日语", "albums-index-page-%d-cate-12.html"), + Pair("同人志-CG书籍", "albums-index-page-%d-cate-2.html"), + Pair("同人志-Cosplay", "albums-index-page-%d-cate-3.html"), + Pair("单行本-汉化", "albums-index-page-%d-cate-9.html"), + Pair("单行本-日语", "albums-index-page-%d-cate-13.html"), + Pair("杂志&短篇-汉语", "albums-index-page-%d-cate-10.html"), + Pair("杂志&短篇-日语", "albums-index-page-%d-cate-14.html"), + Pair("韩漫-汉化", "albums-index-page-%d-cate-20.html"), + Pair("韩漫-生肉", "albums-index-page-%d-cate-21.html"), + ) + ) + + private open class UriPartFilter(displayName: String, val vals: Array>) : + Filter.Select(displayName, vals.map { it.first }.toTypedArray()) { + fun toUriPart() = vals[state].second + } + + // <<< Filters <<< }