From 11e66824c46d2aceabecd735da38b980e44c8d35 Mon Sep 17 00:00:00 2001 From: Mike <51273546+SnakeDoc83@users.noreply.github.com> Date: Sun, 21 Jan 2024 21:49:05 -0500 Subject: [PATCH] Update C&H (#473) --- src/en/explosm/build.gradle | 2 +- .../tachiyomi/extension/en/explosm/Explosm.kt | 114 ++++++++++++------ 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/src/en/explosm/build.gradle b/src/en/explosm/build.gradle index 04c1aa7ad..cee96f149 100644 --- a/src/en/explosm/build.gradle +++ b/src/en/explosm/build.gradle @@ -2,7 +2,7 @@ ext { extName = 'Cyanide & Happiness' pkgNameSuffix = 'en.explosm' extClass = '.Explosm' - extVersionCode = 3 + extVersionCode = 4 } apply from: "$rootDir/common.gradle" diff --git a/src/en/explosm/src/eu/kanade/tachiyomi/extension/en/explosm/Explosm.kt b/src/en/explosm/src/eu/kanade/tachiyomi/extension/en/explosm/Explosm.kt index 9c42a2b96..571534b8f 100644 --- a/src/en/explosm/src/eu/kanade/tachiyomi/extension/en/explosm/Explosm.kt +++ b/src/en/explosm/src/eu/kanade/tachiyomi/extension/en/explosm/Explosm.kt @@ -1,6 +1,7 @@ package eu.kanade.tachiyomi.extension.en.explosm import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.asObservableSuccess import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.Page @@ -8,11 +9,16 @@ 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 kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.JsonObject +import kotlinx.serialization.json.jsonArray +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.Response -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element import rx.Observable import java.text.SimpleDateFormat import java.util.Locale @@ -29,23 +35,39 @@ class Explosm : HttpSource() { override val client: OkHttpClient = network.cloudflareClient - private fun createManga(element: Element): SManga { - return SManga.create().apply { - initialized = true - title = "C&H ${element.attr("id").substringAfter("panel")}" // year - setUrlWithoutDomain(element.select("li a").first()!!.attr("href")) // January - thumbnail_url = "https://vhx.imgix.net/vitalyuncensored/assets/13ea3806-5ebf-4987-bcf1-82af2b689f77/S2E4_Still1.jpg" - } + private val archivePage = "$baseUrl/comics" + + private fun getArchiveAllYears(response: Response): JsonObject { + val jsonPath = response.asJsoup() + .select("head > script").last()?.attr("src") + ?.replace("static", "data") + ?.replaceAfterLast("/", "comics.json") + ?: throw Exception("Error at last() in getArchiveAllYears") + val json = client.newCall(GET(baseUrl + jsonPath, headers)).execute().body.string() + return Json.decodeFromString(json)["pageProps"] + ?.jsonObject?.get("comicArchiveData") + ?.jsonObject + ?: throw Exception("Error while returning getArchiveAllYears") } // Popular override fun popularMangaRequest(page: Int): Request { - return (GET("$baseUrl/comics/archive", headers)) + return (GET(archivePage, headers)) } override fun popularMangaParse(response: Response): MangasPage { - val eachYearAsAManga = response.asJsoup().select("dd.accordion-navigation > div").map { createManga(it) } + val eachYearAsAManga = getArchiveAllYears(response) + .map { year -> + SManga.create().apply { + initialized = true + title = "C&H " + year.key // year + url = year.key // need key here + thumbnail_url = "https://vhx.imgix.net/vitalyuncensored/assets/13ea3806-5ebf-4987-bcf1-82af2b689f77/S2E4_Still1.jpg" + author = "Explosm.net" + } + } + .reversed() return MangasPage(eachYearAsAManga, false) } @@ -66,49 +88,63 @@ class Explosm : HttpSource() { // Details - override fun mangaDetailsParse(response: Response): SManga { - return createManga(response.asJsoup().select("div.content.active").first()!!) + override fun fetchMangaDetails(manga: SManga): Observable { + return Observable.just(manga) } + // for webview + override fun mangaDetailsRequest(manga: SManga): Request { + return GET("$baseUrl/comics#${manga.url}-01") + } + + override fun mangaDetailsParse(response: Response): SManga = throw UnsupportedOperationException() + // Chapters - override fun chapterListParse(response: Response): List { - val document = response.asJsoup() + private val date = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US) - val januaryChapters = document.chaptersFromDocument() // should be at bottom of final returned list - - // get the rest of the year - val chapters = document.select("div.content.active li:not(.active) a").reversed().map { - client.newCall(GET(it.attr("abs:href"), headers)).execute().asJsoup().chaptersFromDocument() - }.flatten() - - return chapters + januaryChapters + private fun JsonElement?.getContent(key: String): String { + return this?.jsonObject?.get(key)?.jsonPrimitive?.content ?: throw Exception("Error getting chapter content from $key") } - private fun Document.chaptersFromDocument(): List { - return this.select("div.inner-wrap > div.row div.row.collapse").map { element -> - SChapter.create().apply { - setUrlWithoutDomain(element.select("a").attr("href")) - element.select("div#comic-author").text().let { cName -> - name = cName - date_upload = SimpleDateFormat("yyyy.MM.dd", Locale.getDefault()) - .parse(cName.substringBefore(" "))?.time ?: 0L - } + override fun fetchChapterList(manga: SManga): Observable> { + var chapterCount = 0F + return client.newCall(GET(archivePage, headers)) + .asObservableSuccess() + .map { response -> + getArchiveAllYears(response)[manga.url]?.jsonObject + ?.map { month -> + month.value.jsonArray.map { comic -> + chapterCount++ + SChapter.create().apply { + name = comic.getContent("slug") + // we get the url for page.imageurl here + url = if (comic.getContent("file_static") != "null") { + comic.getContent("file_static") + } else { + "https://files.explosm.net/comics/${comic.getContent("file")}" + } + date_upload = date.parse(comic.getContent("publish_at"))?.time ?: 0L + scanlator = comic.getContent("author_name") + chapter_number = chapterCount // so no "missing chapters" warning in app + } + } + } + ?.flatten() + ?.reversed() + ?: throw Exception("Error with main jsonObject") } - } } + override fun chapterListParse(response: Response): List = throw UnsupportedOperationException() + // Pages override fun fetchPageList(chapter: SChapter): Observable> { - return Observable.just(listOf(Page(0, baseUrl + chapter.url))) + return Observable.just(listOf(Page(0, "", chapter.url))) } override fun pageListParse(response: Response): List = throw UnsupportedOperationException() - override fun imageUrlParse(response: Response): String { - return response.asJsoup().select("div#comic-wrap img").attr("abs:src") - } - - override fun getFilterList() = FilterList() + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() }