parent
f93f28cbd4
commit
ee394dc2a8
|
@ -5,7 +5,7 @@ ext {
|
||||||
appName = 'Tachiyomi: LectorManga'
|
appName = 'Tachiyomi: LectorManga'
|
||||||
pkgNameSuffix = 'es.lectormanga'
|
pkgNameSuffix = 'es.lectormanga'
|
||||||
extClass = '.LectorManga'
|
extClass = '.LectorManga'
|
||||||
extVersionCode = 9
|
extVersionCode = 10
|
||||||
libVersion = '1.2'
|
libVersion = '1.2'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,16 +7,28 @@ import android.support.v7.preference.PreferenceScreen
|
||||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||||
import eu.kanade.tachiyomi.network.GET
|
import eu.kanade.tachiyomi.network.GET
|
||||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||||
import eu.kanade.tachiyomi.source.model.*
|
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.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.FormBody
|
||||||
|
import okhttp3.Headers
|
||||||
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.Response
|
||||||
import org.jsoup.nodes.Document
|
import org.jsoup.nodes.Document
|
||||||
import org.jsoup.nodes.Element
|
import org.jsoup.nodes.Element
|
||||||
import uy.kohesive.injekt.Injekt
|
import uy.kohesive.injekt.Injekt
|
||||||
import uy.kohesive.injekt.api.get
|
import uy.kohesive.injekt.api.get
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
import java.util.TimeZone
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -24,26 +36,24 @@ import java.util.concurrent.TimeUnit
|
||||||
*/
|
*/
|
||||||
class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
|
|
||||||
|
//Info
|
||||||
|
|
||||||
override val name = "LectorManga"
|
override val name = "LectorManga"
|
||||||
|
override val baseUrl = "https://lectormanga.com"
|
||||||
override val baseUrl = "https://lectormanga.com/"
|
|
||||||
|
|
||||||
override val lang = "es"
|
override val lang = "es"
|
||||||
|
|
||||||
override val supportsLatest = true
|
override val supportsLatest = true
|
||||||
|
|
||||||
private val rateLimitInterceptor = RateLimitInterceptor(1)
|
//Client
|
||||||
|
|
||||||
|
private val rateLimitInterceptor = RateLimitInterceptor(1)
|
||||||
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
override val client: OkHttpClient = network.cloudflareClient.newBuilder()
|
||||||
.addNetworkInterceptor(rateLimitInterceptor)
|
.addNetworkInterceptor(rateLimitInterceptor)
|
||||||
.connectTimeout(1, TimeUnit.MINUTES)
|
.connectTimeout(1, TimeUnit.MINUTES)
|
||||||
.readTimeout(1, TimeUnit.MINUTES)
|
.readTimeout(1, TimeUnit.MINUTES)
|
||||||
.retryOnConnectionFailure(true)
|
.retryOnConnectionFailure(true)
|
||||||
.followRedirects(true)
|
.followRedirects(true)
|
||||||
.build()!!
|
.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"
|
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 {
|
override fun headersBuilder(): Headers.Builder {
|
||||||
return Headers.Builder()
|
return Headers.Builder()
|
||||||
.add("User-Agent", userAgent)
|
.add("User-Agent", userAgent)
|
||||||
|
@ -54,7 +64,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
val req = Request.Builder()
|
val req = Request.Builder()
|
||||||
.headers(headers)
|
.headers(headers)
|
||||||
.url(url)
|
.url(url)
|
||||||
.method(method,formBody)
|
.method(method, formBody)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
return client.newCall(req)
|
return client.newCall(req)
|
||||||
|
@ -64,24 +74,23 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
.toString()
|
.toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val preferences: SharedPreferences by lazy {
|
//Popular
|
||||||
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaSelector() = ".col-6 .card"
|
|
||||||
|
|
||||||
override fun latestUpdatesSelector() = "div.table-responsive:first-child td[scope=row]:nth-child(5n-3)"
|
|
||||||
|
|
||||||
override fun popularMangaRequest(page: Int) = GET("$baseUrl/library?order_item=likes_count&order_dir=desc&type=&filter_by=title&page=$page", headers)
|
override fun popularMangaRequest(page: Int) = GET("$baseUrl/library?order_item=likes_count&order_dir=desc&type=&filter_by=title&page=$page", headers)
|
||||||
|
override fun popularMangaNextPageSelector() = ".pagination .page-item:not(.disabled) a[rel='next']"
|
||||||
override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers)
|
override fun popularMangaSelector() = ".col-6 .card"
|
||||||
|
|
||||||
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
|
||||||
setUrlWithoutDomain(element.select("a").attr("href"))
|
setUrlWithoutDomain(element.select("a").attr("href"))
|
||||||
title = element.select("a").text()
|
title = element.select("a").text()
|
||||||
thumbnail_url = element.select("img").attr("src")
|
thumbnail_url = element.select("img").attr("src")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//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 {
|
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val mangas = document.select(latestUpdatesSelector())
|
val mangas = document.select(latestUpdatesSelector())
|
||||||
|
@ -99,25 +108,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
return manga
|
return manga
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
//Search
|
||||||
genre = document.select("a.py-2").joinToString(", ") {
|
|
||||||
it.text()
|
|
||||||
}
|
|
||||||
|
|
||||||
description = document.select(".col-12.mt-2")?.text()
|
|
||||||
status = parseStatus(document.select(".status-publishing")?.text().orEmpty())
|
|
||||||
thumbnail_url = document.select(".text-center img.img-fluid").attr("src")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun parseStatus(status: String) = when {
|
|
||||||
status.contains("Publicándose") -> SManga.ONGOING
|
|
||||||
status.contains("Finalizado") -> SManga.COMPLETED
|
|
||||||
else -> SManga.UNKNOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun popularMangaNextPageSelector() = ".pagination .page-item:not(.disabled) a[rel='next']"
|
|
||||||
|
|
||||||
override fun latestUpdatesNextPageSelector() = "none"
|
|
||||||
|
|
||||||
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
|
||||||
val url = HttpUrl.parse("$baseUrl/library")!!.newBuilder()
|
val url = HttpUrl.parse("$baseUrl/library")!!.newBuilder()
|
||||||
|
@ -172,8 +163,8 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
}
|
}
|
||||||
is GenreList -> {
|
is GenreList -> {
|
||||||
filter.state
|
filter.state
|
||||||
.filter { genre -> genre.state }
|
.filter { genre -> genre.state }
|
||||||
.forEach { genre -> url.addQueryParameter("genders[]", genre.id) }
|
.forEach { genre -> url.addQueryParameter("genders[]", genre.id) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -182,21 +173,37 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun searchMangaSelector() = popularMangaSelector()
|
override fun searchMangaSelector() = popularMangaSelector()
|
||||||
|
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||||
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
|
override fun searchMangaFromElement(element: Element): SManga = popularMangaFromElement(element)
|
||||||
|
|
||||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
//Details
|
||||||
|
|
||||||
|
override fun mangaDetailsParse(document: Document) = SManga.create().apply {
|
||||||
|
genre = document.select("a.py-2").joinToString(", ") {
|
||||||
|
it.text()
|
||||||
|
}
|
||||||
|
description = document.select(".col-12.mt-2")?.text()
|
||||||
|
status = parseStatus(document.select(".status-publishing")?.text().orEmpty())
|
||||||
|
thumbnail_url = document.select(".text-center img.img-fluid").attr("src")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseStatus(status: String) = when {
|
||||||
|
status.contains("Publicándose") -> SManga.ONGOING
|
||||||
|
status.contains("Finalizado") -> SManga.COMPLETED
|
||||||
|
else -> SManga.UNKNOWN
|
||||||
|
}
|
||||||
|
|
||||||
|
//Chapters
|
||||||
|
|
||||||
override fun chapterListParse(response: Response): List<SChapter> {
|
override fun chapterListParse(response: Response): List<SChapter> {
|
||||||
time = serverTime() //Get time when the chapter page is opened
|
time = serverTime() //Get time when the chapter page is opened
|
||||||
|
|
||||||
val document = response.asJsoup()
|
val document = response.asJsoup()
|
||||||
val chapterurl = response.request().url().toString()
|
val chapterUrl = response.request().url().toString()
|
||||||
val chapteridselector = ""
|
|
||||||
|
|
||||||
// One-shot
|
// One-shot
|
||||||
if (document.select("#chapters").isEmpty()) {
|
if (document.select("#chapters").isEmpty()) {
|
||||||
return document.select(oneShotChapterListSelector()).map { oneShotChapterFromElement(it, chapterurl, chapteridselector) }
|
return document.select(oneShotChapterListSelector()).map { oneShotChapterFromElement(it, chapterUrl) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regular list of chapters
|
// Regular list of chapters
|
||||||
|
@ -207,10 +214,10 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
val chapterInfos = document.select("#chapters .chapter-list")
|
val chapterInfos = document.select("#chapters .chapter-list")
|
||||||
chapterNames.forEachIndexed { index, _ ->
|
chapterNames.forEachIndexed { index, _ ->
|
||||||
val scanlator = chapterInfos[index].select("li")
|
val scanlator = chapterInfos[index].select("li")
|
||||||
if (dupselect=="one") {
|
if (dupselect == "one") {
|
||||||
scanlator.last { chapters.add(regularChapterFromElement(chapterNames[index].text(), it , chapterNumbers[index], chapterurl, chapteridselector)) }
|
scanlator.last { chapters.add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
|
||||||
} else {
|
} else {
|
||||||
scanlator.forEach { chapters.add(regularChapterFromElement(chapterNames[index].text(), it ,chapterNumbers[index], chapterurl, chapteridselector)) }
|
scanlator.forEach { chapters.add(regularChapterFromElement(chapterNames[index].text(), it, chapterNumbers[index], chapterUrl)) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return chapters
|
return chapters
|
||||||
|
@ -221,42 +228,51 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
|
|
||||||
private fun oneShotChapterListSelector() = "div.chapter-list-element > ul.list-group li.list-group-item"
|
private fun oneShotChapterListSelector() = "div.chapter-list-element > ul.list-group li.list-group-item"
|
||||||
|
|
||||||
private fun oneShotChapterFromElement(element: Element, chapterurl: String, chapteridselector: String) = SChapter.create().apply {
|
private fun oneShotChapterFromElement(element: Element, chapterUrl: String) = SChapter.create().apply {
|
||||||
url = "$chapterurl#${element.select("div.row > .text-right > form").attr("id")}"
|
url = "$chapterUrl#${element.select("div.row > .text-right > form").attr("id")}"
|
||||||
name = "One Shot"
|
name = "One Shot"
|
||||||
scanlator = element.select("div.col-md-6.text-truncate")?.text()
|
scanlator = element.select("div.col-md-6.text-truncate")?.text()
|
||||||
date_upload = element.select("span.badge.badge-primary.p-2").first()?.text()?.let { parseChapterDate(it) } ?: 0
|
date_upload = element.select("span.badge.badge-primary.p-2").first()?.text()?.let { parseChapterDate(it) }
|
||||||
|
?: 0
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun regularChapterFromElement(chapterName: String, info: Element, number: Float, chapterurl: String, chapteridselector: String): SChapter {
|
private fun regularChapterFromElement(chapterName: String, info: Element, number: Float, chapterUrl: String): SChapter {
|
||||||
val chapter = SChapter.create()
|
val chapter = SChapter.create()
|
||||||
chapter.url = "$chapterurl#${info.select("div.row > .text-right > form").attr("id")}"
|
chapter.url = "$chapterUrl#${info.select("div.row > .text-right > form").attr("id")}"
|
||||||
chapter.name = chapterName
|
chapter.name = chapterName
|
||||||
chapter.scanlator = info.select("div.col-md-6.text-truncate")?.text()
|
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.date_upload = info.select("span.badge.badge-primary.p-2").first()?.text()?.let { parseChapterDate(it) }
|
||||||
|
?: 0
|
||||||
chapter.chapter_number = number
|
chapter.chapter_number = number
|
||||||
return chapter
|
return chapter
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun parseChapterDate(date: String): Long = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(date)?.time ?: 0
|
private fun parseChapterDate(date: String): Long = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(date)?.time
|
||||||
|
?: 0
|
||||||
|
|
||||||
|
//Utilities
|
||||||
|
|
||||||
private var time = serverTime() //Grab time at app launch, can be updated
|
private var time = serverTime() //Grab time at app launch, can be updated
|
||||||
private fun serverTime() :String {
|
private fun serverTime(): String {
|
||||||
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
|
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
|
||||||
formatter.timeZone = TimeZone.getTimeZone("GMT+1") //Convert time to match server
|
formatter.timeZone = TimeZone.getTimeZone("GMT+1") //Convert time to match server
|
||||||
return formatter.format(Date())
|
return formatter.format(Date())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Pages
|
||||||
|
|
||||||
override fun pageListRequest(chapter: SChapter): Request {
|
override fun pageListRequest(chapter: SChapter): Request {
|
||||||
|
|
||||||
val (chapterURL, chapterID) = chapter.url.split("#")
|
val (chapterURL, chapterID) = chapter.url.split("#")
|
||||||
val response = client.newCall(GET(chapterURL, headers)).execute() //Get chapter page for current token
|
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()}")
|
if (!response.isSuccessful) throw Exception("Lector Manga HTTP Error ${response.code()}")
|
||||||
val document = response.asJsoup()
|
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 token = document.select("form#$chapterID input").attr("value") //Get token
|
||||||
val method = document.select("form#$chapterID").attr("method") //Check POST or GET
|
val method = document.select("form#$chapterID").attr("method") //Check POST or GET
|
||||||
time = serverTime() //Update time for next chapter
|
time = serverTime() //Update time for next chapter
|
||||||
|
|
||||||
val getHeaders = headersBuilder()
|
val getHeaders = headersBuilder()
|
||||||
.add("User-Agent", userAgent)
|
.add("User-Agent", userAgent)
|
||||||
.add("Referer", chapterURL)
|
.add("Referer", chapterURL)
|
||||||
.add("Content-Type", "application/x-www-form-urlencoded")
|
.add("Content-Type", "application/x-www-form-urlencoded")
|
||||||
|
@ -270,10 +286,12 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
else -> throw UnsupportedOperationException("Lector Manga something else broke.")
|
else -> throw UnsupportedOperationException("Lector Manga something else broke.")
|
||||||
}
|
}
|
||||||
|
|
||||||
val newurl = getBuilder(geturl,getHeaders,formBody,method)
|
val newurl = getBuilder(geturl, getHeaders, formBody, method)
|
||||||
val url = if (getPageMethod()=="cascade" && newurl.contains("paginated")) {
|
|
||||||
|
// Get /cascade instead of /paginate to get all pages at once
|
||||||
|
val url = if (getPageMethod() == "cascade" && newurl.contains("paginated")) {
|
||||||
newurl.substringBefore("paginated") + "cascade"
|
newurl.substringBefore("paginated") + "cascade"
|
||||||
} else if (getPageMethod()=="paginated" && newurl.contains("cascade")) {
|
} else if (getPageMethod() == "paginated" && newurl.contains("cascade")) {
|
||||||
newurl.substringBefore("cascade") + "paginated"
|
newurl.substringBefore("cascade") + "paginated"
|
||||||
} else newurl
|
} else newurl
|
||||||
|
|
||||||
|
@ -282,15 +300,16 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
.add("Referer", newurl)
|
.add("Referer", newurl)
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
// Get /cascade instead of /paginate to get all pages at once
|
|
||||||
return GET(url, headers)
|
return GET(url, headers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
|
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
|
||||||
if (getPageMethod()=="cascade") {
|
if (getPageMethod() == "cascade") {
|
||||||
val style = document.select("style:containsData(height)").html()
|
document.select("img.viewer-img").forEach {
|
||||||
document.select( "img[id]").filterNot { "#${it.attr("id")}," in style || "#${it.attr("id")}{" in style }.forEach {
|
add(Page(size, "", it.let {
|
||||||
add(Page(size, "", it.attr("src")))
|
if (it.hasAttr("data-src"))
|
||||||
|
it.attr("abs:data-src") else it.attr("abs:src")
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
val pageList = document.select("#viewer-pages-select").first().select("option").map { it.attr("value").toInt() }
|
val pageList = document.select("#viewer-pages-select").first().select("option").map { it.attr("value").toInt() }
|
||||||
|
@ -303,43 +322,45 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
|
|
||||||
override fun imageUrlParse(document: Document): String = document.select("img.viewer-image").attr("src")
|
override fun imageUrlParse(document: Document): String = document.select("img.viewer-image").attr("src")
|
||||||
|
|
||||||
|
//Filters
|
||||||
|
|
||||||
private class Types : UriPartFilter("Tipo", arrayOf(
|
private class Types : UriPartFilter("Tipo", arrayOf(
|
||||||
Pair("Ver todo", ""),
|
Pair("Ver todo", ""),
|
||||||
Pair("Manga", "manga"),
|
Pair("Manga", "manga"),
|
||||||
Pair("Manhua", "manhua"),
|
Pair("Manhua", "manhua"),
|
||||||
Pair("Manhwa", "manhwa"),
|
Pair("Manhwa", "manhwa"),
|
||||||
Pair("Novela", "novel"),
|
Pair("Novela", "novel"),
|
||||||
Pair("One shot", "one_shot"),
|
Pair("One shot", "one_shot"),
|
||||||
Pair("Doujinshi", "doujinshi"),
|
Pair("Doujinshi", "doujinshi"),
|
||||||
Pair("Oel", "oel")
|
Pair("Oel", "oel")
|
||||||
))
|
))
|
||||||
|
|
||||||
private class Demography : UriPartFilter("Demografía", arrayOf(
|
private class Demography : UriPartFilter("Demografía", arrayOf(
|
||||||
Pair("Ver todo", ""),
|
Pair("Ver todo", ""),
|
||||||
Pair("Seinen", "seinen"),
|
Pair("Seinen", "seinen"),
|
||||||
Pair("Shoujo", "shoujo"),
|
Pair("Shoujo", "shoujo"),
|
||||||
Pair("Shounen", "shounen"),
|
Pair("Shounen", "shounen"),
|
||||||
Pair("Josei", "josei"),
|
Pair("Josei", "josei"),
|
||||||
Pair("Kodomo", "kodomo")
|
Pair("Kodomo", "kodomo")
|
||||||
))
|
))
|
||||||
|
|
||||||
private class FilterBy : UriPartFilter("Ordenar por", arrayOf(
|
private class FilterBy : UriPartFilter("Ordenar por", arrayOf(
|
||||||
Pair("Título", "title"),
|
Pair("Título", "title"),
|
||||||
Pair("Autor", "author"),
|
Pair("Autor", "author"),
|
||||||
Pair("Compañia", "company")
|
Pair("Compañia", "company")
|
||||||
))
|
))
|
||||||
|
|
||||||
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
|
private class OrderBy : UriPartFilter("Ordenar por", arrayOf(
|
||||||
Pair("Me gusta", "likes_count"),
|
Pair("Me gusta", "likes_count"),
|
||||||
Pair("Alfabético", "alphabetically"),
|
Pair("Alfabético", "alphabetically"),
|
||||||
Pair("Puntuación", "score"),
|
Pair("Puntuación", "score"),
|
||||||
Pair("Creación", "creation"),
|
Pair("Creación", "creation"),
|
||||||
Pair("Fecha estreno", "release_date")
|
Pair("Fecha estreno", "release_date")
|
||||||
))
|
))
|
||||||
|
|
||||||
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
|
private class OrderDir : UriPartFilter("Ordenar por", arrayOf(
|
||||||
Pair("DESC", "desc"),
|
Pair("DESC", "desc"),
|
||||||
Pair("ASC", "asc")
|
Pair("ASC", "asc")
|
||||||
))
|
))
|
||||||
|
|
||||||
private class WebcomicFilter : Filter.TriState("Webcomic")
|
private class WebcomicFilter : Filter.TriState("Webcomic")
|
||||||
|
@ -351,79 +372,83 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
|
private class GenreList(genres: List<Genre>) : Filter.Group<Genre>("Géneros", genres)
|
||||||
|
|
||||||
override fun getFilterList() = FilterList(
|
override fun getFilterList() = FilterList(
|
||||||
Types(),
|
Types(),
|
||||||
Demography(),
|
Demography(),
|
||||||
Filter.Separator(),
|
Filter.Separator(),
|
||||||
FilterBy(),
|
FilterBy(),
|
||||||
OrderBy(),
|
OrderBy(),
|
||||||
OrderDir(),
|
OrderDir(),
|
||||||
Filter.Separator(),
|
Filter.Separator(),
|
||||||
WebcomicFilter(),
|
WebcomicFilter(),
|
||||||
FourKomaFilter(),
|
FourKomaFilter(),
|
||||||
AmateurFilter(),
|
AmateurFilter(),
|
||||||
EroticFilter(),
|
EroticFilter(),
|
||||||
GenreList(getGenreList())
|
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
|
// on https://lectormanga.com/library
|
||||||
private fun getGenreList() = listOf(
|
private fun getGenreList() = listOf(
|
||||||
Genre("Acción", "1"),
|
Genre("Acción", "1"),
|
||||||
Genre("Aventura", "2"),
|
Genre("Aventura", "2"),
|
||||||
Genre("Comedia", "3"),
|
Genre("Comedia", "3"),
|
||||||
Genre("Drama", "4"),
|
Genre("Drama", "4"),
|
||||||
Genre("Recuentos de la vida", "5"),
|
Genre("Recuentos de la vida", "5"),
|
||||||
Genre("Ecchi", "6"),
|
Genre("Ecchi", "6"),
|
||||||
Genre("Fantasia", "7"),
|
Genre("Fantasia", "7"),
|
||||||
Genre("Magia", "8"),
|
Genre("Magia", "8"),
|
||||||
Genre("Sobrenatural", "9"),
|
Genre("Sobrenatural", "9"),
|
||||||
Genre("Horror", "10"),
|
Genre("Horror", "10"),
|
||||||
Genre("Misterio", "11"),
|
Genre("Misterio", "11"),
|
||||||
Genre("Psicológico", "12"),
|
Genre("Psicológico", "12"),
|
||||||
Genre("Romance", "13"),
|
Genre("Romance", "13"),
|
||||||
Genre("Ciencia Ficción", "14"),
|
Genre("Ciencia Ficción", "14"),
|
||||||
Genre("Thriller", "15"),
|
Genre("Thriller", "15"),
|
||||||
Genre("Deporte", "16"),
|
Genre("Deporte", "16"),
|
||||||
Genre("Girls Love", "17"),
|
Genre("Girls Love", "17"),
|
||||||
Genre("Boys Love", "18"),
|
Genre("Boys Love", "18"),
|
||||||
Genre("Harem", "19"),
|
Genre("Harem", "19"),
|
||||||
Genre("Mecha", "20"),
|
Genre("Mecha", "20"),
|
||||||
Genre("Supervivencia", "21"),
|
Genre("Supervivencia", "21"),
|
||||||
Genre("Reencarnación", "22"),
|
Genre("Reencarnación", "22"),
|
||||||
Genre("Gore", "23"),
|
Genre("Gore", "23"),
|
||||||
Genre("Apocalíptico", "24"),
|
Genre("Apocalíptico", "24"),
|
||||||
Genre("Tragedia", "25"),
|
Genre("Tragedia", "25"),
|
||||||
Genre("Vida Escolar", "26"),
|
Genre("Vida Escolar", "26"),
|
||||||
Genre("Historia", "27"),
|
Genre("Historia", "27"),
|
||||||
Genre("Militar", "28"),
|
Genre("Militar", "28"),
|
||||||
Genre("Policiaco", "29"),
|
Genre("Policiaco", "29"),
|
||||||
Genre("Crimen", "30"),
|
Genre("Crimen", "30"),
|
||||||
Genre("Superpoderes", "31"),
|
Genre("Superpoderes", "31"),
|
||||||
Genre("Vampiros", "32"),
|
Genre("Vampiros", "32"),
|
||||||
Genre("Artes Marciales", "33"),
|
Genre("Artes Marciales", "33"),
|
||||||
Genre("Samurái", "34"),
|
Genre("Samurái", "34"),
|
||||||
Genre("Género Bender", "35"),
|
Genre("Género Bender", "35"),
|
||||||
Genre("Realidad Virtual", "36"),
|
Genre("Realidad Virtual", "36"),
|
||||||
Genre("Ciberpunk", "37"),
|
Genre("Ciberpunk", "37"),
|
||||||
Genre("Musica", "38"),
|
Genre("Musica", "38"),
|
||||||
Genre("Parodia", "39"),
|
Genre("Parodia", "39"),
|
||||||
Genre("Animación", "40"),
|
Genre("Animación", "40"),
|
||||||
Genre("Demonios", "41"),
|
Genre("Demonios", "41"),
|
||||||
Genre("Familia", "42"),
|
Genre("Familia", "42"),
|
||||||
Genre("Extranjero", "43"),
|
Genre("Extranjero", "43"),
|
||||||
Genre("Niños", "44"),
|
Genre("Niños", "44"),
|
||||||
Genre("Realidad", "45"),
|
Genre("Realidad", "45"),
|
||||||
Genre("Telenovela", "46"),
|
Genre("Telenovela", "46"),
|
||||||
Genre("Guerra", "47"),
|
Genre("Guerra", "47"),
|
||||||
Genre("Oeste", "48")
|
Genre("Oeste", "48")
|
||||||
)
|
)
|
||||||
|
|
||||||
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
private open class UriPartFilter(displayName: String, val vals: Array<Pair<String, String>>) :
|
||||||
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
Filter.Select<String>(displayName, vals.map { it.first }.toTypedArray()) {
|
||||||
fun toUriPart() = vals[state].second
|
fun toUriPart() = vals[state].second
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preferences Code
|
// Preferences
|
||||||
|
|
||||||
|
private val preferences: SharedPreferences by lazy {
|
||||||
|
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
|
||||||
|
}
|
||||||
|
|
||||||
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
|
||||||
val deduppref = androidx.preference.ListPreference(screen.context).apply {
|
val deduppref = androidx.preference.ListPreference(screen.context).apply {
|
||||||
|
@ -436,7 +461,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
val selected = newValue as String
|
val selected = newValue as String
|
||||||
val index = this.findIndexOfValue(selected)
|
val index = this.findIndexOfValue(selected)
|
||||||
val entry = entryValues.get(index) as String
|
val entry = entryValues[index] as String
|
||||||
preferences.edit().putString(DEDUP_PREF, entry).commit()
|
preferences.edit().putString(DEDUP_PREF, entry).commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -451,7 +476,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
val selected = newValue as String
|
val selected = newValue as String
|
||||||
val index = this.findIndexOfValue(selected)
|
val index = this.findIndexOfValue(selected)
|
||||||
val entry = entryValues.get(index) as String
|
val entry = entryValues[index] as String
|
||||||
preferences.edit().putString(PAGEGET_PREF, entry).commit()
|
preferences.edit().putString(PAGEGET_PREF, entry).commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -470,7 +495,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
val selected = newValue as String
|
val selected = newValue as String
|
||||||
val index = this.findIndexOfValue(selected)
|
val index = this.findIndexOfValue(selected)
|
||||||
val entry = entryValues.get(index) as String
|
val entry = entryValues[index] as String
|
||||||
preferences.edit().putString(DEDUP_PREF, entry).commit()
|
preferences.edit().putString(DEDUP_PREF, entry).commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -485,7 +510,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
|
||||||
setOnPreferenceChangeListener { _, newValue ->
|
setOnPreferenceChangeListener { _, newValue ->
|
||||||
val selected = newValue as String
|
val selected = newValue as String
|
||||||
val index = this.findIndexOfValue(selected)
|
val index = this.findIndexOfValue(selected)
|
||||||
val entry = entryValues.get(index) as String
|
val entry = entryValues[index] as String
|
||||||
preferences.edit().putString(PAGEGET_PREF, entry).commit()
|
preferences.edit().putString(PAGEGET_PREF, entry).commit()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue