From 84383a1601dab0369fbbc70eac6f0d2d858485ab Mon Sep 17 00:00:00 2001 From: are-are-are <62763969+dejavui@users.noreply.github.com> Date: Tue, 4 Nov 2025 21:59:12 +0700 Subject: [PATCH] Add OTruyen (#11414) --- src/vi/otruyen/build.gradle | 7 + .../otruyen/res/mipmap-hdpi/ic_launcher.png | Bin 0 -> 4053 bytes .../otruyen/res/mipmap-mdpi/ic_launcher.png | Bin 0 -> 2227 bytes .../otruyen/res/mipmap-xhdpi/ic_launcher.png | Bin 0 -> 5857 bytes .../otruyen/res/mipmap-xxhdpi/ic_launcher.png | Bin 0 -> 11415 bytes .../res/mipmap-xxxhdpi/ic_launcher.png | Bin 0 -> 19307 bytes .../tachiyomi/extension/vi/otruyen/Dto.kt | 153 +++++++++++++ .../tachiyomi/extension/vi/otruyen/OTruyen.kt | 209 ++++++++++++++++++ 8 files changed, 369 insertions(+) create mode 100644 src/vi/otruyen/build.gradle create mode 100644 src/vi/otruyen/res/mipmap-hdpi/ic_launcher.png create mode 100644 src/vi/otruyen/res/mipmap-mdpi/ic_launcher.png create mode 100644 src/vi/otruyen/res/mipmap-xhdpi/ic_launcher.png create mode 100644 src/vi/otruyen/res/mipmap-xxhdpi/ic_launcher.png create mode 100644 src/vi/otruyen/res/mipmap-xxxhdpi/ic_launcher.png create mode 100644 src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/Dto.kt create mode 100644 src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/OTruyen.kt diff --git a/src/vi/otruyen/build.gradle b/src/vi/otruyen/build.gradle new file mode 100644 index 000000000..61be3e4da --- /dev/null +++ b/src/vi/otruyen/build.gradle @@ -0,0 +1,7 @@ +ext { + extName = 'OTruyen' + extClass = '.OTruyen' + extVersionCode = 1 +} + +apply from: "$rootDir/common.gradle" diff --git a/src/vi/otruyen/res/mipmap-hdpi/ic_launcher.png b/src/vi/otruyen/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..8fb3883ec30ceb40f3ca8a9162a7294b3d65476f GIT binary patch literal 4053 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 literal 0 HcmV?d00001 diff --git a/src/vi/otruyen/res/mipmap-xxhdpi/ic_launcher.png b/src/vi/otruyen/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..da435ac14b5a43bd5654b801b256b0a3c5df9dff GIT binary patch literal 11415 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 literal 0 HcmV?d00001 diff --git a/src/vi/otruyen/res/mipmap-xxxhdpi/ic_launcher.png b/src/vi/otruyen/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 0000000000000000000000000000000000000000..b70496656d4fe717fe0d6d42e9367d528d98719b GIT binary patch literal 19307 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 P5n#KA*H5|b@R>gWK7Q7> literal 0 HcmV?d00001 diff --git a/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/Dto.kt b/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/Dto.kt new file mode 100644 index 000000000..7ce799d1a --- /dev/null +++ b/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/Dto.kt @@ -0,0 +1,153 @@ +package eu.kanade.tachiyomi.extension.vi.otruyen + +import eu.kanade.tachiyomi.source.model.Page +import eu.kanade.tachiyomi.source.model.SChapter +import eu.kanade.tachiyomi.source.model.SManga +import keiyoushi.utils.tryParse +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable +import org.jsoup.Jsoup +import java.text.SimpleDateFormat +import java.util.Locale +import kotlin.collections.mapIndexed + +@Serializable +class DataDto( + val data: T, +) + +@Serializable +class ListingData( + val items: List, + val params: ParamsListing, +) + +@Serializable +class ParamsListing( + val pagination: Pagination, +) + +@Serializable +class Pagination( + val totalItems: Int, + val totalItemsPerPage: Int, + val currentPage: Int, +) + +@Serializable +class EntriesData( + private val name: String, + private val slug: String, + @SerialName("thumb_url") private val thumbUrl: String?, + private val category: List = emptyList(), + +) { + fun toSManga(imgUrl: String): SManga = SManga.create().apply { + url = slug + title = name + thumbnail_url = thumbUrl?.let { "$imgUrl/$it" } + genre = category.joinToString { it.name } + } +} + +@Serializable +class Category( + val name: String, +) + +@Serializable +class EntryData( + val item: Entry, +) + +@Serializable +class Entry( + private val name: String, + val slug: String, + @SerialName("origin_name") private val originName: List, + private val content: String, + private val status: String, + @SerialName("thumb_url") private val thumbUrl: String?, + private val author: List, + private val category: List, + val chapters: List, + val updatedAt: String, +) { + fun toSManga(imgUrl: String): SManga = SManga.create().apply { + val entry = this@Entry + author = entry.author.joinToString() + val altNames = originName.filter { it.isNotBlank() } + val descText = Jsoup.parse(content).select("p").joinToString("\n") { it.wholeText() } + description = buildString { + if (altNames.isNotEmpty()) { + append("Tên khác: ${altNames.joinToString()}\n\n") + } + append(descText) + } + genre = category.joinToString { it.name } + title = name + thumbnail_url = thumbUrl?.let { "$imgUrl/$it" } + status = when (entry.status) { + "ongoing" -> SManga.ONGOING + "completed" -> SManga.COMPLETED + "coming_soon" -> SManga.ONGOING + else -> SManga.UNKNOWN + } + } +} + +@Serializable +class ChapterDto( + @SerialName("server_data") val serverData: List, +) + +@Serializable +class ChapterData( + @SerialName("chapter_name") private val chapterName: String, + @SerialName("chapter_title") private val chapterTitle: String? = null, + @SerialName("chapter_api_data") private val chapterApiData: String, +) { + fun toSChapter(date: String, mangaUrl: String): SChapter = SChapter.create().apply { + val chapterId = chapterApiData.substringAfterLast("/") + name = "Chapter " + chapterName + (chapterTitle?.let { " : $it" } ?: "") + date_upload = dateFormat.tryParse(date) // API has no date for chapter → temporarily use updatedAt of entry + chapter_number = chapterName.toFloatOrNull() ?: 0f + url = "$chapterId:$mangaUrl" + } +} + +@Serializable +class PageDto( + @SerialName("domain_cdn") val domainCdn: String, + private val item: PageItem, +) { + fun toPage(): List { + val url = "$domainCdn/${item.chapterPath}/" + return item.chapterImage.mapIndexed { index, image -> + Page(index, imageUrl = url + image.imageFile) + } + } +} + +@Serializable +class PageItem( + @SerialName("chapter_path") val chapterPath: String, + @SerialName("chapter_image") val chapterImage: List, +) + +@Serializable +class PageImage( + @SerialName("image_file") val imageFile: String, +) + +@Serializable +class GenresData( + val items: List, +) + +@Serializable +class GenreItem( + val slug: String, + val name: String, +) +private val dateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.ROOT) diff --git a/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/OTruyen.kt b/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/OTruyen.kt new file mode 100644 index 000000000..d71f840fc --- /dev/null +++ b/src/vi/otruyen/src/eu/kanade/tachiyomi/extension/vi/otruyen/OTruyen.kt @@ -0,0 +1,209 @@ +package eu.kanade.tachiyomi.extension.vi.otruyen + +import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.await +import eu.kanade.tachiyomi.network.interceptor.rateLimit +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 +import eu.kanade.tachiyomi.source.online.HttpSource +import keiyoushi.utils.parseAs +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.SupervisorJob +import kotlinx.coroutines.launch +import okhttp3.Headers +import okhttp3.HttpUrl.Companion.toHttpUrl +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import kotlin.collections.flatMap +import kotlin.collections.map + +class OTruyen : HttpSource() { + + override val name: String = "OTruyen" + + override val lang: String = "vi" + + override val supportsLatest: Boolean = true + + private val domainName = "otruyen" + + override val baseUrl: String = "https://$domainName.cc" + + private val domainApi = "${domainName}api.com" + + private val apiUrl = "https://$domainApi/v1/api" + + private val cdnUrl = "https://sv1.${domainName}cdn.com" + + private val imgUrl = "https://img.$domainApi/uploads/comics" + + override val client: OkHttpClient = network.cloudflareClient.newBuilder() + .rateLimit(3) + .build() + + override fun headersBuilder(): Headers.Builder = super.headersBuilder() + .add("Referer", "$baseUrl/") + + override fun latestUpdatesRequest(page: Int): Request { + return GET("$apiUrl/danh-sach/truyen-moi?page=$page", headers) + } + + override fun latestUpdatesParse(response: Response): MangasPage { + val res = response.parseAs>() + val pagination = res.data.params.pagination + val totalPages = (pagination.totalItems + pagination.totalItemsPerPage - 1) / pagination.totalItemsPerPage + val manga = res.data.items.map { it.toSManga(imgUrl) } + val hasNextPage = pagination.currentPage < totalPages + return MangasPage(manga, hasNextPage) + } + + override fun popularMangaRequest(page: Int): Request { + return GET("$apiUrl/danh-sach/hoan-thanh?page=$page", headers) + } + + override fun popularMangaParse(response: Response) = latestUpdatesParse(response) + + override fun mangaDetailsRequest(manga: SManga): Request { + return GET("$apiUrl/truyen-tranh/${manga.url}", headers) + } + + override fun mangaDetailsParse(response: Response): SManga { + val res = response.parseAs>() + return res.data.item.toSManga(imgUrl) + } + + override fun getMangaUrl(manga: SManga): String { + return "$baseUrl/truyen-tranh/${manga.url}" + } + + override fun chapterListRequest(manga: SManga): Request { + return mangaDetailsRequest(manga) + } + + override fun chapterListParse(response: Response): List { + val res = response.parseAs>() + val mangaUrl = res.data.item.slug + val date = res.data.item.updatedAt + return res.data.item.chapters + .flatMap { server -> server.serverData.map { it.toSChapter(date, mangaUrl) } } + .sortedByDescending { it.chapter_number } + } + + override fun getChapterUrl(chapter: SChapter): String { + val mangaUrl = chapter.url.substringAfter(":") + return "$baseUrl/truyen-tranh/$mangaUrl" + } + + override fun imageUrlParse(response: Response): String = throw UnsupportedOperationException() + + override fun pageListRequest(chapter: SChapter): Request { + val chapterId = chapter.url.substringBefore(":") + return GET("$cdnUrl/v1/api/chapter/$chapterId", headers) + } + + override fun pageListParse(response: Response): List { + val res = response.parseAs>() + return res.data.toPage() + } + + override fun searchMangaParse(response: Response) = latestUpdatesParse(response) + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { + val (segments, params) = when { + query.isNotBlank() -> { + listOf("tim-kiem") to mapOf("keyword" to query) + } + filters.filterIsInstance().isNotEmpty() -> { + val genre = filters.filterIsInstance().first() + listOf("the-loai", genre.values[genre.state].slug) to emptyMap() + } + filters.filterIsInstance().isEmpty() -> { + val status = filters.filterIsInstance().first() + listOf("danh-sach", status.values[status.state].slug) to emptyMap() + } + else -> { + listOf("danh-sach", "dang-phat-hanh") to emptyMap() + } + } + + val url = apiUrl.toHttpUrl().newBuilder().apply { + segments.forEach { addPathSegment(it) } + addQueryParameter("page", "$page") + params.forEach { (k, v) -> addQueryParameter(k, v) } + }.build() + + return GET(url, headers) + } + + private fun genresRequest(): Request = GET("$apiUrl/the-loai", headers) + + private fun parseGenres(response: Response): List> { + return response.parseAs>().data.items.map { Pair(it.slug, it.name) } + } + + private var genreList: List> = emptyList() + + private var fetchGenresAttempts: Int = 0 + private fun fetchGenres() { + launchIO { + try { + client.newCall(genresRequest()).await() + .use { parseGenres(it) } + .takeIf { it.isNotEmpty() } + ?.also { genreList = it } + } catch (_: Exception) { + } finally { + fetchGenresAttempts++ + } + } + } + + private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO) + + private fun launchIO(block: suspend () -> Unit) = scope.launch { block() } + + private class GenreList(name: String, pairs: List>) : GenresFilter(name, pairs) + + private class StatusList : Filter.Select( + "Trạng thái", + arrayOf( + Genre("Mới nhất", "truyen-moi"), + Genre("Đang phát hành", "dang-phat-hanh"), + Genre("Hoàn thành", "hoan-thanh"), + Genre("Sắp ra mắt", "sap-ra-mat"), + ), + ) + + private open class GenresFilter(title: String, pairs: List>) : + Filter.Select( + title, + pairs.map { Genre(it.second, it.first) }.toTypedArray(), + ) + + private class Genre(val name: String, val slug: String) { + override fun toString() = name + } + + override fun getFilterList(): FilterList { + fetchGenres() + return if (genreList.isEmpty()) { + FilterList( + Filter.Header("Nhấn 'Làm mới' để hiển thị thể loại"), + Filter.Header("Hiển thị thể loại sẽ ẩn danh sách trạng thái vì không dùng chung được"), + Filter.Header("Không dùng chung được với tìm kiếm bằng tên"), + StatusList(), + ) + } else { + FilterList( + Filter.Header("Không dùng chung được với tìm kiếm bằng tên"), + GenreList("Thể loại", genreList), + ) + } + } +}