From 0bb60c35a68b8a3386ef39a5c500dd137819fed6 Mon Sep 17 00:00:00 2001 From: beerpsi <92439990+beerpiss@users.noreply.github.com> Date: Tue, 23 Jan 2024 14:00:12 +0700 Subject: [PATCH] Add JapScan (again) (#510) * Add JapScan (again) * remove unusued dep * fix search thumbnails --- src/fr/japscan/AndroidManifest.xml | 2 + src/fr/japscan/build.gradle | 7 + .../japscan/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 3204 bytes .../japscan/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2077 bytes .../japscan/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 4609 bytes .../japscan/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 8131 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 13220 bytes .../tachiyomi/extension/fr/japscan/Japscan.kt | 405 ++++++++++++++++++ 8 files changed, 414 insertions(+) create mode 100644 src/fr/japscan/AndroidManifest.xml create mode 100644 src/fr/japscan/build.gradle create mode 100644 src/fr/japscan/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/fr/japscan/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/fr/japscan/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/fr/japscan/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/fr/japscan/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/fr/japscan/src/eu/kanade/tachiyomi/extension/fr/japscan/Japscan.kt diff --git a/src/fr/japscan/AndroidManifest.xml b/src/fr/japscan/AndroidManifest.xml new file mode 100644 index 000000000..8072ee00d --- /dev/null +++ b/src/fr/japscan/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/src/fr/japscan/build.gradle b/src/fr/japscan/build.gradle new file mode 100644 index 000000000..852cb9fb8 --- /dev/null +++ b/src/fr/japscan/build.gradle @@ -0,0 +1,7 @@ +ext { + extName = 'Japscan' + extClass = '.Japscan' + extVersionCode = 44 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/fr/japscan/res/mipmap-hdpi/ic_launcher.png b/src/fr/japscan/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..4659fbb8cb82d4edeafa68853b0c001d9bb76071 GIT binary patch literal 3204 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%0A!1 zGC(gBfV0#yGvg8y;pys%74N<)6>+SzB)_ETLj&jchvN!qW(8M8YX$)BPUjtJpw`8-^1m-yxJj*DL4FNhal1Muz05GcvOzpwqdRnBGgcbqf(uQ8>PL zFLq3s0@K#5v91iWQxbV;u(^FZoZPb;>AdZ|Vk@FG0{}NoU%he#8`iJKB+-Rv)uges zp0bU?$}RMTcsDaQOk30YmV%Mya*JshTMwD}%SA!OR)AoxRp({t<>qV0H~$Wok0!ul z)|c?2%+`D9QuwU;0mn!P+~&@KGdWXxifAl#n@S*Blr^s?*l^d)p(RTYPXfhe@}*yn zX4U5|lYrBw@rAK57H~w-sA1_A5p8-(+O(x!JROA@WU1F2(}oU#ezRs+BGziG<*JsV z=BsSJwh*8&$kt7pz^buu>WaB7l*M~7r_}B$c3SM6|23jwW08I5c4d;jngM`qzUz@A z7}K{eexz`YJJ2^Mnx>y3g?%rr)5?w1Vwb~ul4|>(eu6zENsGSy7Q&3oZMJ=5$`S4$;@HA(PBjB@6T~9su6b!5xU)=r*E% zf6QS9X-Z0e%p_|;RtmCKkfo43UJCf0OqBUYAK{p%C!(%i#pMeZaNNfS+wJW!Z_XTy zefu4ZB~vzquKiXtV4Eo#uWhvE)Fufup)nkKa?Y`|b7xr0_zd1hkK!6R=qfP3<}`q} z00x{o1yhpR_xtq0$9j5F>2E&K60v1urJxnu&nu+)Yi_D;(Ejue)`_A~J7Q-+vEx(%f+JU#ViwTGt~cKkw~2MIiyiBqwKQtX{ho-;gt0 zICCcEOq_@r6w-ZWV1UmJ4KZuP2$)R$6ssr$T}RGxhn*d~{rnI{jK4|D&ZN*%?$Ir+ zYSI0fLD$GOb5ma6*|YHUItnKWV{JBX#>y2duxRc)eDmd(SU6)kW|J1pHZsCjpG#5`%q+j{BX&$$$WyJ%1h-=$dFUGYMqAIE3Z(AZGltBv9T3!C-ScDfjta zqa=>kb1svHgocLlBZH-2;H1Al`~>;a|G@Kw5^zz`(YQ`FKAApyo9@BDR`KyPFJC6i z2^lkqZD|I5Nsf^CfqXJ$P-@Qw^K6Q-nF0BgYz>tG;gwW29Sk6s9QpoCJg@w-a=yGj z0lD68O{_zt0-yq*0-yq*0-yq*0#L&MWD^f7|M+_Sp+kKhs{m9E019)9i;7a-8#b(6 zg#qB>ONd(a=+VQGGDP(VlZw~3i++Fbpg1Hb=t7GYE%-RF3Z1SeA6Lkyk*)GOapFE7 zQl=i_Q{gjY;Opb#S=pnkWHV&Ea>a@iag3E}hAME160z*@q)C(Bt~3C`40X}f)!h?z z@#4cj9zHB45L7Mre<(L6=h2hLkKuCgpgZ%uDkrRJ#Ainh89eyX{oj7W!~6FoO&}Xr zTv)pf)p_oRw{f6ClK+U$+04$&OzPgPTW7(;svU7lC^n;)sY8Yg36746l8)))qpkS- z#DbD@CF?aY4=6|hA9BjW*W3HzYczxfsh$&6g+m_Rx^-*&A6Bl64-E-PS)0la}i4wgQ#ger$!1Z!KBeV=fmYSa-P5-i%IJ{ rX~en9&z13i21b1+b*Mufl^*{EJiv<0Dv4gV00000NkvXXu0mjfRpQF( literal 0 HcmV?d00001 diff --git a/src/fr/japscan/res/mipmap-xxhdpi/ic_launcher.png b/src/fr/japscan/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..52e248fa63f4a93e97522f490da5f00a34fe0b47 GIT binary patch literal 8131 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 W_J-M}5+VlxEwYkI5|v`cLH`3Cj~-().getSharedPreferences("source_$id", 0x0000) + } + + override val client: OkHttpClient = network.cloudflareClient.newBuilder() + .rateLimit(1, 2) + .build() + + companion object { + val dateFormat by lazy { + SimpleDateFormat("dd MMM yyyy", Locale.US) + } + private const val SHOW_SPOILER_CHAPTERS_Title = "Les chapitres en Anglais ou non traduit sont upload en tant que \" Spoilers \" sur Japscan" + private const val SHOW_SPOILER_CHAPTERS = "JAPSCAN_SPOILER_CHAPTERS" + private val prefsEntries = arrayOf("Montrer uniquement les chapitres traduit en Français", "Montrer les chapitres spoiler") + private val prefsEntryValues = arrayOf("hide", "show") + } + + private fun chapterListPref() = preferences.getString(SHOW_SPOILER_CHAPTERS, "hide") + + override fun headersBuilder() = super.headersBuilder() + .add("referer", "$baseUrl/") + + // Popular + override fun popularMangaRequest(page: Int): Request { + return GET("$baseUrl/mangas/", headers) + } + + override fun popularMangaParse(response: Response): MangasPage { + val document = response.asJsoup() + pageNumberDoc = document + + val mangas = document.select(popularMangaSelector()).map { element -> + popularMangaFromElement(element) + } + val hasNextPage = false + return MangasPage(mangas, hasNextPage) + } + + override fun popularMangaNextPageSelector(): String? = null + + override fun popularMangaSelector() = "#top_mangas_week li" + + override fun popularMangaFromElement(element: Element): SManga { + val manga = SManga.create() + element.select("a").first()!!.let { + manga.setUrlWithoutDomain(it.attr("href")) + manga.title = it.text() + manga.thumbnail_url = "$baseUrl/imgs/${it.attr("href").replace(Regex("/$"),".jpg").replace("manga","mangas")}".lowercase(Locale.ROOT) + } + return manga + } + + // Latest + private lateinit var latestDirectory: List + + override fun fetchLatestUpdates(page: Int): Observable { + return if (page == 1) { + client.newCall(latestUpdatesRequest(page)) + .asObservableSuccess() + .map { latestUpdatesParse(it) } + } else { + Observable.just(parseLatestDirectory(page)) + } + } + + override fun latestUpdatesRequest(page: Int): Request { + return GET(baseUrl, headers) + } + + override fun latestUpdatesParse(response: Response): MangasPage { + val document = response.asJsoup() + + latestDirectory = document.select(latestUpdatesSelector()) + .distinctBy { element -> element.select("a").attr("href") } + + return parseLatestDirectory(1) + } + + private fun parseLatestDirectory(page: Int): MangasPage { + val manga = mutableListOf() + val end = ((page * 24) - 1).let { if (it <= latestDirectory.lastIndex) it else latestDirectory.lastIndex } + + for (i in (((page - 1) * 24)..end)) { + manga.add(latestUpdatesFromElement(latestDirectory[i])) + } + + return MangasPage(manga, end < latestDirectory.lastIndex) + } + + override fun latestUpdatesSelector() = "#chapters h3.mb-0" + + override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) + + override fun latestUpdatesNextPageSelector(): String = throw UnsupportedOperationException() + + // Search + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + if (query.isEmpty()) { + val url = baseUrl.toHttpUrl().newBuilder().apply { + addPathSegment("mangas") + + filters.forEach { filter -> + when (filter) { + is TextField -> addPathSegment(((page - 1) + filter.state.toInt()).toString()) + is PageList -> addPathSegment(((page - 1) + filter.values[filter.state]).toString()) + else -> {} + } + } + }.build() + + return GET(url, headers) + } else { + val formBody = FormBody.Builder() + .add("search", query) + .build() + val searchHeaders = headers.newBuilder() + .add("X-Requested-With", "XMLHttpRequest") + .build() + + return POST("$baseUrl/live-search/", searchHeaders, formBody) + } + } + + override fun searchMangaNextPageSelector(): String = "li.page-item:last-child:not(li.active)" + + override fun searchMangaSelector(): String = "div.card div.p-2" + + override fun searchMangaParse(response: Response): MangasPage { + if (response.request.url.pathSegments.first() == "live-search") { + val jsonResult = json.parseToJsonElement(response.body.string()).jsonArray + + val mangaList = jsonResult.map { jsonEl -> searchMangaFromJson(jsonEl.jsonObject) } + + return MangasPage(mangaList, hasNextPage = false) + } + + val baseUrlHost = baseUrl.toHttpUrl().host + val document = response.asJsoup() + val manga = document + .select(searchMangaSelector()) + .filter { it -> + // Filter out ads masquerading as search results + it.select("p a").attr("abs:href").toHttpUrl().host == baseUrlHost + } + .map(::searchMangaFromElement) + val hasNextPage = document.selectFirst(searchMangaNextPageSelector()) != null + + return MangasPage(manga, hasNextPage) + } + + override fun searchMangaFromElement(element: Element) = SManga.create().apply { + thumbnail_url = element.select("img").attr("abs:src") + element.select("p a").let { + title = it.text() + url = it.attr("href") + } + } + + private fun searchMangaFromJson(jsonObj: JsonObject): SManga = SManga.create().apply { + url = jsonObj["url"]!!.jsonPrimitive.content + title = jsonObj["name"]!!.jsonPrimitive.content + thumbnail_url = baseUrl + jsonObj["image"]!!.jsonPrimitive.content + } + + override fun mangaDetailsParse(document: Document): SManga { + val infoElement = document.selectFirst("#main .card-body")!! + + val manga = SManga.create() + manga.thumbnail_url = infoElement.select("img").attr("abs:src") + + val infoRows = infoElement.select(".row, .d-flex") + infoRows.select("p").forEach { el -> + when (el.select("span").text().trim()) { + "Auteur(s):" -> manga.author = el.text().replace("Auteur(s):", "").trim() + "Artiste(s):" -> manga.artist = el.text().replace("Artiste(s):", "").trim() + "Genre(s):" -> manga.genre = el.text().replace("Genre(s):", "").trim() + "Statut:" -> manga.status = el.text().replace("Statut:", "").trim().let { + parseStatus(it) + } + } + } + manga.description = infoElement.select("div:contains(Synopsis) + p").text().orEmpty() + + return manga + } + + private fun parseStatus(status: String) = when { + status.contains("En Cours") -> SManga.ONGOING + status.contains("Terminé") -> SManga.COMPLETED + else -> SManga.UNKNOWN + } + + override fun chapterListSelector() = "#chapters_list > div.collapse > div.chapters_list" + + if (chapterListPref() == "hide") { ":not(:has(.badge:contains(SPOILER),.badge:contains(RAW),.badge:contains(VUS)))" } else { "" } + // JapScan sometimes uploads some "spoiler preview" chapters, containing 2 or 3 untranslated pictures taken from a raw. Sometimes they also upload full RAWs/US versions and replace them with a translation as soon as available. + // Those have a span.badge "SPOILER" or "RAW". The additional pseudo selector makes sure to exclude these from the chapter list. + + override fun chapterFromElement(element: Element): SChapter { + val urlElement = element.selectFirst("a")!! + + val chapter = SChapter.create() + chapter.setUrlWithoutDomain(urlElement.attr("href")) + chapter.name = urlElement.ownText() + // Using ownText() doesn't include childs' text, like "VUS" or "RAW" badges, in the chapter name. + chapter.date_upload = element.selectFirst("span")!!.text().trim().let { parseChapterDate(it) } + return chapter + } + + private fun parseChapterDate(date: String) = runCatching { + dateFormat.parse(date)!!.time + }.getOrDefault(0L) + + @SuppressLint("SetJavaScriptEnabled") + override fun pageListParse(document: Document): List { + val interfaceName = randomString() + val zjsElement = document.selectFirst("script[src*=/zjs/]") + ?: throw Exception("ZJS not found") + val dataElement = document.selectFirst("#data") + ?: throw Exception("Chapter data not found") + val minDoc = Document.createShell(document.location()) + val minDocBody = minDoc.body() + + minDocBody.appendChild(dataElement) + minDocBody.append( + """ + + """.trimIndent(), + ) + minDocBody.appendChild(zjsElement) + + val handler = Handler(Looper.getMainLooper()) + val latch = CountDownLatch(1) + val jsInterface = JsInterface(latch) + var webView: WebView? = null + + handler.post { + val innerWv = WebView(Injekt.get()) + + webView = innerWv + innerWv.settings.javaScriptEnabled = true + innerWv.settings.blockNetworkImage = true + innerWv.setLayerType(View.LAYER_TYPE_SOFTWARE, null) + innerWv.addJavascriptInterface(jsInterface, interfaceName) + + innerWv.loadDataWithBaseURL( + document.location(), + minDoc.outerHtml(), + "text/html", + "UTF-8", + null, + ) + } + + latch.await(5, TimeUnit.SECONDS) + handler.post { webView?.destroy() } + + if (latch.count == 1L) { + throw Exception("Timed out decrypting image links") + } + + val baseUrlHost = baseUrl.toHttpUrl().host + + return jsInterface + .images + .filterNot { it.toHttpUrl().host == baseUrlHost } // Pages not served through their CDN are probably ads + .mapIndexed { i, url -> + Page(i, imageUrl = url) + } + } + + override fun imageUrlParse(document: Document): String = "" + + // Filters + private class TextField(name: String) : Filter.Text(name) + + private class PageList(pages: Array) : Filter.Select("Page #", arrayOf(0, *pages)) + + override fun getFilterList(): FilterList { + val totalPages = pageNumberDoc?.select("li.page-item:last-child a")?.text() + val pageList = mutableListOf() + return if (!totalPages.isNullOrEmpty()) { + for (i in 0 until totalPages.toInt()) { + pageList.add(i + 1) + } + FilterList( + Filter.Header("Page alphabétique"), + PageList(pageList.toTypedArray()), + ) + } else { + FilterList( + Filter.Header("Page alphabétique"), + TextField("Page #"), + Filter.Header("Appuyez sur reset pour la liste"), + ) + } + } + + private var pageNumberDoc: Document? = null + + // Prefs + override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) { + val chapterListPref = androidx.preference.ListPreference(screen.context).apply { + key = SHOW_SPOILER_CHAPTERS_Title + title = SHOW_SPOILER_CHAPTERS_Title + entries = prefsEntries + entryValues = prefsEntryValues + summary = "%s" + + setOnPreferenceChangeListener { _, newValue -> + val selected = newValue as String + val index = this.findIndexOfValue(selected) + val entry = entryValues[index] as String + preferences.edit().putString(SHOW_SPOILER_CHAPTERS, entry).commit() + } + } + screen.addPreference(chapterListPref) + } + + private fun randomString(length: Int = 10): String { + val charPool = ('a'..'z') + ('A'..'Z') + return List(length) { charPool.random() }.joinToString("") + } + + internal class JsInterface(private val latch: CountDownLatch) { + private val json: Json by injectLazy() + + var images: List = listOf() + private set + + @JavascriptInterface + @Suppress("UNUSED") + fun passPayload(rawData: String) { + val data = json.parseToJsonElement(rawData).jsonObject + + images = data["imagesLink"]!!.jsonArray.map { it.jsonPrimitive.content } + latch.countDown() + } + } +}