Add host preference madara (#6841)

* Move MethodScans to GenkanOriginal

* Add host selecter madara

* remove extension preference

* add preferences back
This commit is contained in:
nzoba 2021-05-19 14:01:34 +02:00 committed by GitHub
parent 6dc3d58bc0
commit 3d586916f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 122 additions and 12 deletions

View File

@ -17,7 +17,6 @@ class GenkanGenerator : ThemeSourceGenerator {
SingleLang("ZeroScans", "https://zeroscans.com", "en"), SingleLang("ZeroScans", "https://zeroscans.com", "en"),
SingleLang("The Nonames Scans", "https://the-nonames.com", "en"), SingleLang("The Nonames Scans", "https://the-nonames.com", "en"),
SingleLang("Edelgarde Scans", "https://edelgardescans.com", "en"), SingleLang("Edelgarde Scans", "https://edelgardescans.com", "en"),
SingleLang("Method Scans", "https://methodscans.com", "en"),
SingleLang("LynxScans", "https://lynxscans.com", "en", overrideVersionCode = 1), SingleLang("LynxScans", "https://lynxscans.com", "en", overrideVersionCode = 1),
) )

View File

@ -14,6 +14,7 @@ class GenkanOriginalGenerator : ThemeSourceGenerator {
override val sources = listOf( override val sources = listOf(
SingleLang("Reaper Scans", "https://reaperscans.com", "en"), SingleLang("Reaper Scans", "https://reaperscans.com", "en"),
SingleLang("Hatigarm Scans", "https://hatigarmscanz.net", "en", overrideVersionCode = 1), SingleLang("Hatigarm Scans", "https://hatigarmscanz.net", "en", overrideVersionCode = 1),
SingleLang("Method Scans", "https://methodscans.com", "en", overrideVersionCode = 1)
) )
companion object { companion object {

View File

@ -1,8 +1,16 @@
package eu.kanade.tachiyomi.multisrc.madara package eu.kanade.tachiyomi.multisrc.madara
import android.app.Application
import android.content.SharedPreferences
import android.os.Handler
import android.os.Looper
import android.view.Gravity
import android.widget.TextView
import android.widget.Toast
import eu.kanade.tachiyomi.network.GET import eu.kanade.tachiyomi.network.GET
import eu.kanade.tachiyomi.network.POST import eu.kanade.tachiyomi.network.POST
import eu.kanade.tachiyomi.network.asObservable import eu.kanade.tachiyomi.network.asObservable
import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.Filter import eu.kanade.tachiyomi.source.model.Filter
import eu.kanade.tachiyomi.source.model.FilterList import eu.kanade.tachiyomi.source.model.FilterList
import eu.kanade.tachiyomi.source.model.MangasPage import eu.kanade.tachiyomi.source.model.MangasPage
@ -17,11 +25,13 @@ import okhttp3.Headers
import okhttp3.HttpUrl.Companion.toHttpUrlOrNull import okhttp3.HttpUrl.Companion.toHttpUrlOrNull
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import okhttp3.RequestBody import okhttp3.RequestBody.Companion.toRequestBody
import okhttp3.Response 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 rx.Observable
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.text.ParseException import java.text.ParseException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
@ -35,10 +45,53 @@ abstract class Madara(
override val baseUrl: String, override val baseUrl: String,
override val lang: String, override val lang: String,
private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US) private val dateFormat: SimpleDateFormat = SimpleDateFormat("MMMM dd, yyyy", Locale.US)
) : ParsedHttpSource() { ) : ParsedHttpSource(), ConfigurableSource {
override val supportsLatest = true override val supportsLatest = true
// Preferences Code
private val preferences: SharedPreferences by lazy {
Injekt.get<Application>().getSharedPreferences("source_$id", 0x0000)
}
override fun setupPreferenceScreen(screen: androidx.preference.PreferenceScreen) {
val chooseHostPref = androidx.preference.ListPreference(screen.context).apply {
key = CHOOSE_HOST_Key
title = CHOOSE_HOST_Title
entries = prefsEntries
entryValues = prefsEntryValues
summary = "%s"
setOnPreferenceChangeListener { _, newValue ->
val selected = newValue as String
val index = this.findIndexOfValue(selected)
val entry = entryValues[index] as String
hostValues = prefsEntryValues.toMutableList()
hostValues.removeAt(index)
preferences.edit().putString(CHOOSE_HOST_Key, entry).commit()
}
}
screen.addPreference(chooseHostPref)
}
private fun chooseHostPref() = preferences.getString(CHOOSE_HOST_Key, "")
private fun cleanHostValues(): MutableList<String> {
val hostsList = prefsEntryValues.toMutableList()
hostsList.remove(chooseHostPref())
return hostsList
}
companion object {
private const val CHOOSE_HOST_Title = "Choose the host/server you prefer for images"
private const val CHOOSE_HOST_Key = "choose_host"
private val prefsEntries = arrayOf("Default", "Local", "Amazon", "Imgur", "Flickr", "Picasa (Blogspot)", "Google Photos")
private val prefsEntryValues = arrayOf("", "local", "amazon", "imgur", "flickr", "picasa", "gphotos")
}
private var hostValues = cleanHostValues()
override val client: OkHttpClient = network.cloudflareClient.newBuilder() override val client: OkHttpClient = network.cloudflareClient.newBuilder()
.connectTimeout(10, TimeUnit.SECONDS) .connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(30, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS)
@ -372,24 +425,24 @@ abstract class Madara(
} }
} }
val genres = select("div.genres-content a") val genres = select("div.genres-content a")
.map { element -> element.text().toLowerCase() } .map { element -> element.text().toLowerCase(Locale.ROOT) }
.toMutableSet() .toMutableSet()
// add tag(s) to genre // add tag(s) to genre
select("div.tags-content a").forEach { element -> select("div.tags-content a").forEach { element ->
if (genres.contains(element.text()).not()) { if (genres.contains(element.text()).not()) {
genres.add(element.text().toLowerCase()) genres.add(element.text().toLowerCase(Locale.ROOT))
} }
} }
// add manga/manhwa/manhua thinggy to genre // add manga/manhwa/manhua thinggy to genre
document.select(seriesTypeSelector).firstOrNull()?.ownText()?.let { document.select(seriesTypeSelector).firstOrNull()?.ownText()?.let {
if (it.isEmpty().not() && it.notUpdating() && it != "-" && genres.contains(it).not()) { if (it.isEmpty().not() && it.notUpdating() && it != "-" && genres.contains(it).not()) {
genres.add(it.toLowerCase()) genres.add(it.toLowerCase(Locale.ROOT))
} }
} }
manga.genre = genres.toList().map { it.capitalize() }.joinToString(", ") manga.genre = genres.toList().joinToString(", ") { it.capitalize(Locale.ROOT) }
// add alternative name to manga description // add alternative name to manga description
document.select(altNameSelector).firstOrNull()?.ownText()?.let { document.select(altNameSelector).firstOrNull()?.ownText()?.let {
@ -427,7 +480,7 @@ abstract class Madara(
val xhrHeaders = headersBuilder().add("Content-Type: application/x-www-form-urlencoded; charset=UTF-8") val xhrHeaders = headersBuilder().add("Content-Type: application/x-www-form-urlencoded; charset=UTF-8")
.add("Referer", baseUrl) .add("Referer", baseUrl)
.build() .build()
val body = RequestBody.create(null, "action=manga_get_chapters&manga=$mangaId") val body = "action=manga_get_chapters&manga=$mangaId".toRequestBody(null)
return client.newCall(POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, body)).execute().asJsoup() return client.newCall(POST("$baseUrl/wp-admin/admin-ajax.php", xhrHeaders, body)).execute().asJsoup()
} }
@ -455,9 +508,15 @@ abstract class Madara(
with(element) { with(element) {
select(chapterUrlSelector).first()?.let { urlElement -> select(chapterUrlSelector).first()?.let { urlElement ->
chapter.url = urlElement.attr("abs:href").let { val url = urlElement.attr("abs:href").let {
it.substringBefore("?style=paged") + if (!it.endsWith(chapterUrlSuffix)) chapterUrlSuffix else "" it.substringBefore("?style=paged") + if (!it.endsWith(chapterUrlSuffix)) chapterUrlSuffix else ""
} }.toHttpUrlOrNull()!!.newBuilder()
if (chooseHostPref() != "")
url.addQueryParameter("host", chooseHostPref())
chapter.url = url.toString()
chapter.name = urlElement.text() chapter.name = urlElement.text()
} }
@ -547,6 +606,47 @@ abstract class Madara(
return super.pageListRequest(chapter) return super.pageListRequest(chapter)
} }
override fun fetchPageList(chapter: SChapter): Observable<List<Page>> {
var observable = super.fetchPageList(chapter)
var pages = emptyList<Page>()
var index = 0
while (pages.isEmpty() && index < hostValues.size) {
observable.subscribe {
pages = it
}
if (pages.isNotEmpty()) {
if (index > 0) {
// put validHost in first position
val validHost = hostValues[index - 1]
hostValues.removeAt(index - 1)
hostValues.add(0, validHost)
val hostName = prefsEntries[prefsEntryValues.indexOf(validHost)]
Handler(Looper.getMainLooper()).post {
val toast = Toast.makeText(Injekt.get<Application>().applicationContext, "Host : $hostName\nYou may want to switch to this host to avoid unnecessary loading time", Toast.LENGTH_SHORT)
val view = toast.view.findViewById<TextView>(android.R.id.message)
view?.let {
view.gravity = Gravity.CENTER_HORIZONTAL
}
toast.show()
}
}
return observable
}
val url = chapter.url.toHttpUrlOrNull()!!.newBuilder()
url.setQueryParameter("host", hostValues[index])
chapter.url = url.toString()
observable = super.fetchPageList(chapter)
index++
}
return observable
}
open val pageListParseSelector = "div.page-break, li.blocks-gallery-item" open val pageListParseSelector = "div.page-break, li.blocks-gallery-item"
override fun pageListParse(document: Document): List<Page> { override fun pageListParse(document: Document): List<Page> {
@ -562,7 +662,17 @@ abstract class Madara(
} }
override fun imageRequest(page: Page): Request { override fun imageRequest(page: Page): Request {
return GET(page.imageUrl!!, headers.newBuilder().set("Referer", page.url).build()) val headers = headersBuilder()
headers.apply {
add("Referer", page.url)
}
if (page.imageUrl!!.contains("amazonaws.com")) {
headers.apply {
add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9")
}
}
return GET(page.imageUrl!!, headers.build())
} }
override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used") override fun imageUrlParse(document: Document) = throw UnsupportedOperationException("Not used")

View File

@ -10,7 +10,7 @@ class MadaraGenerator : ThemeSourceGenerator {
override val themeClass = "Madara" override val themeClass = "Madara"
override val baseVersionCode: Int = 3 override val baseVersionCode: Int = 4
override val sources = listOf( override val sources = listOf(
SingleLang("24hRomance", "https://24hromance.com", "en", className = "Romance24h"), SingleLang("24hRomance", "https://24hromance.com", "en", className = "Romance24h"),