parent
271c770af0
commit
b5e1e8686d
|
@ -0,0 +1,12 @@
|
|||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: HentaiVN'
|
||||
pkgNameSuffix = 'vi.hentaivn'
|
||||
extClass = '.HentaiVN'
|
||||
extVersionCode = 1
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
Binary file not shown.
After Width: | Height: | Size: 3.1 KiB |
Binary file not shown.
After Width: | Height: | Size: 1.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 4.8 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
Binary file not shown.
After Width: | Height: | Size: 79 KiB |
|
@ -0,0 +1,352 @@
|
|||
package eu.kanade.tachiyomi.extension.vi.hentaivn
|
||||
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import okhttp3.HttpUrl
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import org.jsoup.nodes.Document
|
||||
import org.jsoup.nodes.Element
|
||||
import java.text.ParseException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
class HentaiVN : ParsedHttpSource() {
|
||||
|
||||
override val baseUrl = "https://hentaivn.net"
|
||||
override val lang = "vi"
|
||||
override val name = "HentaiVN"
|
||||
override val supportsLatest = true
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
private val dateFormat = SimpleDateFormat("dd/MM/yyyy", Locale.ENGLISH)
|
||||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val chapter = SChapter.create()
|
||||
element.select("a").first().let {
|
||||
chapter.name = it.select("h2").text()
|
||||
chapter.setUrlWithoutDomain(it.attr("href"))
|
||||
}
|
||||
chapter.date_upload = parseDate(element.select("td:nth-child(2)").text().trim())
|
||||
return chapter
|
||||
}
|
||||
|
||||
private fun parseDate(dateString: String): Long {
|
||||
val date: Date
|
||||
try {
|
||||
date = dateFormat.parse(dateString)
|
||||
} catch (e: ParseException) {
|
||||
return 0
|
||||
}
|
||||
return date.time
|
||||
}
|
||||
|
||||
override fun chapterListSelector() = ".page-info > table.listing > tbody > tr"
|
||||
|
||||
override fun imageUrlParse(document: Document) = ""
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
element.select(".box-description a").first().let {
|
||||
manga.setUrlWithoutDomain(it.attr("href"))
|
||||
manga.title = it.text().trim()
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = "ul.pagination > li:contains(Next)"
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET("$baseUrl/chap-moi.html?page=$page", headers)
|
||||
}
|
||||
|
||||
override fun latestUpdatesSelector() = ".main > .block-left > .block-item > ul > li.item"
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
val infoElement = document.select(".main > .page-left > .left-info > .page-info")
|
||||
val manga = SManga.create()
|
||||
manga.author = infoElement.select("p:contains(Tác giả) a").text()
|
||||
manga.description = infoElement.select(":root > p:contains(Nội dung) +p").text()
|
||||
manga.genre = infoElement.select("p:contains(Thể loại) a").joinToString { it.text() }
|
||||
manga.thumbnail_url = document.select(".main > .page-right > .right-info > .page-ava > img").attr("src")
|
||||
manga.status = parseStatus(infoElement.select("p:contains(Tình Trạng) a").first().text())
|
||||
return manga
|
||||
}
|
||||
|
||||
private fun parseStatus(status: String) = when {
|
||||
status.contains("Đang tiến hành") -> SManga.ONGOING
|
||||
status.contains("Đã hoàn thành") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document) = document.select("#image > img").mapIndexed { i, element -> Page(i, "", element.attr("src")) }
|
||||
|
||||
override fun popularMangaFromElement(element: Element) = latestUpdatesFromElement(element)
|
||||
|
||||
override fun popularMangaNextPageSelector() = latestUpdatesNextPageSelector()
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return GET("$baseUrl/tieu-diem.html?page=$page", headers)
|
||||
}
|
||||
|
||||
override fun popularMangaSelector() = latestUpdatesSelector()
|
||||
|
||||
override fun searchMangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
element.select(".search-des > a").first().let {
|
||||
manga.setUrlWithoutDomain(it.attr("href"))
|
||||
manga.title = it.text().trim()
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun searchMangaNextPageSelector() = "ul.pagination > li:contains(Cuối)"
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val url = HttpUrl.parse("$baseUrl/forum/search-plus.php?name=$query&page=$page&dou=&char=&group=0&search=")!!.newBuilder()
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is TextField -> url.addQueryParameter(filter.key, filter.state)
|
||||
is GenreList -> filter.state
|
||||
.filter { it.state }
|
||||
.map { it.id }
|
||||
.forEach { url.addQueryParameter("tag[]", it) }
|
||||
is GroupList -> {
|
||||
val group = getGroupList()[filter.state]
|
||||
url.addQueryParameter("group", group.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return GET(url.toString(), headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = "#container .search-li"
|
||||
|
||||
private class TextField(name: String, val key: String) : Filter.Text(name)
|
||||
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Thể loại", genres)
|
||||
private class TransGroup(name: String, val id: String) : Filter.CheckBox(name) {
|
||||
override fun toString(): String {
|
||||
return name
|
||||
}
|
||||
}
|
||||
private class GroupList(groups: Array<TransGroup>) : Filter.Select<TransGroup>("Nhóm dịch", groups)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
TextField("Doujinshi", "dou"),
|
||||
TextField("Nhân vật", "char"),
|
||||
GenreList(getGenreList()),
|
||||
GroupList(getGroupList())
|
||||
)
|
||||
|
||||
// jQuery.makeArray($('#container > div > div > div.box-box.textbox > form > ul:nth-child(7) > li').map((i, e) => `Genre("${e.textContent}", "${e.children[0].value}")`)).join(',\n')
|
||||
// https://hentaivn.net/forum/search-plus.php
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("3D Hentai", "3"),
|
||||
Genre("Action", "5"),
|
||||
Genre("Adult", "116"),
|
||||
Genre("Adventure", "203"),
|
||||
Genre("Ahegao", "20"),
|
||||
Genre("Anal", "21"),
|
||||
Genre("Angel", "249"),
|
||||
Genre("Ảnh động", "131"),
|
||||
Genre("Animal", "127"),
|
||||
Genre("Animal girl", "22"),
|
||||
Genre("Artist", "115"),
|
||||
Genre("BBW", "251"),
|
||||
Genre("BDSM", "24"),
|
||||
Genre("Bestiality", "25"),
|
||||
Genre("Big Ass", "133"),
|
||||
Genre("Big Boobs", "23"),
|
||||
Genre("Big Penis", "32"),
|
||||
Genre("Bloomers", "27"),
|
||||
Genre("BlowJobs", "28"),
|
||||
Genre("Body Swap", "29"),
|
||||
Genre("Bodysuit", "30"),
|
||||
Genre("Bondage", "254"),
|
||||
Genre("Breast Sucking", "33"),
|
||||
Genre("BreastJobs", "248"),
|
||||
Genre("Brocon", "31"),
|
||||
Genre("Brother", "242"),
|
||||
Genre("Business Suit", "241"),
|
||||
Genre("Catgirls", "39"),
|
||||
Genre("Che ít", "101"),
|
||||
Genre("Che nhiều", "129"),
|
||||
Genre("Cheating", "34"),
|
||||
Genre("Chikan", "35"),
|
||||
Genre("Có che", "100"),
|
||||
Genre("Comedy", "36"),
|
||||
Genre("Comic", "120"),
|
||||
Genre("Condom", "210"),
|
||||
Genre("Cosplay", "38"),
|
||||
Genre("Cousin", "2"),
|
||||
Genre("Dark Skin", "40"),
|
||||
Genre("Demon", "132"),
|
||||
Genre("DemonGirl", "212"),
|
||||
Genre("Devil", "104"),
|
||||
Genre("DevilGirl", "105"),
|
||||
Genre("Dirty", "253"),
|
||||
Genre("Dirty Old Man", "41"),
|
||||
Genre("Double Penetration", "42"),
|
||||
Genre("Doujinshi", "44"),
|
||||
Genre("Drama", "4"),
|
||||
Genre("Drug", "43"),
|
||||
Genre("Ecchi", "45"),
|
||||
Genre("Elder Sister", "245"),
|
||||
Genre("Elf", "125"),
|
||||
Genre("Exhibitionism", "46"),
|
||||
Genre("Fantasy", "123"),
|
||||
Genre("Father", "243"),
|
||||
Genre("Femdom", "47"),
|
||||
Genre("Fingering", "48"),
|
||||
Genre("Footjob", "108"),
|
||||
Genre("Full Color", "37"),
|
||||
Genre("Furry", "202"),
|
||||
Genre("Futanari", "50"),
|
||||
Genre("Game", "130"),
|
||||
Genre("GangBang", "51"),
|
||||
Genre("Garter Belts", "206"),
|
||||
Genre("Gender Bender", "52"),
|
||||
Genre("Ghost", "106"),
|
||||
Genre("Glasses", "56"),
|
||||
Genre("Group", "53"),
|
||||
Genre("Guro", "55"),
|
||||
Genre("Hairy", "247"),
|
||||
Genre("Handjob", "57"),
|
||||
Genre("Harem", "58"),
|
||||
Genre("HentaiVN", "102"),
|
||||
Genre("Historical", "80"),
|
||||
Genre("Horror", "122"),
|
||||
Genre("Housewife", "59"),
|
||||
Genre("Humiliation", "60"),
|
||||
Genre("Idol", "61"),
|
||||
Genre("Imouto", "244"),
|
||||
Genre("Incest", "62"),
|
||||
Genre("Insect (Côn Trùng)", "26"),
|
||||
Genre("Không che", "99"),
|
||||
Genre("Kimono", "110"),
|
||||
Genre("Loli", "63"),
|
||||
Genre("Maids", "64"),
|
||||
Genre("Manhwa", "114"),
|
||||
Genre("Mature", "119"),
|
||||
Genre("Miko", "124"),
|
||||
Genre("Milf", "126"),
|
||||
Genre("Mind Break", "121"),
|
||||
Genre("Mind Control", "113"),
|
||||
Genre("Monster", "66"),
|
||||
Genre("Monstergirl", "67"),
|
||||
Genre("Mother", "103"),
|
||||
Genre("Nakadashi", "205"),
|
||||
Genre("Netori", "1"),
|
||||
Genre("Non-hen", "201"),
|
||||
Genre("NTR", "68"),
|
||||
Genre("Nurse", "69"),
|
||||
Genre("Old Man", "211"),
|
||||
Genre("Oneshot", "71"),
|
||||
Genre("Oral", "70"),
|
||||
Genre("Osananajimi", "209"),
|
||||
Genre("Paizuri", "72"),
|
||||
Genre("Pantyhose", "204"),
|
||||
Genre("Pregnant", "73"),
|
||||
Genre("Rape", "98"),
|
||||
Genre("Romance", "117"),
|
||||
Genre("Ryona", "207"),
|
||||
Genre("Scat", "134"),
|
||||
Genre("School Uniform", "74"),
|
||||
Genre("SchoolGirl", "75"),
|
||||
Genre("Series", "87"),
|
||||
Genre("Sex Toys", "88"),
|
||||
Genre("Shimapan", "246"),
|
||||
Genre("Short Hentai", "118"),
|
||||
Genre("Shota", "77"),
|
||||
Genre("Shoujo", "76"),
|
||||
Genre("Siscon", "79"),
|
||||
Genre("Sister", "78"),
|
||||
Genre("Slave", "82"),
|
||||
Genre("Sleeping", "213"),
|
||||
Genre("Small Boobs", "84"),
|
||||
Genre("Sports", "83"),
|
||||
Genre("Stockings", "81"),
|
||||
Genre("Supernatural", "85"),
|
||||
Genre("Sweating", "250"),
|
||||
Genre("Swimsuit", "86"),
|
||||
Genre("Teacher", "91"),
|
||||
Genre("Tentacles", "89"),
|
||||
Genre("Time Stop", "109"),
|
||||
Genre("Tomboy", "90"),
|
||||
Genre("Tracksuit", "252"),
|
||||
Genre("Transformation", "256"),
|
||||
Genre("Trap", "92"),
|
||||
Genre("Tsundere", "111"),
|
||||
Genre("Tự sướng", "65"),
|
||||
Genre("Twins", "93"),
|
||||
Genre("Vampire", "107"),
|
||||
Genre("Vanilla", "208"),
|
||||
Genre("Virgin", "95"),
|
||||
Genre("X-ray", "94"),
|
||||
Genre("Yandere", "112"),
|
||||
Genre("Yaoi", "96"),
|
||||
Genre("Yuri", "97"),
|
||||
Genre("Zombie", "128")
|
||||
)
|
||||
|
||||
// jQuery.makeArray($('#container > div > div > div.box-box.textbox > form > ul:nth-child(8) > li').map((i, e) => `TransGroup("${e.textContent}", "${e.children[0].value}")`)).join(',\n')
|
||||
// https://hentaivn.net/forum/search-plus.php
|
||||
private fun getGroupList() = arrayOf(
|
||||
TransGroup("Tất cả", "0"),
|
||||
TransGroup("Đang cập nhật", "1"),
|
||||
TransGroup("Góc Hentai", "3"),
|
||||
TransGroup("Hakihome", "4"),
|
||||
TransGroup("LXERS", "5"),
|
||||
TransGroup("Hentai-Homies", "6"),
|
||||
TransGroup("BUZPLANET", "7"),
|
||||
TransGroup("Trang Sally", "8"),
|
||||
TransGroup("Loli Rules The World", "9"),
|
||||
TransGroup("XXX Inc", "10"),
|
||||
TransGroup("Kobato9x", "11"),
|
||||
TransGroup("Blazing Soul", "12"),
|
||||
TransGroup("TAYXUONG", "13"),
|
||||
TransGroup("[S]ky [G]arden [G]roup", "14"),
|
||||
TransGroup("Bloomer-kun", "15"),
|
||||
TransGroup("DHT", "16"),
|
||||
TransGroup("TruyenHen18", "17"),
|
||||
TransGroup("iHentaiManga", "18"),
|
||||
TransGroup("Quân cảng Kancolle X", "19"),
|
||||
TransGroup("LHMANGA", "20"),
|
||||
TransGroup("Ship of The Dream", "21"),
|
||||
TransGroup("Fallen Angels", "22"),
|
||||
TransGroup("TruyenHentai2H", "23"),
|
||||
TransGroup("Lạc Thiên", "24"),
|
||||
TransGroup("69HENTAIXXX", "25"),
|
||||
TransGroup("DHL", "26"),
|
||||
TransGroup("Hentai-AdutsManga", "27"),
|
||||
TransGroup("Hatsu Kaze Desu Translator Team", "28"),
|
||||
TransGroup("IHentai69", "29"),
|
||||
TransGroup("Zest", "30"),
|
||||
TransGroup("Demon Victory Team", "31"),
|
||||
TransGroup("NTR Victory Team", "32"),
|
||||
TransGroup("Rori Saikou", "33"),
|
||||
TransGroup("Bullet Burn Team", "34"),
|
||||
TransGroup("RE Team", "35"),
|
||||
TransGroup("Rebelliones", "36"),
|
||||
TransGroup("Shinto", "37"),
|
||||
TransGroup("Sexual Paradise", "38"),
|
||||
TransGroup("FA Dislike Team", "39"),
|
||||
TransGroup("Triggered Team", "41"),
|
||||
TransGroup("T.K Translation Team", "42"),
|
||||
TransGroup("Mabu MG", "43"),
|
||||
TransGroup("Team Zentsu", "44"),
|
||||
TransGroup("Sweeter Than Salt", "46"),
|
||||
TransGroup("Cà rà cà rà Cặt", "47"),
|
||||
TransGroup("Paradise Of The Happiness", "48"),
|
||||
TransGroup("Furry Break the 4th Wall", "49"),
|
||||
TransGroup("The Ignite Team", "50"),
|
||||
TransGroup("Cuồng Loli", "51"),
|
||||
TransGroup("Depressed Lolicons Squad - DLS", "52"),
|
||||
TransGroup("Heaven Of The Fuck", "53")
|
||||
)
|
||||
|
||||
}
|
Loading…
Reference in New Issue