Fix Tapas and Japanread (#6764)

* tapas : settings to show lock after login on locked chapters

* japanread : fix missing chapters and wrong popularmangalist
This commit is contained in:
nzoba 2021-04-29 22:00:15 +02:00 committed by GitHub
parent 948cff84e5
commit b13ccc27ec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 83 additions and 21 deletions

View File

@ -5,7 +5,7 @@ ext {
extName = 'Tapas' extName = 'Tapas'
pkgNameSuffix = 'en.tapastic' pkgNameSuffix = 'en.tapastic'
extClass = '.Tapastic' extClass = '.Tapastic'
extVersionCode = 10 extVersionCode = 11
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -19,6 +19,7 @@ import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga 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.Headers
import okhttp3.Request import okhttp3.Request
import okhttp3.Response import okhttp3.Response
import org.jsoup.Jsoup import org.jsoup.Jsoup
@ -41,8 +42,8 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
val chapterListPref = androidx.preference.ListPreference(screen.context).apply { val chapterListPref = androidx.preference.ListPreference(screen.context).apply {
key = SHOW_LOCKED_CHAPTERS_Title key = SHOW_LOCKED_CHAPTERS_Title
title = SHOW_LOCKED_CHAPTERS_Title title = SHOW_LOCKED_CHAPTERS_Title
entries = prefsEntries entries = prefsEntriesChapters
entryValues = prefsEntryValues entryValues = prefsEntryValuesChapters
summary = "%s" summary = "%s"
setOnPreferenceChangeListener { _, newValue -> setOnPreferenceChangeListener { _, newValue ->
@ -53,15 +54,37 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
} }
} }
screen.addPreference(chapterListPref) screen.addPreference(chapterListPref)
val lockPref = androidx.preference.ListPreference(screen.context).apply {
key = SHOW_LOCK_Title
title = SHOW_LOCK_Title
entries = prefsEntriesLock
entryValues = prefsEntryValuesLock
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = this.findIndexOfValue(selected)
val entry = entryValues[index] as String
preferences.edit().putString(SHOW_LOCK, entry).commit()
}
}
screen.addPreference(lockPref)
} }
private fun chapterListPref() = preferences.getString(SHOW_LOCKED_CHAPTERS, "free") private fun chapterListPref() = preferences.getString(SHOW_LOCKED_CHAPTERS, "free")
private fun lockPref() = preferences.getString(SHOW_LOCK, "yes")
companion object { companion object {
private const val SHOW_LOCKED_CHAPTERS_Title = "Tapas requires login/payment for some chapters" private const val SHOW_LOCKED_CHAPTERS_Title = "Tapas requires login/payment for some chapters"
private const val SHOW_LOCKED_CHAPTERS = "tapas_locked_chapters" private const val SHOW_LOCKED_CHAPTERS = "tapas_locked_chapters"
private val prefsEntries = arrayOf("Show all chapters (including pay-to-read)", "Only show free chapters") private val prefsEntriesChapters = arrayOf("Show all chapters (including pay-to-read)", "Only show free chapters")
private val prefsEntryValues = arrayOf("all", "free") private val prefsEntryValuesChapters = arrayOf("all", "free")
private const val SHOW_LOCK_Title = "Show \uD83D\uDD12 for locked chapters after login"
private const val SHOW_LOCK = "tapas_lock"
private val prefsEntriesLock = arrayOf("Yes", "No")
private val prefsEntryValuesLock = arrayOf("yes", "no")
} }
// Info // Info
@ -71,10 +94,13 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
override val baseUrl = "https://tapas.io" override val baseUrl = "https://tapas.io"
override val id = 3825434541981130345 override val id = 3825434541981130345
override fun headersBuilder(): Headers.Builder = Headers.Builder()
.add("Referer", "https://m.tapas.io")
// Popular // Popular
override fun popularMangaRequest(page: Int): Request = override fun popularMangaRequest(page: Int): Request =
GET("$baseUrl/comics?b=POPULAR&g=&f=NONE&pageNumber=$page&pageSize=20&") GET("$baseUrl/comics?b=POPULAR&g=0&f=NONE&pageNumber=$page&pageSize=20&")
override fun popularMangaNextPageSelector() = "div[data-has-next=true]" override fun popularMangaNextPageSelector() = "div[data-has-next=true]"
override fun popularMangaSelector() = "li.js-list-item" override fun popularMangaSelector() = "li.js-list-item"
@ -87,9 +113,9 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
// Latest // Latest
override fun latestUpdatesRequest(page: Int): Request = override fun latestUpdatesRequest(page: Int): Request =
GET("$baseUrl/comics?b=FRESH&g=&f=NONE&pageNumber=$page&pageSize=20&") GET("$baseUrl/comics?b=FRESH&g=0&f=NONE&pageNumber=$page&pageSize=20&")
override fun latestUpdatesNextPageSelector(): String? = popularMangaNextPageSelector() override fun latestUpdatesNextPageSelector(): String = popularMangaNextPageSelector()
override fun latestUpdatesSelector(): String = popularMangaSelector() override fun latestUpdatesSelector(): String = popularMangaSelector()
override fun latestUpdatesFromElement(element: Element): SManga = override fun latestUpdatesFromElement(element: Element): SManga =
popularMangaFromElement(element) popularMangaFromElement(element)
@ -151,7 +177,7 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
private val gson by lazy { Gson() } private val gson by lazy { Gson() }
private fun Element.isLockedChapter(): Boolean { private fun Element.isLockedChapter(): Boolean {
return this.hasClass("js-have-to-sign") return this.hasClass("js-have-to-sign") || (lockPref() == "yes" && this.hasClass("js-locked"))
} }
override fun chapterListParse(response: Response): List<SChapter> { override fun chapterListParse(response: Response): List<SChapter> {
@ -239,7 +265,7 @@ class Tapastic : ConfigurableSource, ParsedHttpSource() {
"Genre", "Genre",
"g", "g",
arrayOf( arrayOf(
Pair("", "Any"), Pair("0", "Any"),
Pair("7", "Action"), Pair("7", "Action"),
Pair("22", "Boys Love"), Pair("22", "Boys Love"),
Pair("2", "Comedy"), Pair("2", "Comedy"),

View File

@ -5,7 +5,7 @@ ext {
extName = 'Japanread' extName = 'Japanread'
pkgNameSuffix = 'fr.japanread' pkgNameSuffix = 'fr.japanread'
extClass = '.Japanread' extClass = '.Japanread'
extVersionCode = 4 extVersionCode = 5
libVersion = '1.2' libVersion = '1.2'
containsNsfw = true containsNsfw = true
} }

View File

@ -3,14 +3,18 @@ package eu.kanade.tachiyomi.extension.fr.japanread
import com.github.salomonbrys.kotson.string import com.github.salomonbrys.kotson.string
import com.google.gson.JsonParser import com.google.gson.JsonParser
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.asObservableSuccess
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.Page
import eu.kanade.tachiyomi.source.model.SChapter import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SManga 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 okhttp3.Request 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 rx.Observable
import java.util.Calendar import java.util.Calendar
class Japanread : ParsedHttpSource() { class Japanread : ParsedHttpSource() {
@ -25,20 +29,20 @@ class Japanread : ParsedHttpSource() {
// Popular // Popular
override fun popularMangaRequest(page: Int): Request { override fun popularMangaRequest(page: Int): Request {
return GET(baseUrl, headers) return GET("$baseUrl/manga-list?page=$page", headers)
} }
override fun popularMangaSelector() = "#nav-tabContent #nav-home li" override fun popularMangaSelector() = "div#manga-container div.col-lg-6"
override fun popularMangaFromElement(element: Element): SManga { override fun popularMangaFromElement(element: Element): SManga {
return SManga.create().apply { return SManga.create().apply {
title = element.select("p a").text() title = element.select("img").attr("alt")
setUrlWithoutDomain(element.select("p a").attr("href")) setUrlWithoutDomain(element.select("a").attr("abs:href"))
thumbnail_url = element.select("img").attr("src").replace("manga_small", "manga_large") thumbnail_url = element.select("img").attr("src").replace("manga_medium", "manga_large")
} }
} }
override fun popularMangaNextPageSelector(): String? = null override fun popularMangaNextPageSelector(): String = "a[rel=next]"
// Latest // Latest
override fun latestUpdatesRequest(page: Int): Request { override fun latestUpdatesRequest(page: Int): Request {
@ -55,7 +59,7 @@ class Japanread : ParsedHttpSource() {
} }
} }
override fun latestUpdatesNextPageSelector() = "a[rel=\"next\"]" override fun latestUpdatesNextPageSelector() = "a[rel=next]"
// Search // Search
override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request { override fun searchMangaRequest(page: Int, query: String, filters: FilterList): Request {
@ -73,7 +77,7 @@ class Japanread : ParsedHttpSource() {
} }
} }
override fun searchMangaNextPageSelector() = "a[rel=\"next\"]" override fun searchMangaNextPageSelector() = "a[rel=next]"
// Details // Details
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
@ -90,7 +94,7 @@ class Japanread : ParsedHttpSource() {
else -> SManga.UNKNOWN else -> SManga.UNKNOWN
} }
} }
thumbnail_url = document.select("img[alt=\"couverture manga\"]").attr("src") thumbnail_url = document.select("img[alt=couverture manga]").attr("src")
} }
} }
@ -119,7 +123,7 @@ class Japanread : ParsedHttpSource() {
return calendar.timeInMillis return calendar.timeInMillis
} }
override fun chapterListSelector() = "#chapters div[data-row=\"chapter\"]" override fun chapterListSelector() = "#chapters div[data-row=chapter]"
override fun chapterFromElement(element: Element): SChapter { override fun chapterFromElement(element: Element): SChapter {
return SChapter.create().apply { return SChapter.create().apply {
name = element.select("div.col-lg-5 a").text() name = element.select("div.col-lg-5 a").text()
@ -129,6 +133,38 @@ class Japanread : ParsedHttpSource() {
} }
} }
override fun fetchChapterList(manga: SManga): Observable<List<SChapter>> {
val requestUrl = if (manga.url.startsWith("http")) {
"${manga.url}?page="
} else {
"$baseUrl${manga.url}?page="
}
return client.newCall(GET(requestUrl, headers))
.asObservableSuccess()
.map { response ->
chapterListParse(response, requestUrl)
}
}
private fun chapterListParse(response: Response, requestUrl: String): List<SChapter> {
val chapters = mutableListOf<SChapter>()
var document = response.asJsoup()
var moreChapters = true
var nextPage = 2
// chapters are paginated
while (moreChapters) {
document.select(chapterListSelector()).map { chapters.add(chapterFromElement(it)) }
if (!document.select("a[rel=next]").isNullOrEmpty()) {
document = client.newCall(GET(requestUrl + nextPage, headers)).execute().asJsoup()
nextPage++
} else {
moreChapters = false
}
}
return chapters
}
// Alternative way through API in case jSoup doesn't work anymore // Alternative way through API in case jSoup doesn't work anymore
// It gives precise timestamp, but we are not using it // It gives precise timestamp, but we are not using it
// since the API wrongly returns null for the scanlation group // since the API wrongly returns null for the scanlation group