Fix: Academyvn (#109)
Add: - Blogtruyen - Truyentranhlh - Iutruyentranh
This commit is contained in:
parent
cd392cd52b
commit
acacecf4bd
@ -14,7 +14,7 @@ class Academyvn : ParsedHttpSource() {
|
||||
|
||||
override val name = "Academy VN"
|
||||
|
||||
override val baseUrl = "http://truyen.academyvn.com"
|
||||
override val baseUrl = "http://hocvientruyentranh.com"
|
||||
|
||||
override val lang = "vi"
|
||||
|
||||
|
13
src/vi/blogtruyen/build.gradle
Normal file
13
src/vi/blogtruyen/build.gradle
Normal file
@ -0,0 +1,13 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: BlogTruyen'
|
||||
pkgNameSuffix = "vi.blogtruyen"
|
||||
extClass = '.Blogtruyen'
|
||||
extVersionCode = 1
|
||||
extVersionSuffix = 1
|
||||
libVersion = '1.0'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
@ -0,0 +1,214 @@
|
||||
package eu.kanade.tachiyomi.source.online.vietnamese
|
||||
|
||||
import android.util.Log
|
||||
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.SimpleDateFormat
|
||||
|
||||
|
||||
class Blogtruyen : ParsedHttpSource() {
|
||||
|
||||
override val name = "BlogTruyen"
|
||||
|
||||
override val baseUrl = "http://blogtruyen.com"
|
||||
|
||||
override val lang = "vi"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
override fun popularMangaSelector() = "div.list span.tiptip.fs-12.ellipsis"
|
||||
|
||||
override fun latestUpdatesSelector() = popularMangaSelector()
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return GET("$baseUrl/ajax/Search/AjaxLoadListManga?key=tatca&orderBy=3&p=$page", headers)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET("$baseUrl/ajax/Search/AjaxLoadListManga?key=tatca&orderBy=5&p=$page", headers)
|
||||
}
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
element.select("a").first().let {
|
||||
manga.setUrlWithoutDomain(it.attr("href"))
|
||||
manga.title = it.text()
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SManga {
|
||||
return popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
override fun popularMangaNextPageSelector() = "div.paging:last-child:not(.current_page)"
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
var temp = "$baseUrl/timkiem/nangcao/1/0"
|
||||
val genres = mutableListOf<String>()
|
||||
val genresEx = mutableListOf<String>()
|
||||
var aut = ""
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is GenreList -> filter.state.forEach {
|
||||
genre ->
|
||||
when (genre.state) {
|
||||
Filter.TriState.STATE_INCLUDE -> genres.add(genre.name.toLowerCase())
|
||||
Filter.TriState.STATE_EXCLUDE -> genresEx.add(genre.name.toLowerCase())
|
||||
}
|
||||
}
|
||||
is Author -> {
|
||||
if (!filter.state.isEmpty()) {
|
||||
aut = filter.state
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (genres.isNotEmpty()) temp = temp + "/" + genres.joinToString(",")
|
||||
else temp = temp + "/-1"
|
||||
if (genresEx.isNotEmpty()) temp = temp + "/" + genresEx.joinToString(",")
|
||||
else temp = temp + "/-1"
|
||||
val url = HttpUrl.parse(temp)!!.newBuilder()
|
||||
url.addQueryParameter("txt", query)
|
||||
if (!aut.isEmpty()) url.addQueryParameter("aut", aut)
|
||||
url.addQueryParameter("p", page.toString())
|
||||
Log.i("tachiyomi", url.toString())
|
||||
return GET(url.toString().replace("m.", ""), headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = "div.list > p:gt(0) > span:eq(0)"
|
||||
|
||||
override fun searchMangaFromElement(element: Element): SManga {
|
||||
return popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
override fun searchMangaNextPageSelector() = "ul.pagination i.glyphicon.glyphicon-step-forward.red"
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
val infoElement = document.select("div.description").first()
|
||||
|
||||
val manga = SManga.create()
|
||||
manga.author = infoElement.select("p:contains(Tác giả) > a").first()?.text()
|
||||
manga.genre = infoElement.select("p:contains(Thể loại) > span.category > a").text()
|
||||
manga.description = document.select("div.detail > div.content").text()
|
||||
manga.status = infoElement.select("p:contains(Trạng thái) > span.color-red").first()?.text().orEmpty().let { parseStatus(it) }
|
||||
manga.thumbnail_url = document.select("div.thumbnail > img").first()?.attr("src")
|
||||
return manga
|
||||
}
|
||||
|
||||
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 chapterListSelector() = "div.list-wrap > p"
|
||||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val urlElement = element.select("span > a").first()
|
||||
|
||||
val chapter = SChapter.create()
|
||||
chapter.setUrlWithoutDomain(urlElement.attr("href"))
|
||||
chapter.name = urlElement.attr("title")
|
||||
chapter.date_upload = element.select("span.publishedDate").first()?.text()?.let {
|
||||
SimpleDateFormat("dd/MM/yyyy HH:mm").parse(it).time
|
||||
} ?: 0
|
||||
return chapter
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, headers)
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
val pages = mutableListOf<Page>()
|
||||
var i = 0
|
||||
document.select("article#content > img").forEach {
|
||||
pages.add(Page(i++, "", it.attr("src")))
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
override fun imageUrlRequest(page: Page) = GET(page.url)
|
||||
|
||||
override fun imageUrlParse(document: Document) = ""
|
||||
|
||||
var status = arrayOf("Sao cũng được", "Đang tiến hành", "Đã hoàn thành", "Tạm ngưng")
|
||||
|
||||
private class Status : Filter.Select<String>("Status", arrayOf("Sao cũng được", "Đang tiến hành", "Đã hoàn thành", "Tạm ngưng"))
|
||||
private class Author : Filter.Text("Tác giả")
|
||||
private class Genre(name: String, val id: Int) : Filter.TriState(name)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Thể loại", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
Status(),
|
||||
GenreList(getGenreList()),
|
||||
Author()
|
||||
)
|
||||
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("16+", 54),
|
||||
Genre("18+", 45),
|
||||
Genre("Action", 1),
|
||||
Genre("Adult", 2),
|
||||
Genre("Adventure", 3),
|
||||
Genre("Anime", 4),
|
||||
Genre("Comedy", 5),
|
||||
Genre("Comic", 6),
|
||||
Genre("Doujinshi", 7),
|
||||
Genre("Drama", 49),
|
||||
Genre("Ecchi", 48),
|
||||
Genre("Even BT", 60),
|
||||
Genre("Fantasy", 50),
|
||||
Genre("Game", 61),
|
||||
Genre("Gender Bender", 51),
|
||||
Genre("Harem", 12),
|
||||
Genre("Historical", 13),
|
||||
Genre("Horror", 14),
|
||||
Genre("Josei", 15),
|
||||
Genre("Live Action", 16),
|
||||
Genre("Magic", 46),
|
||||
Genre("Manga", 55),
|
||||
Genre("Manhua", 17),
|
||||
Genre("Manhwa", 18),
|
||||
Genre("Martial Arts", 19),
|
||||
Genre("Mature", 20),
|
||||
Genre("Mecha", 21),
|
||||
Genre("Mystery", 22),
|
||||
Genre("Nấu ăn", 56),
|
||||
Genre("NTR", 61),
|
||||
Genre("One shot", 23),
|
||||
Genre("Psychological", 24),
|
||||
Genre("Romance", 25),
|
||||
Genre("School Life", 26),
|
||||
Genre("Sci-fi", 27),
|
||||
Genre("Seinen", 28),
|
||||
Genre("Shoujo", 29),
|
||||
Genre("Shoujo Ai", 30),
|
||||
Genre("Shounen", 31),
|
||||
Genre("Shounen Ai", 32),
|
||||
Genre("Slice of Life", 33),
|
||||
Genre("Smut", 34),
|
||||
Genre("Soft Yaoi", 35),
|
||||
Genre("Soft Yuri", 36),
|
||||
Genre("Sports", 37),
|
||||
Genre("Supernatural", 38),
|
||||
Genre("Tạp chí truyện tranh", 39),
|
||||
Genre("Tragedy", 40),
|
||||
Genre("Trap", 58),
|
||||
Genre("Trinh thám", 57),
|
||||
Genre("Truyện scan", 41),
|
||||
Genre("Video clip", 53),
|
||||
Genre("VnComic", 42),
|
||||
Genre("Webtoon", 52),
|
||||
Genre("Yuri", 59)
|
||||
)
|
||||
}
|
13
src/vi/iutruyentranh/build.gradle
Normal file
13
src/vi/iutruyentranh/build.gradle
Normal file
@ -0,0 +1,13 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: IuTruyenTranh'
|
||||
pkgNameSuffix = "vi.iutruyentranh"
|
||||
extClass = '.Iutruyentranh'
|
||||
extVersionCode = 1
|
||||
extVersionSuffix = 1
|
||||
libVersion = '1.0'
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
@ -0,0 +1,201 @@
|
||||
package eu.kanade.tachiyomi.source.online.vietnamese
|
||||
|
||||
import android.util.Log
|
||||
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.SimpleDateFormat
|
||||
|
||||
/**
|
||||
* Created by Nam Nguyen on 29/4/2017.
|
||||
*/
|
||||
|
||||
class Iutruyentranh : ParsedHttpSource() {
|
||||
|
||||
override val name = "IuTruyenTranh"
|
||||
|
||||
override val baseUrl = "http://iutruyentranh.com"
|
||||
|
||||
override val lang = "vi"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
override fun popularMangaSelector() = "div.bbottom h4.media-heading"
|
||||
|
||||
override fun latestUpdatesSelector() = "h4.media-heading"
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return GET("$baseUrl/genre/$page?popular", headers)
|
||||
}
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET("$baseUrl/latest/$page", headers)
|
||||
}
|
||||
|
||||
override fun popularMangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
element.select("a").first().let {
|
||||
manga.setUrlWithoutDomain(it.attr("href"))
|
||||
manga.title = it.text()
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun latestUpdatesFromElement(element: Element): SManga {
|
||||
return popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
override fun popularMangaNextPageSelector() = "ul.pagination > li:contains(...»)"
|
||||
|
||||
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
val url = HttpUrl.parse("$baseUrl/search/$page?")!!.newBuilder().addQueryParameter("name", query)
|
||||
val genres = mutableListOf<String>()
|
||||
val genresEx = mutableListOf<String>()
|
||||
(if (filters.isEmpty()) getFilterList() else filters).forEach { filter ->
|
||||
when (filter) {
|
||||
is Author -> url.addQueryParameter("autart", filter.state)
|
||||
is GenreList -> filter.state.forEach { genre ->
|
||||
when (genre.state) {
|
||||
Filter.TriState.STATE_INCLUDE -> genres.add(genre.name.toLowerCase())
|
||||
Filter.TriState.STATE_EXCLUDE -> genresEx.add(genre.name.toLowerCase())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (genres.isNotEmpty()) url.addQueryParameter("genres", genres.joinToString(","))
|
||||
if (genresEx.isNotEmpty()) url.addQueryParameter("genres-exclude", genresEx.joinToString(","))
|
||||
|
||||
Log.i("tachiyomi", url.toString())
|
||||
return GET(url.toString(), headers)
|
||||
}
|
||||
|
||||
override fun searchMangaSelector() = popularMangaSelector()
|
||||
|
||||
override fun searchMangaFromElement(element: Element): SManga {
|
||||
return popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
override fun mangaDetailsParse(document: Document): SManga {
|
||||
val infoElement = document.select("section.manga article").first()
|
||||
|
||||
val manga = SManga.create()
|
||||
manga.author = infoElement.select("span[itemprop=author]").first()?.text()
|
||||
manga.genre = infoElement.select("a[itemprop=genre]").text()
|
||||
manga.description = infoElement.select("p.box.box-danger").text()
|
||||
manga.status = infoElement.select("a[rel=nofollow]").last()?.text().orEmpty().let { parseStatus(it) }
|
||||
manga.thumbnail_url = infoElement.select("img[class^=thumbnail]").first()?.attr("src")
|
||||
return manga
|
||||
}
|
||||
|
||||
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 chapterListSelector() = "ul.list-unstyled > table > tbody > tr"
|
||||
|
||||
override fun chapterFromElement(element: Element): SChapter {
|
||||
val urlElement = element.select("a").first()
|
||||
|
||||
val chapter = SChapter.create()
|
||||
chapter.setUrlWithoutDomain(urlElement.attr("href") + "&load=all")
|
||||
chapter.name = urlElement.select("b").text()
|
||||
chapter.date_upload = element.select("td:eq(1)").first()?.text()?.let {
|
||||
SimpleDateFormat("dd/MM/yyyy").parse(it).time
|
||||
} ?: 0
|
||||
return chapter
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, headers)
|
||||
|
||||
override fun pageListParse(document: Document): List<Page> {
|
||||
val pages = mutableListOf<Page>()
|
||||
var i = 0
|
||||
document.select("img.img").forEach {
|
||||
pages.add(Page(i++, "", it.attr("src")))
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
override fun imageUrlRequest(page: Page) = GET(page.url)
|
||||
|
||||
override fun imageUrlParse(document: Document) = ""
|
||||
|
||||
private class Author : Filter.Text("Tác giả")
|
||||
private class Genre(name: String) : Filter.TriState(name)
|
||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Thể loại", genres)
|
||||
|
||||
override fun getFilterList() = FilterList(
|
||||
Author(),
|
||||
GenreList(getGenreList())
|
||||
)
|
||||
|
||||
private fun getGenreList() = listOf(
|
||||
Genre("Action"),
|
||||
Genre("Adult"),
|
||||
Genre("Adventure"),
|
||||
Genre("Anime"),
|
||||
Genre("Bishounen"),
|
||||
Genre("Comedy"),
|
||||
Genre("Cookin"),
|
||||
Genre("Demons"),
|
||||
Genre("Doujinshi"),
|
||||
Genre("Drama"),
|
||||
Genre("Ecchi"),
|
||||
Genre("Fantasy"),
|
||||
Genre("Gender Bender"),
|
||||
Genre("Harem"),
|
||||
Genre("Hentai"),
|
||||
Genre("Historical"),
|
||||
Genre("Horror"),
|
||||
Genre("Josei"),
|
||||
Genre("Live action"),
|
||||
Genre("Magic"),
|
||||
Genre("Manhua"),
|
||||
Genre("Manhwa"),
|
||||
Genre("Martial Arts"),
|
||||
Genre("Mature"),
|
||||
Genre("Mecha"),
|
||||
Genre("Medical"),
|
||||
Genre("Military"),
|
||||
Genre("Mystery"),
|
||||
Genre("One shot"),
|
||||
Genre("Oneshot"),
|
||||
Genre("Other"),
|
||||
Genre("Psychological"),
|
||||
Genre("Romance"),
|
||||
Genre("School Life"),
|
||||
Genre("Sci fi"),
|
||||
Genre("Seinen"),
|
||||
Genre("Shotacon"),
|
||||
Genre("Shoujo"),
|
||||
Genre("Shoujo Ai"),
|
||||
Genre("Shoujoai"),
|
||||
Genre("Shounen"),
|
||||
Genre("Shounen Ai"),
|
||||
Genre("Shounenai"),
|
||||
Genre("Slice of Life"),
|
||||
Genre("Smut"),
|
||||
Genre("Sports"),
|
||||
Genre("Super power"),
|
||||
Genre("Superma"),
|
||||
Genre("Supernatural"),
|
||||
Genre("Tragedy"),
|
||||
Genre("Vampire"),
|
||||
Genre("Webtoon"),
|
||||
Genre("Yaoi"),
|
||||
Genre("Yuri")
|
||||
)
|
||||
}
|
18
src/vi/truyentranhlh/build.gradle
Normal file
18
src/vi/truyentranhlh/build.gradle
Normal file
@ -0,0 +1,18 @@
|
||||
apply plugin: 'com.android.application'
|
||||
apply plugin: 'kotlin-android'
|
||||
|
||||
ext {
|
||||
appName = 'Tachiyomi: TruyenTranhLh'
|
||||
pkgNameSuffix = "vi.truyentranhlh"
|
||||
extClass = '.Truyentrnahlh'
|
||||
extVersionCode = 1
|
||||
extVersionSuffix = 1
|
||||
libVersion = '1.0'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
provided "com.google.code.gson:gson:2.8.0"
|
||||
provided "com.github.salomonbrys.kotson:kotson:2.5.0"
|
||||
}
|
||||
|
||||
apply from: "$rootDir/common.gradle"
|
@ -0,0 +1,191 @@
|
||||
package eu.kanade.tachiyomi.source.online.vietnamese
|
||||
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonParser
|
||||
import eu.kanade.tachiyomi.network.GET
|
||||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.HttpSource
|
||||
import eu.kanade.tachiyomi.util.asJsoup
|
||||
import okhttp3.OkHttpClient
|
||||
import okhttp3.Request
|
||||
import okhttp3.Response
|
||||
import org.jsoup.nodes.Element
|
||||
import java.util.*
|
||||
|
||||
class Truyentranhlh : HttpSource() {
|
||||
|
||||
override val name = "TruyenTranhLH"
|
||||
|
||||
override val baseUrl = "http://truyentranhlh.com"
|
||||
|
||||
override val lang = "vi"
|
||||
|
||||
override val supportsLatest = true
|
||||
|
||||
override val client: OkHttpClient = network.cloudflareClient
|
||||
|
||||
fun popularMangaSelector() = "div.media-body > h3"
|
||||
|
||||
fun latestUpdatesSelector() = popularMangaSelector()
|
||||
|
||||
override fun popularMangaRequest(page: Int): Request {
|
||||
return GET("$baseUrl/manga-list.html?listType=pagination&page=$page&artist=&author=&group=&name=&genre=&sort=views&sort_type=DESC", headers)
|
||||
}
|
||||
|
||||
override fun popularMangaParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
|
||||
val mangas = document.select(popularMangaSelector()).map { element ->
|
||||
popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
val hasNextPage = popularMangaNextPageSelector()?.let { selector ->
|
||||
document.select(selector).first()
|
||||
} != null
|
||||
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
|
||||
|
||||
override fun latestUpdatesRequest(page: Int): Request {
|
||||
return GET("$baseUrl/manga-list.html?listType=pagination&page=$page&artist=&author=&group=&name=&genre=&sort=last_update&sort_type=DESC", headers)
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
val document = response.asJsoup()
|
||||
|
||||
val mangas = document.select(latestUpdatesSelector()).map { element ->
|
||||
latestUpdatesFromElement(element)
|
||||
}
|
||||
|
||||
val hasNextPage = latestUpdatesNextPageSelector()?.let { selector ->
|
||||
document.select(selector).first()
|
||||
} != null
|
||||
|
||||
return MangasPage(mangas, hasNextPage)
|
||||
}
|
||||
|
||||
fun popularMangaFromElement(element: Element): SManga {
|
||||
val manga = SManga.create()
|
||||
element.select("a").first().let {
|
||||
manga.setUrlWithoutDomain("/" + it.attr("href"))
|
||||
manga.title = it.text()
|
||||
}
|
||||
return manga
|
||||
}
|
||||
|
||||
fun latestUpdatesFromElement(element: Element): SManga {
|
||||
return popularMangaFromElement(element)
|
||||
}
|
||||
|
||||
fun popularMangaNextPageSelector() = "i.glyphicon.glyphicon-chevron-right"
|
||||
|
||||
fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||
return GET("$baseUrl/app/manga/controllers/search.single.php?q=" + query, headers)
|
||||
}
|
||||
|
||||
override fun searchMangaParse(response: Response): MangasPage {
|
||||
var jsonData = response.asJsoup().text()
|
||||
jsonData = jsonData.substring(1, jsonData.length - 1)
|
||||
val elementArray = JsonParser().parse(jsonData)
|
||||
.asJsonObject
|
||||
.getAsJsonArray("data")
|
||||
val mangas = elementArray.map { element ->
|
||||
searchMangaFromElement(element)
|
||||
}
|
||||
return MangasPage(mangas, false)
|
||||
}
|
||||
|
||||
fun searchMangaFromElement(element: JsonElement): SManga {
|
||||
val result = element.asJsonObject
|
||||
val manga = SManga.create()
|
||||
manga.title = result.get("primary").toString().replace("\"", "")
|
||||
manga.url = "/" + result.get("onclick").toString().replace("\"window.location='", "").replace("'\"", "")
|
||||
return manga
|
||||
}
|
||||
|
||||
override fun mangaDetailsParse(response: Response): SManga {
|
||||
val document = response.asJsoup()
|
||||
val infoElement = document.select("ul.manga-info").first()
|
||||
|
||||
val manga = SManga.create()
|
||||
manga.author = infoElement.select("a.btn.btn-xs.btn-info").first()?.text()
|
||||
manga.genre = infoElement.select("a.btn.btn-xs.btn-danger").text()
|
||||
manga.description = document.select("h3:contains(Sơ lược) + p").text()
|
||||
manga.status = infoElement.select("a.btn.btn-xs.btn-success").last()?.text().orEmpty().let { parseStatus(it) }
|
||||
manga.thumbnail_url = document.select("img.thumbnail").first()?.attr("src")
|
||||
return manga
|
||||
}
|
||||
|
||||
fun parseStatus(status: String) = when {
|
||||
status.contains("Chưa hoàn thành") -> SManga.ONGOING
|
||||
status.contains("Đã hoàn thành") -> SManga.COMPLETED
|
||||
else -> SManga.UNKNOWN
|
||||
}
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
return document.select(chapterListSelector()).map { chapterFromElement(it) }
|
||||
}
|
||||
|
||||
fun chapterListSelector() = "table.table.table-hover > tbody > tr"
|
||||
|
||||
fun chapterFromElement(element: Element): SChapter {
|
||||
val urlElement = element.select("td > a").first()
|
||||
|
||||
val chapter = SChapter.create()
|
||||
chapter.setUrlWithoutDomain(cleanUrl(urlElement.attr("href")))
|
||||
chapter.name = urlElement.select("b").text()
|
||||
chapter.date_upload = element.select("td > i > time").first()?.text()?.let { parseChapterDate(it) } ?: 0
|
||||
return chapter
|
||||
}
|
||||
|
||||
fun cleanUrl(url: String): String {
|
||||
val index = url.lastIndexOf(baseUrl)
|
||||
if (index != -1) return url.substring(index)
|
||||
return "/" + url
|
||||
}
|
||||
|
||||
private fun parseChapterDate(date: String): Long {
|
||||
val dateWords: List<String> = date.split(" ")
|
||||
if (dateWords.size == 3) {
|
||||
val timeAgo = Integer.parseInt(dateWords[0])
|
||||
val dates: Calendar = Calendar.getInstance()
|
||||
if (dateWords[1].contains("phút")) {
|
||||
dates.add(Calendar.MINUTE, -timeAgo)
|
||||
} else if (dateWords[1].contains("giờ")) {
|
||||
dates.add(Calendar.HOUR_OF_DAY, -timeAgo)
|
||||
} else if (dateWords[1].contains("ngày")) {
|
||||
dates.add(Calendar.DAY_OF_YEAR, -timeAgo)
|
||||
} else if (dateWords[1].contains("tuần")) {
|
||||
dates.add(Calendar.WEEK_OF_YEAR, -timeAgo)
|
||||
} else if (dateWords[1].contains("tháng")) {
|
||||
dates.add(Calendar.MONTH, -timeAgo)
|
||||
} else if (dateWords[1].contains("năm")) {
|
||||
dates.add(Calendar.YEAR, -timeAgo)
|
||||
}
|
||||
return dates.timeInMillis
|
||||
}
|
||||
return 0L
|
||||
}
|
||||
|
||||
override fun pageListRequest(chapter: SChapter) = GET(baseUrl + chapter.url, headers)
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
val document = response.asJsoup()
|
||||
val pages = mutableListOf<Page>()
|
||||
var i = 0
|
||||
document.select("div.chapter-content > img").forEach {
|
||||
pages.add(Page(i++, "", it.attr("src")))
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
override fun imageUrlRequest(page: Page) = GET(page.url)
|
||||
|
||||
override fun imageUrlParse(response: Response): String {
|
||||
return ""
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user