Update Lector (#2447)

Update Lector
This commit is contained in:
happywillow0 2020-03-18 20:30:14 -04:00 committed by GitHub
parent f93f28cbd4
commit ee394dc2a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 187 additions and 162 deletions

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: LectorManga'
pkgNameSuffix = 'es.lectormanga'
extClass = '.LectorManga'
extVersionCode = 9
extVersionCode = 10
libVersion = '1.2'
}

View File

@ -7,16 +7,28 @@ 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.*
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.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.Element
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.TimeUnit
/**
@ -24,26 +36,24 @@ import java.util.concurrent.TimeUnit
*/
class LectorManga : ConfigurableSource, ParsedHttpSource() {
//Info
override val name = "LectorManga"
override val baseUrl = "https://lectormanga.com/"
override val baseUrl = "https://lectormanga.com"
override val lang = "es"
override val supportsLatest = true
private val rateLimitInterceptor = RateLimitInterceptor(1)
//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()!!
.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()
.add("User-Agent", userAgent)
@ -64,24 +74,23 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
.toString()
}
private val preferences: SharedPreferences by lazy {
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)"
//Popular
override fun popularMangaRequest(page: Int) = GET("$baseUrl/library?order_item=likes_count&order_dir=desc&type=&filter_by=title&page=$page", headers)
override fun latestUpdatesRequest(page: Int) = GET(baseUrl, headers)
override fun popularMangaNextPageSelector() = ".pagination .page-item:not(.disabled) a[rel='next']"
override fun popularMangaSelector() = ".col-6 .card"
override fun popularMangaFromElement(element: Element) = SManga.create().apply {
setUrlWithoutDomain(element.select("a").attr("href"))
title = element.select("a").text()
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 {
val document = response.asJsoup()
val mangas = document.select(latestUpdatesSelector())
@ -99,25 +108,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
return manga
}
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
}
override fun popularMangaNextPageSelector() = ".pagination .page-item:not(.disabled) a[rel='next']"
override fun latestUpdatesNextPageSelector() = "none"
//Search
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
val url = HttpUrl.parse("$baseUrl/library")!!.newBuilder()
@ -182,21 +173,37 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
}
override fun searchMangaSelector() = popularMangaSelector()
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
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> {
time = serverTime() //Get time when the chapter page is opened
val document = response.asJsoup()
val chapterurl = response.request().url().toString()
val chapteridselector = ""
val chapterUrl = response.request().url().toString()
// One-shot
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
@ -208,9 +215,9 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
chapterNames.forEachIndexed { index, _ ->
val scanlator = chapterInfos[index].select("li")
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 {
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
@ -221,24 +228,30 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
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 {
url = "$chapterurl#${element.select("div.row > .text-right > form").attr("id")}"
private fun oneShotChapterFromElement(element: Element, chapterUrl: String) = SChapter.create().apply {
url = "$chapterUrl#${element.select("div.row > .text-right > form").attr("id")}"
name = "One Shot"
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()
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.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
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 fun serverTime(): String {
val formatter = SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US)
@ -246,7 +259,10 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
return formatter.format(Date())
}
//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()}")
@ -271,6 +287,8 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
}
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")) {
@ -282,15 +300,16 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
.add("Referer", newurl)
.build()
// Get /cascade instead of /paginate to get all pages at once
return GET(url, headers)
}
override fun pageListParse(document: Document): List<Page> = mutableListOf<Page>().apply {
if (getPageMethod() == "cascade") {
val style = document.select("style:containsData(height)").html()
document.select( "img[id]").filterNot { "#${it.attr("id")}," in style || "#${it.attr("id")}{" in style }.forEach {
add(Page(size, "", it.attr("src")))
document.select("img.viewer-img").forEach {
add(Page(size, "", it.let {
if (it.hasAttr("data-src"))
it.attr("abs:data-src") else it.attr("abs:src")
}))
}
} else {
val pageList = document.select("#viewer-pages-select").first().select("option").map { it.attr("value").toInt() }
@ -303,6 +322,8 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
override fun imageUrlParse(document: Document): String = document.select("img.viewer-image").attr("src")
//Filters
private class Types : UriPartFilter("Tipo", arrayOf(
Pair("Ver todo", ""),
Pair("Manga", "manga"),
@ -423,7 +444,11 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
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) {
val deduppref = androidx.preference.ListPreference(screen.context).apply {
@ -436,7 +461,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
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()
}
}
@ -451,7 +476,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
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()
}
}
@ -470,7 +495,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
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()
}
}
@ -485,7 +510,7 @@ class LectorManga : ConfigurableSource, ParsedHttpSource() {
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
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()
}
}