From 842225ad83388b8371e51f8c266a4a4b11f6f01a Mon Sep 17 00:00:00 2001 From: ObserverOfTime Date: Fri, 24 Dec 2021 14:59:43 +0200 Subject: [PATCH] Comico: new extension (#10210) --- src/all/comico/AndroidManifest.xml | 2 + src/all/comico/build.gradle | 13 + .../comico/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 2579 bytes .../comico/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 1744 bytes .../comico/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 3549 bytes .../comico/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 5556 bytes .../comico/res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 7657 bytes src/all/comico/res/web_hi_res_512.png | Bin 0 -> 28211 bytes .../tachiyomi/extension/all/comico/Comico.kt | 259 ++++++++++++++++++ .../extension/all/comico/ComicoFactory.kt | 19 ++ .../extension/all/comico/ComicoModels.kt | 75 +++++ 11 files changed, 368 insertions(+) create mode 100644 src/all/comico/AndroidManifest.xml create mode 100644 src/all/comico/build.gradle create mode 100644 src/all/comico/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/all/comico/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/all/comico/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/all/comico/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/all/comico/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/all/comico/res/web_hi_res_512.png create mode 100644 src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/Comico.kt create mode 100644 src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoFactory.kt create mode 100644 src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoModels.kt diff --git a/src/all/comico/AndroidManifest.xml b/src/all/comico/AndroidManifest.xml new file mode 100644 index 000000000..30deb7f79 --- /dev/null +++ b/src/all/comico/AndroidManifest.xml @@ -0,0 +1,2 @@ + + diff --git a/src/all/comico/build.gradle b/src/all/comico/build.gradle new file mode 100644 index 000000000..1e456374d --- /dev/null +++ b/src/all/comico/build.gradle @@ -0,0 +1,13 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlinx-serialization' + +ext { + extName = 'Comico' + pkgNameSuffix = 'all.comico' + extClass = '.ComicoFactory' + extVersionCode = 1 + isNsfw = true +} + +apply from: "$rootDir/common.gradle" diff --git a/src/all/comico/res/mipmap-hdpi/ic_launcher.png b/src/all/comico/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..c691fb27c90ebfff8ab7d84092737ac3637eeaf1 GIT binary patch literal 2579 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 literal 0 HcmV?d00001 diff --git a/src/all/comico/res/mipmap-mdpi/ic_launcher.png b/src/all/comico/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..a846eabc1183edd04cca8e27dcaf371d7e37aa29 GIT binary patch literal 1744 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 XSG~mOsoUl500000NkvXXu0mjfnIo&2 literal 0 HcmV?d00001 diff --git a/src/all/comico/res/mipmap-xxhdpi/ic_launcher.png b/src/all/comico/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..f592ec6278877cf140a3074f311b52f8fe573cf5 GIT binary patch literal 5556 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 RU<&S<;&WBma%t0m{{i0fQbqs( literal 0 HcmV?d00001 diff --git a/src/all/comico/res/web_hi_res_512.png b/src/all/comico/res/web_hi_res_512.png new file mode 100644 index 0000000000000000000000000000000000000000..4ead0a8521c07a0853358e5e7c44f96c345bfcf6 GIT binary patch literal 28211 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 W9zT<}4~Xy}=#2hZy<%Ob$o~PaeU-rg literal 0 HcmV?d00001 diff --git a/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/Comico.kt b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/Comico.kt new file mode 100644 index 000000000..784b5062b --- /dev/null +++ b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/Comico.kt @@ -0,0 +1,259 @@ +package eu.kanade.tachiyomi.extension.all.comico + +import android.webkit.CookieManager +import com.squareup.duktape.Duktape +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.POST +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 kotlinx.serialization.json.Json +import kotlinx.serialization.json.JsonElement +import kotlinx.serialization.json.boolean +import kotlinx.serialization.json.decodeFromJsonElement +import kotlinx.serialization.json.int +import kotlinx.serialization.json.jsonObject +import kotlinx.serialization.json.jsonPrimitive +import okhttp3.Cookie +import okhttp3.CookieJar +import okhttp3.FormBody +import okhttp3.Headers +import okhttp3.HttpUrl +import okhttp3.Response +import uy.kohesive.injekt.injectLazy +import java.security.MessageDigest +import java.text.SimpleDateFormat +import java.util.Calendar +import java.util.Locale + +open class Comico( + final override val baseUrl: String, + final override val name: String, + private val langCode: String +) : HttpSource() { + final override val supportsLatest = true + + override val lang = langCode.substring(0, 2) + + protected open val apiUrl = baseUrl.replace("www", "api") + + private val json by injectLazy() + + private val cookieManager by lazy { CookieManager.getInstance() } + + private val cryptoJs by lazy { + client.newCall(GET(CRYPTOJS)).execute().body!!.string() + } + + private val imgHeaders by lazy { + headersBuilder().set("Accept", ACCEPT_IMAGE).build() + } + + private val apiHeaders: Headers + get() = headersBuilder().apply { + val time = System.currentTimeMillis() / 1000L + this["X-comico-request-time"] = time.toString() + this["X-comico-check-sum"] = sha256(time) + this["X-comico-client-immutable-uid"] = ANON_IP + this["X-comico-client-accept-mature"] = "Y" + this["X-comico-client-platform"] = "web" + this["X-comico-client-store"] = "other" + this["X-comico-client-os"] = "aos" + this["Origin"] = baseUrl + }.build() + + override val client = network.client.newBuilder() + .cookieJar(object : CookieJar { + override fun saveFromResponse(url: HttpUrl, cookies: List) = + cookies.filter { it.matches(url) }.forEach { + cookieManager.setCookie(url.toString(), it.toString()) + } + + override fun loadForRequest(url: HttpUrl) = + cookieManager.getCookie(url.toString())?.split("; ") + ?.mapNotNull { Cookie.parse(url, it) } ?: emptyList() + }).build() + + override fun headersBuilder() = Headers.Builder() + .set("Accept-Language", langCode) + .set("User-Agent", userAgent) + .set("Referer", "$baseUrl/") + + override fun latestUpdatesRequest(page: Int) = + paginate("all_comic/daily/$day", page) + + override fun popularMangaRequest(page: Int) = + paginate("all_comic/ranking/trending", page) + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList) = + if (query.isEmpty()) paginate("all_comic/read_for_free", page) + else POST("$apiUrl/search", apiHeaders, search(query, page)) + + override fun chapterListRequest(manga: SManga) = + GET(apiUrl + manga.url + "/episode", apiHeaders) + + override fun pageListRequest(chapter: SChapter) = + GET(apiUrl + chapter.url, apiHeaders) + + override fun imageRequest(page: Page) = + GET(page.imageUrl!!.also { android.util.Log.w("URL", it) }, imgHeaders) + + override fun latestUpdatesParse(response: Response) = + popularMangaParse(response) + + override fun popularMangaParse(response: Response): MangasPage { + val data = response.data + val hasNext = data["page"]["hasNext"] + val mangas = data.map("contents") { + SManga.create().apply { + title = it.name + url = "/comic/${it.id}" + thumbnail_url = it.cover + description = it.description + status = when (it.status) { + "completed" -> SManga.COMPLETED + else -> SManga.ONGOING + } + author = it.authors.filter { it.isAuthor }.joinToString() + artist = it.authors.filter { it.isArtist }.joinToString() + genre = buildString { + it.genres.joinTo(this) + if (it.mature) append(", Mature") + if (it.original) append(", Original") + if (it.exclusive) append(", Exclusive") + } + } + } + return MangasPage(mangas, hasNext.jsonPrimitive.boolean) + } + + override fun searchMangaParse(response: Response) = + popularMangaParse(response) + + override fun chapterListParse(response: Response): List { + val content = response.data["episode"]["content"] + val id = content["id"].jsonPrimitive.int + return content.map("chapters") { + SChapter.create().apply { + chapter_number = it.id.toFloat() + url = "/comic/$id/chapter/${it.id}/product" + name = it.name + if (it.isAvailable) "" else LOCK + date_upload = dateFormat.parse(it.publishedAt)?.time ?: 0L + } + } + } + + override fun pageListParse(response: Response) = + response.data["chapter"].map("images") { + Page(it.sort, "", it.url.decrypt() + "?" + it.parameter) + } + + override fun fetchMangaDetails(manga: SManga) = + rx.Observable.just(manga.apply { initialized = true })!! + + override fun fetchPageList(chapter: SChapter) = + if (!chapter.name.endsWith(LOCK)) super.fetchPageList(chapter) + else throw Error("You are not authorized to view this!") + + private fun search(query: String, page: Int) = + FormBody.Builder().add("query", query) + .add("pageNo", (page - 1).toString()) + .add("pageSize", "25").build() + + private fun paginate(route: String, page: Int) = + GET("$apiUrl/$route?pageNo=${page - 1}&pageSize=25", apiHeaders) + + private fun String.decrypt() = Duktape.create().use { + // javax.crypto.Cipher does not support empty IV + val script = """ + const key = CryptoJS.enc.Utf8.parse('$AES_KEY'), iv = {words: []} + CryptoJS.AES.decrypt('$this', key, {iv}).toString(CryptoJS.enc.Utf8) + """ + it.evaluate(cryptoJs + script).toString() + } + + private val Response.data: JsonElement? + get() = json.parseToJsonElement(body!!.string()).jsonObject.also { + val code = it["result"]["code"].jsonPrimitive.int + if (code != 200) throw Error(status(code)) + }["data"] + + private operator fun JsonElement?.get(key: String) = + this!!.jsonObject[key]!! + + private inline fun JsonElement?.map( + key: String, + transform: (T) -> R + ) = json.decodeFromJsonElement>(this[key]).map(transform) + + override fun mangaDetailsParse(response: Response) = + throw UnsupportedOperationException("Not used") + + override fun imageUrlParse(response: Response) = + throw UnsupportedOperationException("Not used") + + companion object { + private const val ANON_IP = "0.0.0.0" + + private const val LOCK = " \uD83D\uDD12" + + private const val ISO_DATE = "yyyy-MM-dd'T'HH:mm:ss'Z'" + + private const val WEB_KEY = "9241d2f090d01716feac20ae08ba791a" + + private const val AES_KEY = "a7fc9dc89f2c873d79397f8a0028a4cd" + + private const val CRYPTOJS = + "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js" + + private const val ACCEPT_IMAGE = + "image/avif,image/jxl,image/webp,image/*,*/*" + + private val userAgent = System.getProperty("http.agent")!! + + private val dateFormat = SimpleDateFormat(ISO_DATE, Locale.ROOT) + + private val SHA256 = MessageDigest.getInstance("SHA-256") + + private val day by lazy { + when (Calendar.getInstance()[Calendar.DAY_OF_WEEK]) { + Calendar.SUNDAY -> "sunday" + Calendar.MONDAY -> "monday" + Calendar.TUESDAY -> "tuesday" + Calendar.WEDNESDAY -> "wednesday" + Calendar.THURSDAY -> "thursday" + Calendar.FRIDAY -> "friday" + Calendar.SATURDAY -> "saturday" + else -> "completed" + } + } + + fun sha256(timestamp: Long) = buildString(64) { + SHA256.digest((WEB_KEY + ANON_IP + timestamp).toByteArray()) + .joinTo(this, "") { "%02x".format(it) } + SHA256.reset() + } + + private fun status(code: Int) = when (code) { + 400 -> "Bad Request" + 401 -> "Unauthorized" + 402 -> "Payment Required" + 403 -> "Forbidden" + 404 -> "Not Found" + 408 -> "Request Timeout" + 409 -> "Conflict" + 410 -> "DormantAccount" + 417 -> "Expectation Failed" + 426 -> "Upgrade Required" + 428 -> "성인 on/off 권한" + 429 -> "Too Many Requests" + 500 -> "Internal Server Error" + 503 -> "Service Unavailable" + 451 -> "성인 인증" + else -> "Error $code" + } + } +} diff --git a/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoFactory.kt b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoFactory.kt new file mode 100644 index 000000000..a76b390ca --- /dev/null +++ b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoFactory.kt @@ -0,0 +1,19 @@ +package eu.kanade.tachiyomi.extension.all.comico + +import eu.kanade.tachiyomi.source.SourceFactory + +class ComicoFactory : SourceFactory { + open class PocketComics(langCode: String) : + Comico("https://www.pocketcomics.com", "POCKET COMICS", langCode) + + class ComicoJP : Comico("https://www.comico.jp", "コミコ", "ja-JP") + + class ComicoKR : Comico("https://www.comico.kr", "코미코", "ko-KR") + + override fun createSources() = listOf( + PocketComics("en-US"), + PocketComics("zh-TW"), + ComicoJP(), + ComicoKR() + ) +} diff --git a/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoModels.kt b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoModels.kt new file mode 100644 index 000000000..fe6032af9 --- /dev/null +++ b/src/all/comico/src/eu/kanade/tachiyomi/extension/all/comico/ComicoModels.kt @@ -0,0 +1,75 @@ +package eu.kanade.tachiyomi.extension.all.comico + +import kotlinx.serialization.Serializable + +@Serializable +data class ContentInfo( + val id: Int, + val name: String, + val description: String, + val authors: List, + val genres: List, + val original: Boolean, + val exclusive: Boolean, + val mature: Boolean, + val status: String? = null, + private val thumbnails: List, +) { + val cover: String + get() = thumbnails[0].toString() +} + +@Serializable +data class Thumbnail(private val url: String) { + override fun toString() = url +} + +@Serializable +data class Author(private val name: String, private val role: String) { + val isAuthor: Boolean + get() = role == "creator" || + role == "writer" || + role == "original_creator" + + val isArtist: Boolean + get() = role == "creator" || + role == "artist" || + role == "studio" || + role == "assistant" + + override fun toString() = name +} + +@Serializable +data class Genre(private val name: String) { + override fun toString() = name +} + +@Serializable +data class Chapter( + val id: Int, + val name: String, + val publishedAt: String, + private val salesConfig: SalesConfig, + private val hasTrial: Boolean, + private val activity: Activity +) { + val isAvailable: Boolean + get() = salesConfig.free || hasTrial || activity.owned +} + +@Serializable +data class SalesConfig(val free: Boolean) + +@Serializable +data class Activity(val rented: Boolean, val unlocked: Boolean) { + inline val owned: Boolean + get() = rented || unlocked +} + +@Serializable +data class ChapterImage( + val sort: Int, + val url: String, + val parameter: String +)