Heavenmanga - updates (#2815)
* Heavenmanga - updates * Update build.gradle
This commit is contained in:
parent
0a6494c51d
commit
6c722ce2b3
|
@ -5,7 +5,7 @@ ext {
|
||||||
appName = 'Tachiyomi: HeavenManga'
|
appName = 'Tachiyomi: HeavenManga'
|
||||||
pkgNameSuffix = 'es.heavenmanga'
|
pkgNameSuffix = 'es.heavenmanga'
|
||||||
extClass = '.HeavenManga'
|
extClass = '.HeavenManga'
|
||||||
extVersionCode = 4
|
extVersionCode = 5
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,13 @@
|
||||||
package eu.kanade.tachiyomi.extension.es.heavenmanga
|
package eu.kanade.tachiyomi.extension.es.heavenmanga
|
||||||
|
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.network.asObservableSuccess
|
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
import eu.kanade.tachiyomi.source.model.*
|
||||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||||
import eu.kanade.tachiyomi.util.asJsoup
|
import eu.kanade.tachiyomi.util.asJsoup
|
||||||
import okhttp3.*
|
import okhttp3.*
|
||||||
import okhttp3.Response
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.select.Elements
|
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import rx.Observable
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
class HeavenManga : ParsedHttpSource() {
|
class HeavenManga : ParsedHttpSource() {
|
||||||
|
|
||||||
|
@ -22,91 +17,61 @@ class HeavenManga : ParsedHttpSource() {
|
||||||
|
|
||||||
override val lang = "es"
|
override val lang = "es"
|
||||||
|
|
||||||
override val supportsLatest = true
|
// latest is broken on the site, it's the same as populaar so turning it off
|
||||||
|
override val supportsLatest = false
|
||||||
|
|
||||||
override val client: OkHttpClient = network.cloudflareClient
|
override val client: OkHttpClient = network.cloudflareClient
|
||||||
|
|
||||||
override fun headersBuilder(): Headers.Builder {
|
override fun headersBuilder(): Headers.Builder {
|
||||||
return Headers.Builder()
|
return Headers.Builder()
|
||||||
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/60")
|
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/75")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun popularMangaSelector() = "li.ranking"
|
override fun popularMangaSelector() = "div.page-item-detail"
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = "#container .ultimos_epis .not"
|
override fun latestUpdatesSelector() = "#container .ultimos_epis .not"
|
||||||
|
|
||||||
override fun searchMangaSelector() = ".top.clearfix .cont_manga"
|
override fun searchMangaSelector() = "div.c-tabs-item__content, ${popularMangaSelector()}"
|
||||||
|
|
||||||
private fun novelaFilterSelector() = ".lstsradd"
|
override fun chapterListSelector() = "div.listing-chapters_wrap tr"
|
||||||
|
|
||||||
private fun comicFilterSelector() = "section#related"
|
override fun popularMangaNextPageSelector() = "ul.pagination a[rel=next]"
|
||||||
|
|
||||||
override fun chapterListSelector() = "#mamain ul li"
|
|
||||||
|
|
||||||
private fun chapterPageSelector() = "a#l"
|
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector() = null
|
|
||||||
|
|
||||||
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = "li:contains(Siguiente):not([id=inactive])"
|
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/top/", headers)
|
override fun popularMangaRequest(page: Int) = GET("$baseUrl/top?orderby=views&page=$page", headers)
|
||||||
|
|
||||||
override fun popularMangaParse(response: Response): MangasPage {
|
|
||||||
val mangas = mutableListOf<SManga>()
|
|
||||||
val document = response.asJsoup()
|
|
||||||
|
|
||||||
document.select(popularMangaSelector()).map{ mangas.add(popularMangaFromElement(it)) }
|
|
||||||
|
|
||||||
return MangasPage(mangas, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/", headers)
|
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/", headers)
|
||||||
|
|
||||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
|
||||||
val mangas = mutableListOf<SManga>()
|
|
||||||
val document = response.asJsoup()
|
|
||||||
val checkList = mutableListOf<String>()
|
|
||||||
|
|
||||||
// Fewer duplicates makes for a better user experience and fewer Requests to make
|
|
||||||
document.select(latestUpdatesSelector()).forEach{ e ->
|
|
||||||
e.select("a").attr("href").substringBeforeLast("-").let { urlPart ->
|
|
||||||
if (urlPart !in checkList) {
|
|
||||||
mangas.add(latestUpdatesFromElement(e))
|
|
||||||
checkList.add(urlPart)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return MangasPage(mangas, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
val search_url = "$baseUrl/buscar/$query.html"
|
val searchUrl = "$baseUrl/buscar?query=$query"
|
||||||
|
|
||||||
// Filter
|
// Filter
|
||||||
if(query.isBlank()) {
|
val pageParameter = if (page > 1) "?page=$page" else ""
|
||||||
|
|
||||||
|
if (query.isBlank()) {
|
||||||
val ext = ".html"
|
val ext = ".html"
|
||||||
var name = ""
|
var name: String
|
||||||
filters.forEach { filter ->
|
filters.forEach { filter ->
|
||||||
when(filter) {
|
when(filter) {
|
||||||
is GenreFilter -> {
|
is GenreFilter -> {
|
||||||
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
||||||
name = filter.toUriPart()
|
name = filter.toUriPart()
|
||||||
return GET("$baseUrl/genero/$name$ext", headers)
|
return GET("$baseUrl/genero/$name$ext$pageParameter", headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is AlphabeticoFilter -> {
|
is AlphabeticoFilter -> {
|
||||||
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
||||||
name = filter.toUriPart()
|
name = filter.toUriPart()
|
||||||
return GET("$baseUrl/letra/$name$ext", headers)
|
return GET("$baseUrl/letra/$name$ext$pageParameter", headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is ListaCompletasFilter -> {
|
is ListaCompletasFilter -> {
|
||||||
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
if(filter.toUriPart().isNotBlank() && filter.state != 0) {
|
||||||
name = filter.toUriPart()
|
name = filter.toUriPart()
|
||||||
return GET("$baseUrl/$name/", headers)
|
return GET("$baseUrl/$name$pageParameter", headers)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -114,22 +79,23 @@ class HeavenManga : ParsedHttpSource() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return GET(search_url, headers)
|
return GET(searchUrl, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlRequest(page: Page) = GET(page.url, headers)
|
override fun searchMangaParse(response: Response): MangasPage {
|
||||||
|
return if (response.request().url().toString().contains("query=")) super.searchMangaParse(response)
|
||||||
|
else popularMangaParse(response)
|
||||||
|
}
|
||||||
|
|
||||||
// get contents of a url
|
// get contents of a url
|
||||||
private fun getUrlContents(url: String): Document = client.newCall(GET(url, headers)).execute().asJsoup()
|
private fun getUrlContents(url: String): Document = client.newCall(GET(url, headers)).execute().asJsoup()
|
||||||
|
|
||||||
override fun popularMangaFromElement(element: Element): SManga {
|
override fun popularMangaFromElement(element: Element): SManga {
|
||||||
val manga = SManga.create()
|
return SManga.create().apply {
|
||||||
|
title = element.select("div.manga-name").text()
|
||||||
manga.setUrlWithoutDomain(element.select("a").attr("href"))
|
setUrlWithoutDomain(element.select("a").attr("href"))
|
||||||
manga.title = element.select("div.tit").first().ownText()
|
thumbnail_url = element.select("img").attr("abs:src")
|
||||||
manga.thumbnail_url = element.select("img").attr("src")
|
}
|
||||||
|
|
||||||
return manga
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
|
||||||
|
@ -143,99 +109,42 @@ class HeavenManga : ParsedHttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaFromElement(element: Element) = SManga.create().apply {
|
override fun searchMangaFromElement(element: Element) = SManga.create().apply {
|
||||||
val figure = element.select("figure").attr("style")
|
element.select("h4 a").let {
|
||||||
element.select("a").let {
|
title = it.text()
|
||||||
setUrlWithoutDomain(it.attr("href"))
|
setUrlWithoutDomain(it.attr("href"))
|
||||||
title = if(element.hasClass("titnom")) element.select(".titnom").text() else it.select("header").text()
|
|
||||||
thumbnail_url = if(element.select("figure").hasAttr("style")) figure.substring(figure.indexOf("http"), figure.indexOf(")") ) else it.select("img").attr("src")
|
|
||||||
}
|
}
|
||||||
|
thumbnail_url = element.select("img").attr("abs:data-src")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun chapterFromElement(element: Element): SChapter {
|
override fun chapterFromElement(element: Element): SChapter {
|
||||||
val urlElement = element.select("a").first()
|
return SChapter.create().apply {
|
||||||
val timeElement = element.select("span").first()
|
element.select("a").let {
|
||||||
val time = timeElement.text()
|
name = it.text()
|
||||||
val date = time.replace("--", "-")
|
setUrlWithoutDomain(it.attr("href"))
|
||||||
val url = urlElement.attr("href")
|
|
||||||
|
|
||||||
val chapter = SChapter.create()
|
|
||||||
chapter.setUrlWithoutDomain(url)
|
|
||||||
chapter.name = urlElement.text()
|
|
||||||
chapter.date_upload = parseChapterDate(date.toString())
|
|
||||||
return chapter
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun fetchSearchManga(page: Int, query: String, filters: FilterList): Observable<MangasPage> {
|
|
||||||
return client.newCall(searchMangaRequest(page, query, filters))
|
|
||||||
.asObservableSuccess()
|
|
||||||
.map { response ->
|
|
||||||
searchMangaParse(response)
|
|
||||||
}
|
}
|
||||||
}
|
scanlator = element.select("span.pull-right").text()
|
||||||
|
|
||||||
override fun searchMangaParse(response: Response): MangasPage {
|
|
||||||
val document = response.asJsoup()
|
|
||||||
val el: String
|
|
||||||
|
|
||||||
if(document.select(novelaFilterSelector()).first() != null) {
|
|
||||||
el = novelaFilterSelector()
|
|
||||||
} else if (document.select(comicFilterSelector()).first() != null) {
|
|
||||||
el = comicFilterSelector()
|
|
||||||
} else {
|
|
||||||
el = searchMangaSelector()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val mangas = document.select(el).map { element ->
|
|
||||||
searchMangaFromElement(element)
|
|
||||||
}
|
|
||||||
|
|
||||||
val hasNextPage = searchMangaNextPageSelector()?.let { selector ->
|
|
||||||
document.select(selector).first()
|
|
||||||
} != null
|
|
||||||
|
|
||||||
return MangasPage(mangas, hasNextPage)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
||||||
document.select(".left.home").let {
|
document.select("div.tab-summary").let { info ->
|
||||||
val genres = it.select(".sinopsis a")?.map {
|
genre = info.select("div.genres-content a").joinToString { it.text() }
|
||||||
it.text()
|
thumbnail_url = info.select("div.summary_image img").attr("abs:data-src")
|
||||||
}
|
|
||||||
|
|
||||||
genre = genres?.joinToString(", ")
|
|
||||||
val allElements: Elements = document.select(".sinopsis")
|
|
||||||
//get all elements under .sinopsis
|
|
||||||
for (e: Element in allElements) {
|
|
||||||
description = e.childNode(0).toString() //the description
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
description = document.select("div.description-summary p").text()
|
||||||
thumbnail_url = document.select(".cover.clearfix img[style='width:142px;height:212px;']").attr("src")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseChapterDate(date: String): Long = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).parse(date).time
|
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
val chapters = mutableListOf<SChapter>()
|
return getUrlContents(baseUrl + chapter.url).select("a[id=leer]").attr("abs:href")
|
||||||
val document = response.asJsoup()
|
.let { GET(it, headers) }
|
||||||
document.select(chapterListSelector()).forEach {
|
|
||||||
chapters.add(chapterFromElement(it))
|
|
||||||
}
|
|
||||||
return chapters
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document) = ""
|
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> {
|
override fun pageListParse(document: Document): List<Page> {
|
||||||
val pages = mutableListOf<Page>()
|
return document.select("script:containsData(pUrl)").first().data()
|
||||||
val leerUrl = document.select(chapterPageSelector()).attr("href")
|
|
||||||
val urlElement = getUrlContents(leerUrl)
|
|
||||||
|
|
||||||
urlElement.select("script:containsData(pUrl)").first().data()
|
|
||||||
.substringAfter("pUrl=[").substringBefore("\"},];").split("\"},")
|
.substringAfter("pUrl=[").substringBefore("\"},];").split("\"},")
|
||||||
.forEach{ pages.add(Page(pages.size, "", it.substringAfterLast("\""))) }
|
.mapIndexed{ i, string -> Page(i, "", string.substringAfterLast("\"")) }
|
||||||
|
|
||||||
return pages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Loading…
Reference in New Issue