parent
468c01dfc2
commit
ac6f534b06
|
@ -5,7 +5,7 @@ ext {
|
|||
appName = 'Tachiyomi: TuMangaOnline'
|
||||
pkgNameSuffix = 'es.tumangaonline'
|
||||
extClass = '.TuMangaOnline'
|
||||
extVersionCode = 12
|
||||
extVersionCode = 13
|
||||
libVersion = '1.2'
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,6 @@ import android.app.Application
|
|||
import android.content.SharedPreferences
|
||||
import android.support.v7.preference.ListPreference
|
||||
import android.support.v7.preference.PreferenceScreen
|
||||
import com.github.salomonbrys.kotson.string
|
||||
import com.google.gson.JsonParser
|
||||
import okhttp3.*
|
||||
import java.util.*
|
||||
import org.jsoup.nodes.Element
|
||||
|
@ -17,7 +15,6 @@ import eu.kanade.tachiyomi.util.asJsoup
|
|||
import eu.kanade.tachiyomi.source.model.*
|
||||
import eu.kanade.tachiyomi.source.online.ParsedHttpSource
|
||||
import eu.kanade.tachiyomi.lib.ratelimit.RateLimitInterceptor
|
||||
import eu.kanade.tachiyomi.network.POST
|
||||
import eu.kanade.tachiyomi.source.ConfigurableSource
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
|
@ -41,25 +38,27 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
.retryOnConnectionFailure(true)
|
||||
.followRedirects(true)
|
||||
.build()!!
|
||||
|
||||
private val userAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:71.0) Gecko/20100101 Firefox/71.0"
|
||||
|
||||
override fun headersBuilder(): Headers.Builder {
|
||||
return Headers.Builder()
|
||||
.add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; WOW64) Gecko/20100101 Firefox/60")
|
||||
.add("User-Agent", userAgent)
|
||||
.add("Referer", "$baseUrl/")
|
||||
.add("Cache-mode", "no-cache")
|
||||
}
|
||||
|
||||
private fun getBuilder(url: String): String {
|
||||
val req = Request.Builder()
|
||||
.headers(headersBuilder().add("Referer", "$baseUrl/library/manga/").build())
|
||||
private fun getBuilder(url: String, headers: Headers, formBody: FormBody): String {
|
||||
val req = Request.Builder()
|
||||
.headers(headers)
|
||||
.url(url)
|
||||
.post(formBody)
|
||||
.build()
|
||||
|
||||
return client.newCall(req)
|
||||
.execute()
|
||||
.request()
|
||||
.url()
|
||||
.toString()
|
||||
return client.newCall(req)
|
||||
.execute()
|
||||
.body()!!
|
||||
.string()
|
||||
}
|
||||
|
||||
private val preferences: SharedPreferences by lazy {
|
||||
|
@ -83,8 +82,8 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
thumbnail_url = it.select("style").toString().substringAfter("('").substringBeforeLast("')")
|
||||
}
|
||||
}
|
||||
|
||||
override fun latestUpdatesParse(response: Response): MangasPage {
|
||||
|
||||
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() }
|
||||
|
@ -196,12 +195,17 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
|
||||
override fun searchMangaNextPageSelector() = popularMangaNextPageSelector()
|
||||
|
||||
private val scriptselector = "addEventListener"
|
||||
|
||||
override fun chapterListParse(response: Response): List<SChapter> {
|
||||
val document = response.asJsoup()
|
||||
val chapterurl = response.request().url().toString()
|
||||
val script = document.select("script:containsData($scriptselector)").html()
|
||||
val chapteridselector = script.substringAfter("getAttribute(\"").substringBefore("\"")
|
||||
|
||||
// One-shot
|
||||
if (document.select("div.chapters").isEmpty()) {
|
||||
return document.select(oneShotChapterListSelector()).map { oneShotChapterFromElement(it) }
|
||||
return document.select(oneShotChapterListSelector()).map { oneShotChapterFromElement(it, chapterurl, chapteridselector) }
|
||||
}
|
||||
|
||||
// Regular list of chapters
|
||||
|
@ -212,10 +216,10 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
val scanelement = chapelement.select("ul.chapter-list > li")
|
||||
val dupselect = getduppref()!!
|
||||
if (dupselect=="one") {
|
||||
scanelement.first { chapters.add(regularChapterFromElement(it, chaptername, chapternumber)) }
|
||||
scanelement.first { chapters.add(regularChapterFromElement(it, chaptername, chapternumber, chapterurl, chapteridselector)) }
|
||||
}
|
||||
else {
|
||||
scanelement.forEach { chapters.add(regularChapterFromElement(it, chaptername, chapternumber)) }
|
||||
scanelement.forEach { chapters.add(regularChapterFromElement(it, chaptername, chapternumber, chapterurl, chapteridselector)) }
|
||||
}
|
||||
}
|
||||
return chapters
|
||||
|
@ -226,8 +230,9 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
|
||||
private fun oneShotChapterListSelector() = "div.chapter-list-element > ul.list-group li.list-group-item"
|
||||
|
||||
private fun oneShotChapterFromElement(element: Element) = SChapter.create().apply {
|
||||
setUrlWithoutDomain(element.select("div.row > .text-right > a").attr("href"))
|
||||
private fun oneShotChapterFromElement(element: Element, chapterurl: String, chapteridselector: String) = SChapter.create().apply {
|
||||
val button = element.select("div.row > .text-right > [$chapteridselector]") //button
|
||||
url = "$chapterurl#${button.attr(chapteridselector)}"
|
||||
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
|
||||
|
@ -235,8 +240,9 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
|
||||
private fun regularChapterListSelector() = "div.chapters > ul.list-group li.p-0.list-group-item"
|
||||
|
||||
private fun regularChapterFromElement(element: Element, chname: String, number: Float) = SChapter.create().apply {
|
||||
setUrlWithoutDomain(element.select("div.row > .text-right > a").attr("href"))
|
||||
private fun regularChapterFromElement(element: Element, chname: String, number: Float, chapterurl: String, chapteridselector: String) = SChapter.create().apply {
|
||||
val button = element.select("div.row > .text-right > [$chapteridselector]") //button
|
||||
url = "$chapterurl#${button.attr(chapteridselector)}"
|
||||
name = chname
|
||||
chapter_number = number
|
||||
scanlator = element.select("div.col-md-6.text-truncate")?.text()
|
||||
|
@ -246,30 +252,46 @@ class TuMangaOnline : ConfigurableSource, ParsedHttpSource() {
|
|||
private fun parseChapterDate(date: String): Long = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).parse(date).time
|
||||
|
||||
override fun pageListRequest(chapter: SChapter): Request {
|
||||
val url = getBuilder(baseUrl + chapter.url).substringBeforeLast("/") + "/cascade"
|
||||
val (chapterURL, chapterID) = chapter.url.split("#")
|
||||
val response = client.newCall(GET(chapterURL, headers)).execute()
|
||||
val document = response.asJsoup()
|
||||
val csrfToken = document.select("meta[name=csrf-token]").attr("content")
|
||||
val script = document.select("script:containsData($scriptselector)").html()
|
||||
val functionID = script.substringAfter("addEventListener").substringAfter("{").substringBefore("(").trim().removePrefix("_")
|
||||
val function = script.substringAfter("function _$functionID(").substringBefore("});")
|
||||
val goto = function.substringAfter("url: '").substringBefore("'")
|
||||
val paramChapter = function.substringAfter("data").substringBefore("\":_").substringAfterLast("\"")
|
||||
|
||||
val getHeaders = headersBuilder()
|
||||
.add("User-Agent", userAgent)
|
||||
.add("Referer", chapterURL)
|
||||
.add("Content-Type","application/x-www-form-urlencoded; charset=UTF-8")
|
||||
.add("X-CSRF-TOKEN",csrfToken)
|
||||
.add("X-Requested-With","XMLHttpRequest")
|
||||
.add(functionID,functionID)
|
||||
.build()
|
||||
|
||||
val formBody = FormBody.Builder()
|
||||
.add(paramChapter, chapterID)
|
||||
.build()
|
||||
|
||||
val url = getBuilder(goto,getHeaders,formBody).substringBeforeLast("/") + "/cascade"
|
||||
// Get /cascade instead of /paginate to get all pages at once
|
||||
|
||||
val headers = headersBuilder()
|
||||
.add("User-Agent", userAgent)
|
||||
.add("Referer", chapterURL)
|
||||
.build()
|
||||
|
||||
return GET(url, headers)
|
||||
}
|
||||
|
||||
override fun pageListParse(response: Response): List<Page> {
|
||||
override fun pageListParse(response: Response): List<Page> = mutableListOf<Page>().apply {
|
||||
val body = response.asJsoup()
|
||||
val imageRoute = body.select("script:containsData(imageRoute)").html().substringAfter("imageRoute = \"").substringBefore(":IMAGE_NAME")
|
||||
val token = body.select("meta[name=csrf-token]").attr("content")
|
||||
val base64 = body.select("script:containsData(base64)").html().substringAfter("','").substringBefore("','all');")
|
||||
val chapterid = body.baseUri().substringAfter("viewer/").substringBefore("/cascade")
|
||||
val headers = headersBuilder()
|
||||
.add("Content-Type", "application/json; charset=utf-8")
|
||||
.add("X-CSRF-TOKEN",token)
|
||||
.build()
|
||||
val jsonData = client.newCall(POST("$baseUrl/upload_images/$chapterid/$base64/all", headers)).execute()
|
||||
val jbody = jsonData.body()!!.string()
|
||||
val results = JsonParser().parse(jbody).asJsonArray
|
||||
val pages = mutableListOf<Page>()
|
||||
for (i in 0 until results.size()) {
|
||||
pages.add(Page(i, "",imageRoute + results[i].string))
|
||||
|
||||
body.select("div#viewer-container > div.viewer-image-container > img.viewer-image")?.forEach {
|
||||
add(Page(size, "", it.attr("src")))
|
||||
}
|
||||
return pages
|
||||
}
|
||||
|
||||
override fun pageListParse(document: Document) = throw UnsupportedOperationException("Not used")
|
||||
|
|
Loading…
Reference in New Issue