From b26afd2269ddaf7285af8b7a8ea3a51f7c02daf4 Mon Sep 17 00:00:00 2001 From: AwkwardPeak7 <48650614+AwkwardPeak7@users.noreply.github.com> Date: Fri, 19 Jan 2024 15:14:33 +0500 Subject: [PATCH] OPSCANS: rewrite for new site (#343) * OpScans: rewrite for new site * remove from MangaThemesiaGenerator * chapter order and webview urls * mangaid and chapter id to find chapter --- .../opscans/res/web_hi_res_512.png | Bin 26032 -> 0 bytes .../mangathemesia/MangaThemesiaGenerator.kt | 1 - src/en/opscans/AndroidManifest.xml | 2 + src/en/opscans/build.gradle | 11 ++ .../opscans/res/mipmap-hdpi/ic_launcher.png | Bin .../opscans/res/mipmap-mdpi/ic_launcher.png | Bin .../opscans/res/mipmap-xhdpi/ic_launcher.png | Bin .../opscans/res/mipmap-xxhdpi/ic_launcher.png | Bin .../res/mipmap-xxxhdpi/ic_launcher.png | Bin .../tachiyomi/extension/en/opscans/OpScans.kt | 181 ++++++++++++++++++ .../extension/en/opscans/OpScansDto.kt | 46 +++++ 11 files changed, 240 insertions(+), 1 deletion(-) delete mode 100644 multisrc/overrides/mangathemesia/opscans/res/web_hi_res_512.png create mode 100644 src/en/opscans/AndroidManifest.xml create mode 100644 src/en/opscans/build.gradle rename {multisrc/overrides/mangathemesia => src/en}/opscans/res/mipmap-hdpi/ic_launcher.png (100%) rename {multisrc/overrides/mangathemesia => src/en}/opscans/res/mipmap-mdpi/ic_launcher.png (100%) rename {multisrc/overrides/mangathemesia => src/en}/opscans/res/mipmap-xhdpi/ic_launcher.png (100%) rename {multisrc/overrides/mangathemesia => src/en}/opscans/res/mipmap-xxhdpi/ic_launcher.png (100%) rename {multisrc/overrides/mangathemesia => src/en}/opscans/res/mipmap-xxxhdpi/ic_launcher.png (100%) create mode 100644 src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScans.kt create mode 100644 src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScansDto.kt diff --git a/multisrc/overrides/mangathemesia/opscans/res/web_hi_res_512.png b/multisrc/overrides/mangathemesia/opscans/res/web_hi_res_512.png deleted file mode 100644 index c4e354264afcff9d2cd2d3abdbd18cc1687d3238..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26032 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�KA8h&{W} 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 + diff --git a/src/en/opscans/build.gradle b/src/en/opscans/build.gradle new file mode 100644 index 000000000..0746c85eb --- /dev/null +++ b/src/en/opscans/build.gradle @@ -0,0 +1,11 @@ +ext { + extName = 'OPSCANS' + extClass = '.OpScans' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" + +dependencies { + implementation(project(":lib:dataimage")) +} diff --git a/multisrc/overrides/mangathemesia/opscans/res/mipmap-hdpi/ic_launcher.png b/src/en/opscans/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from multisrc/overrides/mangathemesia/opscans/res/mipmap-hdpi/ic_launcher.png rename to src/en/opscans/res/mipmap-hdpi/ic_launcher.png diff --git a/multisrc/overrides/mangathemesia/opscans/res/mipmap-mdpi/ic_launcher.png b/src/en/opscans/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from multisrc/overrides/mangathemesia/opscans/res/mipmap-mdpi/ic_launcher.png rename to src/en/opscans/res/mipmap-mdpi/ic_launcher.png diff --git a/multisrc/overrides/mangathemesia/opscans/res/mipmap-xhdpi/ic_launcher.png b/src/en/opscans/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from multisrc/overrides/mangathemesia/opscans/res/mipmap-xhdpi/ic_launcher.png rename to src/en/opscans/res/mipmap-xhdpi/ic_launcher.png diff --git a/multisrc/overrides/mangathemesia/opscans/res/mipmap-xxhdpi/ic_launcher.png b/src/en/opscans/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from multisrc/overrides/mangathemesia/opscans/res/mipmap-xxhdpi/ic_launcher.png rename to src/en/opscans/res/mipmap-xxhdpi/ic_launcher.png diff --git a/multisrc/overrides/mangathemesia/opscans/res/mipmap-xxxhdpi/ic_launcher.png b/src/en/opscans/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from multisrc/overrides/mangathemesia/opscans/res/mipmap-xxxhdpi/ic_launcher.png rename to src/en/opscans/res/mipmap-xxxhdpi/ic_launcher.png diff --git a/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScans.kt b/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScans.kt new file mode 100644 index 000000000..55fb9cc1b --- /dev/null +++ b/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScans.kt @@ -0,0 +1,181 @@ +package eu.kanade.tachiyomi.extension.en.opscans + +import eu.kanade.tachiyomi.lib.dataimage.DataImageInterceptor +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.decodeFromString +import kotlinx.serialization.json.Json +import okhttp3.Headers +import okhttp3.Interceptor +import okhttp3.MultipartBody +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import okhttp3.Response +import uy.kohesive.injekt.injectLazy +import java.lang.UnsupportedOperationException +import java.text.SimpleDateFormat +import java.util.Locale + +class OpScans : HttpSource() { + + override val name = "OPSCANS" + + override val lang = "en" + + override val baseUrl = "https://opchapters.com" + + private val apiUrl = "https://opscanlations.com" + + override val supportsLatest = false + + private val json: Json by injectLazy() + + override val versionId = 2 + + override val client = network.cloudflareClient.newBuilder() + .addInterceptor(::imageInterceptor) + .addInterceptor(DataImageInterceptor()) + .build() + + override fun headersBuilder() = super.headersBuilder() + .set("Referer", "$baseUrl/") + + override fun popularMangaRequest(page: Int): Request { + return GET("$apiUrl/api/mangaData", headers) + } + + override fun popularMangaParse(response: Response): MangasPage { + val mangaData = response.parseAs>() + + return MangasPage( + mangaData.map { it.toSManga() }, + false, + ) + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + return GET("$apiUrl/api/mangaData#${query.trim()}", headers) + } + + override fun searchMangaParse(response: Response): MangasPage { + val mangaData = response.parseAs>() + val query = response.request.url.fragment!! + + return MangasPage( + mangaData.filter { + it.name.contains(query, true) || + it.author.contains(query, true) || + it.info.contains(query, true) + }.map { it.toSManga() }, + false, + ) + } + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET("$apiUrl/api/mangaData#${manga.url}", headers) + } + + override fun getMangaUrl(manga: SManga) = "$baseUrl/${manga.url}" + + override fun mangaDetailsParse(response: Response): SManga { + val mangaData = response.parseAs>() + val mangaId = response.request.url.fragment!! + + return mangaData.firstOrNull { it.id == mangaId }!!.toSManga() + } + + override fun chapterListRequest(manga: SManga) = mangaDetailsRequest(manga) + + override fun getChapterUrl(chapter: SChapter) = "$baseUrl${chapter.url}" + + override fun chapterListParse(response: Response): List { + val mangaData = response.parseAs>() + val mangaId = response.request.url.fragment!! + + return mangaData.firstOrNull { it.id == mangaId } + ?.chapters.orEmpty().map { + SChapter.create().apply { + url = "/$mangaId/${it.id}" + name = it.number + if (it.title.isNullOrEmpty()) "" else ": ${it.title}" + date_upload = runCatching { + dateFormat.parse(it.date!!)!!.time + }.getOrDefault(0L) + } + }.reversed() + } + + override fun pageListRequest(chapter: SChapter): Request { + return GET("$apiUrl/api/mangaData#${chapter.url}", headers) + } + + override fun pageListParse(response: Response): List { + val mangaData = response.parseAs>() + val ids = response.request.url.fragment!!.split("/") + val mangaId = ids[1] + val chapterId = ids[2] + + return mangaData.firstOrNull { it.id == mangaId } + ?.chapters?.firstOrNull { it.id == chapterId } + ?.images.orEmpty().mapIndexed { idx, img -> + Page(idx, "", "https://127.0.0.1/image#${img.source}") + } + } + + private fun imageInterceptor(chain: Interceptor.Chain): Response { + val request = chain.request() + val url = request.url + + if (url.pathSegments.lastOrNull() != "image" || url.fragment.isNullOrEmpty()) { + return chain.proceed(request) + } + + val image = url.fragment!! + + val boundary = buildString { + append((1..9).random()) + repeat(28) { + append((0..9).random()) + } + } + + val form = MultipartBody.Builder("-----------------------------$boundary").apply { + setType(MultipartBody.FORM) + addPart( + Headers.headersOf("Content-Disposition", "form-data; name=\"image\""), + image.toRequestBody(null), + ) + }.build() + + val response = client.newCall( + POST("$apiUrl/api/loadImages", headers, form), + ).execute().parseAs() + + val newUrl = "https://127.0.0.1/?${response.image.substringAfter(":")}" + + return chain.proceed( + request.newBuilder() + .url(newUrl) + .build(), + ) + } + + private inline fun Response.parseAs(): T = use { + json.decodeFromString(it.body.string()) + } + + companion object { + private val dateFormat by lazy { + SimpleDateFormat("MMM d, yyyy", Locale.ENGLISH) + } + } + + override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException() + override fun latestUpdatesParse(response: Response) = throw UnsupportedOperationException() + override fun imageUrlParse(response: Response) = throw UnsupportedOperationException() +} diff --git a/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScansDto.kt b/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScansDto.kt new file mode 100644 index 000000000..5feed9525 --- /dev/null +++ b/src/en/opscans/src/eu/kanade/tachiyomi/extension/en/opscans/OpScansDto.kt @@ -0,0 +1,46 @@ +package eu.kanade.tachiyomi.extension.en.opscans + +import eu.kanade.tachiyomi.source.model.SManga +import kotlinx.serialization.Serializable + +@Serializable +data class MangaData( + val id: String, + val name: String, + val author: String, + val info: String, + val genre1: String, + val genre2: String, + val genre3: String, + val cover: String, + val chapters: List, +) { + fun toSManga() = SManga.create().apply { + url = id + title = name + author = this@MangaData.author + description = info + genre = listOf(genre1, genre2, genre3).joinToString() + thumbnail_url = "https://127.0.0.1/image#$cover" + initialized = true + } +} + +@Serializable +data class Chapter( + val id: String, + val title: String? = "", + val date: String? = "", + val number: String, + val images: List? = emptyList(), +) + +@Serializable +data class Image( + val source: String, +) + +@Serializable +data class ImageResponse( + val image: String, +)