diff --git a/.run/A3MangaGenerator.run.xml b/.run/A3MangaGenerator.run.xml new file mode 100644 index 000000000..c72cdcdba --- /dev/null +++ b/.run/A3MangaGenerator.run.xml @@ -0,0 +1,11 @@ + + + + + diff --git a/multisrc/overrides/a3manga/a3manga/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/a3manga/a3manga/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..c232b90b3 Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/a3manga/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/a3manga/a3manga/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..c5422b58d Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/a3manga/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/a3manga/a3manga/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..720e67f3d Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/a3manga/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/a3manga/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..bf3ce20a6 Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/a3manga/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/a3manga/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..be7125539 Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/a3manga/res/web_hi_res_512.png b/multisrc/overrides/a3manga/a3manga/res/web_hi_res_512.png new file mode 100644 index 000000000..678499563 Binary files /dev/null and b/multisrc/overrides/a3manga/a3manga/res/web_hi_res_512.png differ diff --git a/multisrc/overrides/a3manga/default/AndroidManifest.xml b/multisrc/overrides/a3manga/default/AndroidManifest.xml new file mode 100644 index 000000000..9a92f3a79 --- /dev/null +++ b/multisrc/overrides/a3manga/default/AndroidManifest.xml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + diff --git a/multisrc/overrides/a3manga/ngonphong/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/a3manga/ngonphong/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..0c6c219ff Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/a3manga/ngonphong/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..1626ab78e Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..e897210d4 Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..8100eda75 Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..d5e88a2ac Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/res/web_hi_res_512.png b/multisrc/overrides/a3manga/ngonphong/res/web_hi_res_512.png new file mode 100644 index 000000000..6e3ea71cc Binary files /dev/null and b/multisrc/overrides/a3manga/ngonphong/res/web_hi_res_512.png differ diff --git a/multisrc/overrides/a3manga/ngonphong/src/NgonPhong.kt b/multisrc/overrides/a3manga/ngonphong/src/NgonPhong.kt new file mode 100644 index 000000000..95f2cfc0a --- /dev/null +++ b/multisrc/overrides/a3manga/ngonphong/src/NgonPhong.kt @@ -0,0 +1,7 @@ +package eu.kanade.tachiyomi.extension.vi.ngonphong + +import eu.kanade.tachiyomi.multisrc.a3manga.A3Manga + +class NgonPhong : A3Manga("Ngôn Phong", "https://www.ngonphong.com", "vi") { + override val id: Long = 7268977637085631557 +} diff --git a/multisrc/overrides/a3manga/ocumeo/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/a3manga/ocumeo/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..64de658f5 Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ocumeo/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/a3manga/ocumeo/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..a50fbf960 Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ocumeo/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..062e4bf96 Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..e180f6f6e Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..dec6ff00c Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/ocumeo/res/web_hi_res_512.png b/multisrc/overrides/a3manga/ocumeo/res/web_hi_res_512.png new file mode 100644 index 000000000..dfff10b7b Binary files /dev/null and b/multisrc/overrides/a3manga/ocumeo/res/web_hi_res_512.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-hdpi/ic_launcher.png b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-hdpi/ic_launcher.png new file mode 100644 index 000000000..e1d509058 Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-hdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-mdpi/ic_launcher.png b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-mdpi/ic_launcher.png new file mode 100644 index 000000000..c7411cfca Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-mdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xhdpi/ic_launcher.png b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xhdpi/ic_launcher.png new file mode 100644 index 000000000..a123f228c Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxhdpi/ic_launcher.png new file mode 100644 index 000000000..b507ebb5d Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxxhdpi/ic_launcher.png b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxxhdpi/ic_launcher.png new file mode 100644 index 000000000..70102554b Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/mipmap-xxxhdpi/ic_launcher.png differ diff --git a/multisrc/overrides/a3manga/teamlanhlung/res/web_hi_res_512.png b/multisrc/overrides/a3manga/teamlanhlung/res/web_hi_res_512.png new file mode 100644 index 000000000..bc89f156a Binary files /dev/null and b/multisrc/overrides/a3manga/teamlanhlung/res/web_hi_res_512.png differ diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt new file mode 100644 index 000000000..512bf63b9 --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3Manga.kt @@ -0,0 +1,207 @@ +package eu.kanade.tachiyomi.multisrc.a3manga + +import android.util.Base64 +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.ParsedHttpSource +import kotlinx.serialization.decodeFromString +import kotlinx.serialization.json.Json +import okhttp3.FormBody +import okhttp3.Headers +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.Response +import org.jsoup.Jsoup +import org.jsoup.nodes.Document +import org.jsoup.nodes.Element +import rx.Observable +import uy.kohesive.injekt.injectLazy +import java.text.SimpleDateFormat +import java.util.Locale +import java.util.TimeZone +import javax.crypto.Cipher +import javax.crypto.SecretKeyFactory +import javax.crypto.spec.IvParameterSpec +import javax.crypto.spec.PBEKeySpec +import javax.crypto.spec.SecretKeySpec + +open class A3Manga( + override val name: String, + override val baseUrl: String, + override val lang: String, +) : ParsedHttpSource() { + + override val supportsLatest: Boolean = false + + override val client: OkHttpClient = network.cloudflareClient + + private val json: Json by injectLazy() + + override fun headersBuilder(): Headers.Builder = super.headersBuilder().add("Referer", "$baseUrl/") + + override fun popularMangaRequest(page: Int): Request = GET("$baseUrl/page/$page/", headers) + + override fun popularMangaSelector() = ".comic-list .comic-item" + + override fun popularMangaFromElement(element: Element) = SManga.create().apply { + setUrlWithoutDomain(element.select(".comic-title-link a").attr("href")) + title = element.select(".comic-title").text().trim() + thumbnail_url = element.select(".img-thumbnail").attr("abs:src") + } + + override fun popularMangaNextPageSelector() = "li.next:not(.disabled)" + + override fun latestUpdatesRequest(page: Int) = throw UnsupportedOperationException("Not used") + + override fun latestUpdatesSelector() = throw UnsupportedOperationException("Not used") + + override fun latestUpdatesFromElement(element: Element) = throw UnsupportedOperationException("Not used") + + override fun latestUpdatesNextPageSelector() = throw UnsupportedOperationException("Not used") + + override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable { + return when { + query.startsWith(PREFIX_ID_SEARCH) -> { + val id = query.removePrefix(PREFIX_ID_SEARCH).trim() + fetchMangaDetails( + SManga.create().apply { + url = "/truyen-tranh/$id/" + } + ) + .map { + it.url = "/truyen-tranh/$id/" + MangasPage(listOf(it), false) + } + } + else -> super.fetchSearchManga(page, query, filters) + } + } + + override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request = + POST( + "$baseUrl/wp-admin/admin-ajax.php", + headers, + FormBody.Builder() + .add("action", "searchtax") + .add("keyword", query) + .build(), + ) + + override fun searchMangaSelector(): String = throw UnsupportedOperationException("Not used") + + override fun searchMangaFromElement(element: Element): SManga = throw UnsupportedOperationException("Not used") + + override fun searchMangaNextPageSelector() = throw UnsupportedOperationException("Not used") + + override fun searchMangaParse(response: Response): MangasPage { + val dto = response.parseAs() + + if (!dto.success) { + return MangasPage(emptyList(), false) + } + + val manga = dto.data + .filter { it.cstatus != "Nhóm dịch" } + .map { + SManga.create().apply { + setUrlWithoutDomain(it.link) + title = it.title + thumbnail_url = it.img + } + } + + return MangasPage(manga, false) + } + + override fun mangaDetailsParse(document: Document) = SManga.create().apply { + title = document.select(".info-title").text() + author = document.select(".comic-info strong:contains(Tác giả) + span").text().trim() + description = document.select(".intro-container .text-justify").text().substringBefore("— Xem Thêm —") + genre = document.select(".comic-info .tags a").joinToString { tag -> + tag.text().split(' ').joinToString(separator = " ") { word -> + word.replaceFirstChar { it.titlecase() } + } + } + thumbnail_url = document.select(".img-thumbnail").attr("abs:src") + + val statusString = document.select(".comic-info strong:contains(Tình trạng) + span").text() + status = when (statusString) { + "Đang tiến hành" -> SManga.ONGOING + "Trọn bộ " -> SManga.COMPLETED + else -> SManga.UNKNOWN + } + } + + override fun chapterListSelector(): String = ".chapter-table table tbody tr" + + override fun chapterFromElement(element: Element) = SChapter.create().apply { + setUrlWithoutDomain(element.select("a").attr("href")) + name = element.select("a .hidden-sm").text() + date_upload = kotlin.runCatching { + dateFormat.parse(element.select("td").last().text())?.time + }.getOrNull() ?: 0L + } + + override fun pageListParse(document: Document): List { + val htmlContentScript = document.selectFirst("script:containsData(htmlContent)")?.html() + ?.substringAfter("var htmlContent=\"") + ?.substringBefore("\";") + ?.replace("\\\"", "\"") + ?.replace("\\\\", "\\") + ?.replace("\\/", "/") + ?: throw Exception("Couldn't find script with image data.") + val htmlContent = json.decodeFromString(htmlContentScript) + val ciphertext = Base64.decode(htmlContent.ciphertext, Base64.DEFAULT) + val iv = htmlContent.iv.decodeHex() + val salt = htmlContent.salt.decodeHex() + + val passwordScript = document.selectFirst("script:containsData(chapterHTML)")?.html() + ?: throw Exception("Couldn't find password to decrypt image data.") + val passphrase = passwordScript.substringAfter("var chapterHTML=CryptoJSAesDecrypt('") + .substringBefore("',htmlContent") + .replace("'+'", "") + + val keyFactory = SecretKeyFactory.getInstance(KEY_ALGORITHM) + val spec = PBEKeySpec(passphrase.toCharArray(), salt, 999, 256) + val keyS = SecretKeySpec(keyFactory.generateSecret(spec).encoded, "AES") + + val cipher = Cipher.getInstance(CIPHER_TRANSFORMATION) + cipher.init(Cipher.DECRYPT_MODE, keyS, IvParameterSpec(iv)) + + val imgListHtml = cipher.doFinal(ciphertext).toString(Charsets.UTF_8) + + return Jsoup.parseBodyFragment(imgListHtml).select("img").mapIndexed { idx, it -> + Page(idx, imageUrl = it.attr("abs:src")) + } + } + + override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used") + + private inline fun Response.parseAs(): T { + return json.decodeFromString(body?.string().orEmpty()) + } + + // https://stackoverflow.com/a/66614516 + private fun String.decodeHex(): ByteArray { + check(length % 2 == 0) { "Must have an even length" } + + return chunked(2) + .map { it.toInt(16).toByte() } + .toByteArray() + } + + companion object { + const val KEY_ALGORITHM = "PBKDF2WithHmacSHA512" + const val CIPHER_TRANSFORMATION = "AES/CBC/PKCS7PADDING" + + const val PREFIX_ID_SEARCH = "id:" + val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.US).apply { + timeZone = TimeZone.getTimeZone("Asia/Ho_Chi_Minh") + } + } +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaDto.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaDto.kt new file mode 100644 index 000000000..1f8000df3 --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaDto.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.multisrc.a3manga + +import kotlinx.serialization.Serializable + +@Serializable +data class SearchResponseDto( + val data: List, + val success: Boolean, +) + +@Serializable +data class SearchEntryDto( + val cstatus: String, + val img: String, + val isocm: Int, + val link: String, + val star: Float, + val title: String, + val vote: String, +) + +@Serializable +data class CipherDto( + val ciphertext: String, + val iv: String, + val salt: String, +) diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt new file mode 100644 index 000000000..9a0500766 --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaGenerator.kt @@ -0,0 +1,27 @@ +package eu.kanade.tachiyomi.multisrc.a3manga + +import generator.ThemeSourceData.SingleLang +import generator.ThemeSourceGenerator + +class A3MangaGenerator : ThemeSourceGenerator { + + override val themePkg = "a3manga" + + override val themeClass = "A3Manga" + + override val baseVersionCode: Int = 1 + + override val sources = listOf( + SingleLang("A3 Manga", "https://www.a3mnga.com", "vi"), + SingleLang("Team Lanh Lung", "https://teamlanhlung.com", "vi", sourceName = "Team Lạnh Lùng"), + SingleLang("Ngon Phong", "https://www.ngonphong.com", "vi", sourceName = "Ngôn Phong", overrideVersionCode = 1), + SingleLang("O Cu Meo", "https://www.ocumeo.com", "vi", sourceName = "Ổ Cú Mèo"), + ) + + companion object { + @JvmStatic + fun main(args: Array) { + A3MangaGenerator().createAll() + } + } +} diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaUrlActivity.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaUrlActivity.kt new file mode 100644 index 000000000..936a2d15f --- /dev/null +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/a3manga/A3MangaUrlActivity.kt @@ -0,0 +1,37 @@ +package eu.kanade.tachiyomi.multisrc.a3manga + +import android.app.Activity +import android.content.ActivityNotFoundException +import android.content.Intent +import android.os.Bundle +import android.util.Log +import kotlin.system.exitProcess + +/* + Springboard that accepts https:///truyen-tranh/$id/ intents + */ +class A3MangaUrlActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + val pathSegments = intent?.data?.pathSegments + if (pathSegments != null && pathSegments.size > 1) { + val id = pathSegments[1] + try { + startActivity( + Intent().apply { + action = "eu.kanade.tachiyomi.SEARCH" + putExtra("query", "id:$id") + putExtra("filter", packageName) + } + ) + } catch (e: ActivityNotFoundException) { + Log.e("A3MangaThemeUrlActivity", e.toString()) + } + } else { + Log.e("A3MangaThemeUrlActivity", "Could not parse URI from intent $intent") + } + + finish() + exitProcess(0) + } +} diff --git a/src/vi/ngonphong/AndroidManifest.xml b/src/vi/ngonphong/AndroidManifest.xml deleted file mode 100644 index 30deb7f79..000000000 --- a/src/vi/ngonphong/AndroidManifest.xml +++ /dev/null @@ -1,2 +0,0 @@ - - diff --git a/src/vi/ngonphong/build.gradle b/src/vi/ngonphong/build.gradle deleted file mode 100644 index d858067a8..000000000 --- a/src/vi/ngonphong/build.gradle +++ /dev/null @@ -1,11 +0,0 @@ -apply plugin: 'com.android.application' -apply plugin: 'kotlin-android' - -ext { - extName = 'Ngon Phong' - pkgNameSuffix = 'vi.ngonphong' - extClass = '.NgonPhong' - extVersionCode = 1 -} - -apply from: "$rootDir/common.gradle" diff --git a/src/vi/ngonphong/res/mipmap-hdpi/ic_launcher.png b/src/vi/ngonphong/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index a73203efd..000000000 Binary files a/src/vi/ngonphong/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/src/vi/ngonphong/res/mipmap-mdpi/ic_launcher.png b/src/vi/ngonphong/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 18fd15859..000000000 Binary files a/src/vi/ngonphong/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/src/vi/ngonphong/res/mipmap-xhdpi/ic_launcher.png b/src/vi/ngonphong/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 5747009a8..000000000 Binary files a/src/vi/ngonphong/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/src/vi/ngonphong/res/mipmap-xxhdpi/ic_launcher.png b/src/vi/ngonphong/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index ce75efef7..000000000 Binary files a/src/vi/ngonphong/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/vi/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png b/src/vi/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 34f4ec9df..000000000 Binary files a/src/vi/ngonphong/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/src/vi/ngonphong/res/web_hi_res_512.png b/src/vi/ngonphong/res/web_hi_res_512.png deleted file mode 100644 index d4e9fee2e..000000000 Binary files a/src/vi/ngonphong/res/web_hi_res_512.png and /dev/null differ diff --git a/src/vi/ngonphong/src/eu/kanade/tachiyomi/extension/vi/ngonphong/NgonPhong.kt b/src/vi/ngonphong/src/eu/kanade/tachiyomi/extension/vi/ngonphong/NgonPhong.kt deleted file mode 100644 index c9777068d..000000000 --- a/src/vi/ngonphong/src/eu/kanade/tachiyomi/extension/vi/ngonphong/NgonPhong.kt +++ /dev/null @@ -1,137 +0,0 @@ -package eu.kanade.tachiyomi.extension.vi.ngonphong - -import eu.kanade.tachiyomi.network.GET -import eu.kanade.tachiyomi.source.model.FilterList -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.ParsedHttpSource -import okhttp3.Headers -import okhttp3.OkHttpClient -import okhttp3.Request -import org.jsoup.nodes.Document -import org.jsoup.nodes.Element -import java.text.SimpleDateFormat -import java.util.Locale - -class NgonPhong : ParsedHttpSource() { - - override val name = "Ngon Phong" - - override val baseUrl = "https://ngonphongcomics.com" - - override val lang = "vi" - - override val supportsLatest = true - - override val client: OkHttpClient = network.cloudflareClient - - override fun headersBuilder(): Headers.Builder = super.headersBuilder() - .add("Referer", baseUrl) - - // Popular - - override fun popularMangaRequest(page: Int): Request { - return GET("$baseUrl/danh-sach-truyen/?sort=view&trang=$page", headers) - } - - override fun popularMangaSelector() = "div.comic-item" - - override fun popularMangaFromElement(element: Element): SManga { - return SManga.create().apply { - element.select(".comic-title-link > a").let { - title = it.attr("title") ?: it.text() - setUrlWithoutDomain(it.attr("href")) - } - thumbnail_url = element.select("img.img-thumbnail").attr("abs:src") - } - } - - override fun popularMangaNextPageSelector() = "ul.phantrang li a[title=next]" - - // Latest - - override fun latestUpdatesRequest(page: Int): Request { - return GET("$baseUrl/danh-sach-truyen/?sort=latest&trang=$page", headers) - } - - override fun latestUpdatesSelector() = popularMangaSelector() - - override fun latestUpdatesFromElement(element: Element): SManga = popularMangaFromElement(element) - - override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector() - - // Search - - override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { - return GET("$baseUrl/?s=$query", headers) - } - - override fun searchMangaSelector() = "table.comic-list-table tbody tr" - - override fun searchMangaFromElement(element: Element): SManga { - return SManga.create().apply { - element.select("a").first().let { - title = it.text() - setUrlWithoutDomain(it.attr("href")) - } - } - } - - override fun searchMangaNextPageSelector(): String? = null - - // Details - - override fun mangaDetailsParse(document: Document): SManga { - return SManga.create().apply { - document.select("div.comic-intro div.row").let { info -> - title = info.select("h2").text() - author = info.select("span.green").text() - genre = info.select("strong:contains(Thể loại:) ~ a").joinToString { it.text() } - status = info.select("strong:contains(Tình trạng:) + span").text().toStatus() - thumbnail_url = info.select("img.img-thumbnail").attr("abs:src") - } - description = document.select("div.comic-intro div.row + div p").text() - } - } - - private fun String.toStatus() = when { - this.contains("Đang cập nhật", ignoreCase = true) -> SManga.ONGOING - this.contains("Hoàn thành", ignoreCase = true) -> SManga.COMPLETED - else -> SManga.UNKNOWN - } - - // Chapters - - override fun chapterListSelector() = "table.table tbody tr" - - override fun chapterFromElement(element: Element): SChapter { - return SChapter.create().apply { - element.select("a").let { - name = it.text() - setUrlWithoutDomain(it.attr("href")) - } - date_upload = element.select("td:nth-child(2)").text().toChapterDate() - } - } - - private fun String.toChapterDate(): Long { - return try { - SimpleDateFormat("dd/MM/yyyy", Locale.getDefault()).parse(this)?.time ?: 0L - } catch (_: Exception) { - 0L - } - } - - // Pages - - override fun pageListParse(document: Document): List { - return document.select("script:containsData(htmlContent)").first().data().substringAfter("htmlContent=[") - .substringBefore("];").replace(Regex("""["\\]"""), "").split(",") - .mapIndexed { i, image -> Page(i, "", image) } - } - - override fun imageUrlParse(document: Document): String = throw UnsupportedOperationException("Not used") - - override fun getFilterList() = FilterList() -}