Update TuMangaOnline, LectorManga & TMOHentai (#2656)

* Update filters, update latest URL to prevent server ban for too many requests.

* Update TMO.

* Update filters, fix latest updates URL.
This commit is contained in:
Edgar Mejía 2020-04-13 15:22:39 -06:00 committed by GitHub
parent 7357093dde
commit 8b120ef5d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 156 additions and 206 deletions

View File

@ -5,12 +5,11 @@ ext {
appName = 'Tachiyomi: LectorManga'
pkgNameSuffix = 'es.lectormanga'
extClass = '.LectorManga'
extVersionCode = 10
extVersionCode = 11
libVersion = '1.2'
}
dependencies {
implementation project(':lib-ratelimit')
compileOnly project(':preference-stub')
compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
}

View File

@ -2,34 +2,19 @@ package eu.kanade.tachiyomi.extension.es.lectormanga
import android.app.Application
import android.content.SharedPreferences
import android.support.v7.preference.ListPreference
import android.support.v7.preference.PreferenceScreen
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
import android.support.v7.preference.*
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.ConfigurableSource
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.model.*
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.*
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.TimeUnit
import java.util.*
/**
* Note: this source is similar to TuMangaOnline.
@ -43,16 +28,6 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
override val lang = "es"
override val supportsLatest = true
//Client
private val rateLimitInterceptor = RateLimitInterceptor(1)
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addNetworkInterceptor(rateLimitInterceptor)
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.retryOnConnectionFailure(true)
.followRedirects(true)
.build()
private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
override fun headersBuilder(): Headers.Builder {
return Headers.Builder()
@ -88,25 +63,10 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
//Latest
override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers)
override fun latestUpdatesNextPageSelector(): String? = null
override fun latestUpdatesSelector() = "div.table-responsive:first-child td[scope=row]:nth-child(5n-3)"
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(latestUpdatesSelector())
.distinctBy { it.select("td").text().trim() }
.map { latestUpdatesFromElement(it) }
val hasNextPage = false
return MangasPage(mangas, hasNextPage)
}
override fun latestUpdatesFromElement(element: Element): SManga {
val manga = SManga.create()
manga.setUrlWithoutDomain(element.select("a").first().attr("href"))
manga.title = element.select("td").text().trim()
return manga
}
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/library?order_item=creation&order_dir=desc&page=$page", headers)
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun latestUpdatesSelector() = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element) = popularMangaFromElement(element)
//Search
@ -127,11 +87,14 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
is FilterBy -> {
url.addQueryParameter("filter_by", filter.toUriPart())
}
is OrderBy -> {
url.addQueryParameter("order_item", filter.toUriPart())
is SortBy -> {
if (filter.state != null) {
url.addQueryParameter("order_item", SORTABLES[filter.state!!.index].second)
url.addQueryParameter(
"order_dir",
if (filter.state!!.ascending) { "asc" } else { "desc" }
)
}
is OrderDir -> {
url.addQueryParameter("order_dir", filter.toUriPart())
}
is WebcomicFilter -> {
url.addQueryParameter("webcomic", when (filter.state) {
@ -195,7 +158,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
//Chapters
override fun chapterListParse(response: Response): List<SChapter> {
override fun chapterListParse(response: Response): List<SChapter> = mutableListOf<SChapter>().apply {
time = serverTime() //Get time when the chapter page is opened
val document = response.asJsoup()
@ -207,20 +170,19 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
}
// Regular list of chapters
val chapters = mutableListOf<SChapter>()
val dupselect = getduppref()!!
val chapterNames = document.select("#chapters h4.text-truncate")
val chapterNumbers = chapterNames.map { it.text().substringAfter("Capítulo").substringBefore("|").trim().toFloat() }
val chapterInfos = document.select("#chapters .chapter-list")
chapterNames.forEachIndexed { index, _ ->
val scanlator = chapterInfos[index].select("li")
if (dupselect == "one") {
scanlator.last { chapters.add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
scanlator.last { add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
} else {
scanlator.forEach { chapters.add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
scanlator.forEach { add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
}
}
return chapters
}
override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
@ -236,19 +198,20 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
?: 0
}
private fun regularChapterFromElement(chapterName: String, info: Element, number: Float, chapterUrl: String): SChapter {
val chapter = SChapter.create()
chapter.url = "$chapterUrl#${info.select("div.row > .text-right > form").attr("id")}"
chapter.name = chapterName
chapter.scanlator = info.select("div.col-md-6.text-truncate")?.text()
chapter.date_upload = info.select("span.badge.badge-primary.p-2").first()?.text()?.let { parseChapterDate(it) }
?: 0
chapter.chapter_number = number
return chapter
private fun regularChapterFromElement(chapterName: String, info: Element, number: Float, chapterUrl: String) = SChapter.create().apply {
url = "$chapterUrl#${info.select("div.row > .text-right > form").attr("id")}"
name = chapterName
scanlator = info.select("div.col-md-6.text-truncate")?.text()
date_upload = info.select("span.badge.badge-primary.p-2").first()?.text()?.let {
parseChapterDate(it)
} ?: 0
chapter_number = number
}
private fun parseChapterDate(date: String): Long = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(date)?.time
?: 0
private fun parseChapterDate(date: String): Long {
return SimpleDateFormat("yyyy-MM-dd", Locale.getDefault())
.parse(date)?.time ?: 0
}
//Utilities
@ -262,12 +225,11 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
//Pages
override fun pageListRequest(chapter: SChapter): Request {
val (chapterURL, chapterID) = chapter.url.split("#")
val response = client.newCall(GET(chapterURL, headers)).execute() //Get chapter page for current token
if (!response.isSuccessful) throw Exception("Lector Manga HTTP Error ${response.code()}")
val document = response.asJsoup()
val geturl = document.select("form#$chapterID").attr("action") + "/$time" //Get redirect URL
val getUrl = document.select("form#$chapterID").attr("action") + "/$time" //Get redirect URL
val token = document.select("form#$chapterID input").attr("value") //Get token
val method = document.select("form#$chapterID").attr("method") //Check POST or GET
time = serverTime() //Update time for next chapter
@ -286,18 +248,18 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
else -> throw UnsupportedOperationException("Lector Manga something else broke.")
}
val newurl = getBuilder(geturl, getHeaders, formBody, method)
val newUrl = getBuilder(getUrl, getHeaders, formBody, method)
// Get /cascade instead of /paginate to get all pages at once
val url = if (getPageMethod() == "cascade" && newurl.contains("paginated")) {
newurl.substringBefore("paginated") + "cascade"
} else if (getPageMethod() == "paginated" && newurl.contains("cascade")) {
newurl.substringBefore("cascade") + "paginated"
} else newurl
val url = if (getPageMethod() == "cascade" && newUrl.contains("paginated")) {
newUrl.substringBefore("paginated") + "cascade"
} else if (getPageMethod() == "paginated" && newUrl.contains("cascade")) {
newUrl.substringBefore("cascade") + "paginated"
} else newUrl
val headers = headersBuilder()
.add("User-Agent", userAgent)
.add("Referer", newurl)
.add("Referer", newUrl)
.build()
return GET(url, headers)
@ -324,7 +286,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
//Filters
private class Types : UriPartFilter("Tipo", arrayOf(
private class Types : UriPartFilter("Filtrar por tipo", arrayOf(
Pair("Ver todo", ""),
Pair("Manga", "manga"),
Pair("Manhua", "manhua"),
@ -335,7 +297,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
Pair("Oel", "oel")
))
private class Demography : UriPartFilter("Demografía", arrayOf(
private class Demography : UriPartFilter("Filtrar por demografía", arrayOf(
Pair("Ver todo", ""),
Pair("Seinen", "seinen"),
Pair("Shoujo", "shoujo"),
@ -344,24 +306,17 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
Pair("Kodomo", "kodomo")
))
private class FilterBy : UriPartFilter("Ordenar por", arrayOf(
private class FilterBy : UriPartFilter("Campo de orden", arrayOf(
Pair("Título", "title"),
Pair("Autor", "author"),
Pair("Compañia", "company")
))
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
Pair("Me gusta", "likes_count"),
Pair("Alfabético", "alphabetically"),
Pair("Puntuación", "score"),
Pair("Creación", "creation"),
Pair("Fecha estreno", "release_date")
))
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
Pair("DESC", "desc"),
Pair("ASC", "asc")
))
class SortBy : Filter.Sort(
"Ordenar por",
SORTABLES.map { it.first }.toTypedArray(),
Selection(0, false)
)
private class WebcomicFilter : Filter.TriState("Webcomic")
private class FourKomaFilter : Filter.TriState("Yonkoma")
@ -369,15 +324,14 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
private class EroticFilter : Filter.TriState("Erótico")
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Filtrar por géneros", genres)
override fun getFilterList() = FilterList(
Types(),
Demography(),
Filter.Separator(),
FilterBy(),
OrderBy(),
OrderDir(),
SortBy(),
Filter.Separator(),
WebcomicFilter(),
FourKomaFilter(),
@ -386,8 +340,10 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
GenreList(getGenreList())
)
// Array.from(document.querySelectorAll('#advancedSearch .custom-checkbox')).map(a => `Genre("${a.querySelector('label').innerText}", "${a.querySelector('input').value}")`).join(',\n')
// Array.from(document.querySelectorAll('#advancedSearch .custom-checkbox'))
// .map(a => `Genre("${a.querySelector('label').innerText}", "${a.querySelector('input').value}")`).join(',\n')
// on https://lectormanga.com/library
// Last revision 13/04/2020
private fun getGenreList() = listOf(
Genre("Acción", "1"),
Genre("Aventura", "2"),
@ -480,6 +436,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
preferences.edit().putString(PAGEGET_PREF, entry).commit()
}
}
screen.addPreference(deduppref)
screen.addPreference(pageMethod)
}
@ -514,19 +471,26 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
preferences.edit().putString(PAGEGET_PREF, entry).commit()
}
}
screen.addPreference(deduppref)
screen.addPreference(pageMethod)
}
private fun getduppref() = preferences.getString(DEDUP_PREF, "all")
private fun getPageMethod() = preferences.getString(PAGEGET_PREF, "cascade")
companion object {
private const val DEDUP_PREF_Title = "Chapter List Scanlator Preference"
private const val DEDUP_PREF = "deduppref"
private const val PAGEGET_PREF_Title = "Método para obtener imágenes"
private const val PAGEGET_PREF = "pagemethodpref"
private val SORTABLES = listOf(
Pair("Me gusta", "likes_count"),
Pair("Alfabético", "alphabetically"),
Pair("Puntuación", "score"),
Pair("Creación", "creation"),
Pair("Fecha estreno", "release_date")
)
}
}

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: TMOHentai'
pkgNameSuffix = 'es.tmohentai'
extClass = '.TMOHentai'
extVersionCode = 1
extVersionCode = 2
libVersion = '1.2'
}

View File

@ -17,7 +17,7 @@ class TMOHentai : ParsedHttpSource() {
override val supportsLatest = true
override fun popularMangaRequest(page: Int) = GET("$baseUrl/section/hentai?view=list&page=$page&order=publication_date&order-dir=asc&search%5BsearchText%5D=&search%5BsearchBy%5D=name&type=all", headers)
override fun popularMangaRequest(page: Int) = GET("$baseUrl/section/all?view=list&page=$page&order=popularity&order-dir=desc&search[searchText]=&search[searchBy]=name&type=all", headers)
override fun popularMangaSelector() = "table > tbody > tr[data-toggle=popover]"
@ -31,7 +31,7 @@ class TMOHentai : ParsedHttpSource() {
override fun popularMangaNextPageSelector() = "a[rel=next]"
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/filter/all?view=list&page=$page")
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/section/all?view=list&page=$page&order=publication_date&order-dir=desc&search[searchText]=&search[searchBy]=name&type=all", headers)
override fun latestUpdatesSelector() = popularMangaSelector()
@ -75,10 +75,9 @@ class TMOHentai : ParsedHttpSource() {
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = HttpUrl.parse("$baseUrl/section/hentai?view=list")!!.newBuilder()
val url = HttpUrl.parse("$baseUrl/section/all?view=list")!!.newBuilder()
url.addQueryParameter("search[searchText]", query)
url.addQueryParameter("search[searchBy]", "name")
url.addQueryParameter("page", page.toString())
filters.forEach { filter ->
@ -86,17 +85,23 @@ class TMOHentai : ParsedHttpSource() {
is Types -> {
url.addQueryParameter("type", filter.toUriPart())
}
is OrderBy -> {
url.addQueryParameter("order", filter.toUriPart())
}
is OrderDir -> {
url.addQueryParameter("order-dir", filter.toUriPart())
}
is GenreList -> {
filter.state
.filter { genre -> genre.state }
.forEach { genre -> url.addQueryParameter("genders[]", genre.id) }
}
is FilterBy -> {
url.addQueryParameter("search[searchBy]", filter.toUriPart())
}
is SortBy -> {
if (filter.state != null) {
url.addQueryParameter("order", SORTABLES[filter.state!!.index].second)
url.addQueryParameter(
"order-dir",
if (filter.state!!.ascending) { "asc" } else { "desc" }
)
}
}
}
}
@ -110,13 +115,14 @@ class TMOHentai : ParsedHttpSource() {
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
override fun getFilterList() = FilterList(
Types(),
Filter.Separator(),
OrderBy(),
OrderDir(),
FilterBy(),
SortBy(),
Filter.Separator(),
GenreList(getGenreList())
)
@ -126,7 +132,7 @@ class TMOHentai : ParsedHttpSource() {
fun toUriPart() = vals[state].second
}
private class Types : UriPartFilter("Tipo", arrayOf(
private class Types : UriPartFilter("Filtrar por tipo", arrayOf(
Pair("Ver todos", "all"),
Pair("Manga", "hentai"),
Pair("Light Hentai", "light-hentai"),
@ -135,18 +141,21 @@ class TMOHentai : ParsedHttpSource() {
Pair("Other", "otro")
))
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
Pair("Alfabético", "alphabetic"),
Pair("Creación", "publication_date"),
Pair("Popularidad", "popularity")
private class FilterBy : UriPartFilter("Campo de orden", arrayOf(
Pair("Nombre", "name"),
Pair("Artista", "artist"),
Pair("Revista", "magazine"),
Pair("Tag", "tag")
))
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
Pair("ASC", "asc"),
Pair("DESC", "desc")
))
class SortBy : Filter.Sort(
"Ordenar por",
SORTABLES.map { it.first }.toTypedArray(),
Selection(2, false)
)
// Array.from(document.querySelectorAll('#advancedSearch .list-group .list-group-item')).map(a => `Genre("${a.querySelector('span').innerText.replace(' ', '')}", "${a.querySelector('input').value}")`).join(',\n')
// Array.from(document.querySelectorAll('#advancedSearch .list-group .list-group-item'))
// .map(a => `Genre("${a.querySelector('span').innerText.replace(' ', '')}", "${a.querySelector('input').value}")`).join(',\n')
// https://tmohentai.com/section/hentai
private fun getGenreList() = listOf(
Genre("Romance", "1"),
@ -196,4 +205,13 @@ class TMOHentai : ParsedHttpSource() {
Genre("Tsundere", "45"),
Genre("Yandere", "46")
)
companion object {
private val SORTABLES = listOf(
Pair("Alfabético", "alphabetic"),
Pair("Creación", "publication_date"),
Pair("Popularidad", "popularity")
)
}
}

View File

@ -5,12 +5,11 @@ ext {
appName = 'Tachiyomi: TuMangaOnline'
pkgNameSuffix = 'es.tumangaonline'
extClass = '.TuMangaOnline'
extVersionCode = 25
extVersionCode = 26
libVersion = '1.2'
}
dependencies {
implementation project(':lib-ratelimit')
compileOnly project(':preference-stub')
compileOnly 'com.github.inorichi.injekt:injekt-core:65b0440'
}

View File

@ -4,30 +4,18 @@ import android.app.Application
import android.content.SharedPreferences
import android.support.v7.preference.ListPreference
import android.support.v7.preference.PreferenceScreen
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.source.ConfigurableSource
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.model.*
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.FormBody
import okhttp3.Headers
import okhttp3.HttpUrl
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.*
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.TimeUnit
class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
@ -40,14 +28,6 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
//Client
private val rateLimitInterceptor = RateLimitInterceptor(1, 1)
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.addNetworkInterceptor(rateLimitInterceptor)
.connectTimeout(1, TimeUnit.MINUTES)
.readTimeout(1, TimeUnit.MINUTES)
.retryOnConnectionFailure(true)
.followRedirects(true)
.build()!!
private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.132 Safari/537.36"
override fun headersBuilder(): Headers.Builder {
return Headers.Builder()
@ -61,7 +41,6 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
.headers(headers)
.url(url)
.method(method, formBody)
//.post(formBody)
.build()
return client.newCall(req)
@ -69,9 +48,6 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
.request()
.url()
.toString()
/*.execute()
.body()!!
.string()*/
}
//Popular
@ -89,27 +65,10 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
//Latest
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/latest_uploads?page=$page&uploads_mode=thumbnail", headers)
override fun latestUpdatesRequest(page: Int) = GET("$baseUrl/library?order_item=creation&order_dir=desc&filter_by=title&_page=1&page=$page", headers)
override fun latestUpdatesNextPageSelector() = popularMangaNextPageSelector()
override fun latestUpdatesSelector() = "div.upload-file-row"
override fun latestUpdatesParse(response: Response): MangasPage {
val document = response.asJsoup()
val mangas = document.select(latestUpdatesSelector())
.distinctBy { it.select("div.thumbnail-title > h4.text-truncate").text().trim() }
.map { latestUpdatesFromElement(it) }
val hasNextPage = latestUpdatesNextPageSelector().let { selector ->
document.select(selector).first()
} != null
return MangasPage(mangas, hasNextPage)
}
override fun latestUpdatesFromElement(element: Element) = SManga.create().apply {
element.select("div.upload-file-row > a").let {
setUrlWithoutDomain(it.attr("href"))
title = it.select("div.thumbnail-title > h4.text-truncate").text()
thumbnail_url = it.select("div.thumbnail > style").toString().substringAfter("url('").substringBefore("');")
}
}
override fun latestUpdatesSelector() = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element) = popularMangaFromElement(element)
//Search
@ -131,11 +90,14 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
is FilterBy -> {
url.addQueryParameter("filter_by", filter.toUriPart())
}
is OrderBy -> {
url.addQueryParameter("order_item", filter.toUriPart())
is SortBy -> {
if (filter.state != null) {
url.addQueryParameter("order_item", SORTABLES[filter.state!!.index].second)
url.addQueryParameter(
"order_dir",
if (filter.state!!.ascending) { "asc" } else { "desc" }
)
}
is OrderDir -> {
url.addQueryParameter("order_dir", filter.toUriPart())
}
is WebcomicFilter -> {
url.addQueryParameter("webcomic", when (filter.state) {
@ -217,7 +179,11 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
// Regular list of chapters
val chapters = mutableListOf<SChapter>()
document.select(regularChapterListSelector()).forEach { chapelement ->
val chapternumber = chapelement.select("a.btn-collapse").text().substringBefore(":").substringAfter("Capítulo").trim().toFloat()
val chapternumber = chapelement.select("a.btn-collapse").text()
.substringBefore(":")
.substringAfter("Capítulo")
.trim()
.toFloat()
val chaptername = chapelement.select("div.col-10.text-truncate").text()
val scanelement = chapelement.select("ul.chapter-list > li")
val dupselect = getduppref()!!
@ -231,6 +197,7 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
}
override fun chapterListSelector() = throw UnsupportedOperationException("Not used")
override fun chapterFromElement(element: Element) = throw UnsupportedOperationException("Not used")
private fun oneShotChapterListSelector() = "div.chapter-list-element > ul.list-group li.list-group-item"
@ -318,7 +285,7 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
//Filters
private class Types : UriPartFilter("Tipo", arrayOf(
private class Types : UriPartFilter("Filtrar por tipo", arrayOf(
Pair("Ver todo", ""),
Pair("Manga", "manga"),
Pair("Manhua", "manhua"),
@ -329,7 +296,7 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
Pair("Oel", "oel")
))
private class Demography : UriPartFilter("Demografía", arrayOf(
private class Demography : UriPartFilter("Filtrar por demografía", arrayOf(
Pair("Ver todo", ""),
Pair("Seinen", "seinen"),
Pair("Shoujo", "shoujo"),
@ -338,24 +305,17 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
Pair("Kodomo", "kodomo")
))
private class FilterBy : UriPartFilter("Ordenar por", arrayOf(
private class FilterBy : UriPartFilter("Campo de orden", arrayOf(
Pair("Título", "title"),
Pair("Autor", "author"),
Pair("Compañia", "company")
))
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
Pair("Me gusta", "likes_count"),
Pair("Alfabético", "alphabetically"),
Pair("Puntuación", "score"),
Pair("Creación", "creation"),
Pair("Fecha estreno", "release_date")
))
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
Pair("ASC", "asc"),
Pair("DESC", "desc")
))
class SortBy : Filter.Sort(
"Ordenar por",
SORTABLES.map { it.first }.toTypedArray(),
Selection(0, false)
)
private class WebcomicFilter : Filter.TriState("Webcomic")
private class FourKomaFilter : Filter.TriState("Yonkoma")
@ -363,15 +323,14 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
private class EroticFilter : Filter.TriState("Erótico")
private class Genre(name: String, val id: String) : Filter.CheckBox(name)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Filtrar por géneros", genres)
override fun getFilterList() = FilterList(
Types(),
Demography(),
Filter.Separator(),
FilterBy(),
OrderBy(),
OrderDir(),
SortBy(),
Filter.Separator(),
WebcomicFilter(),
FourKomaFilter(),
@ -380,8 +339,10 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
GenreList(getGenreList())
)
// Array.from(document.querySelectorAll('#books-genders .col-auto .custom-control')).map(a => `Genre("${a.querySelector('label').innerText}", "${a.querySelector('input').value}")`).join(',\n')
// Array.from(document.querySelectorAll('#books-genders .col-auto .custom-control'))
// .map(a => `Genre("${a.querySelector('label').innerText}", "${a.querySelector('input').value}")`).join(',\n')
// on https://tumangaonline.me/library
// Last revision 13/04/2020
private fun getGenreList() = listOf(
Genre("Acción", "1"),
Genre("Aventura", "2"),
@ -474,6 +435,7 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
preferences.edit().putString(PAGEGET_PREF, entry).commit()
}
}
screen.addPreference(deduppref)
screen.addPreference(pageMethod)
}
@ -508,19 +470,27 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
preferences.edit().putString(PAGEGET_PREF, entry).commit()
}
}
screen.addPreference(deduppref)
screen.addPreference(pageMethod)
}
private fun getduppref() = preferences.getString(DEDUP_PREF, "all")
private fun getPageMethod() = preferences.getString(PAGEGET_PREF, "cascade")
companion object {
private const val DEDUP_PREF_Title = "Chapter List Scanlator Preference"
private const val DEDUP_PREF = "deduppref"
private const val PAGEGET_PREF_Title = "Método para obtener imágenes"
private const val PAGEGET_PREF = "pagemethodpref"
private val SORTABLES = listOf(
Pair("Me gusta", "likes_count"),
Pair("Alfabético", "alphabetically"),
Pair("Puntuación", "score"),
Pair("Creación", "creation"),
Pair("Fecha estreno", "release_date"),
Pair("Núm. Capítulos", "num_chapters")
)
}
}