Update Preference Stubs & Update Manamoa extension (#2087)

* Add TwoStatePreference and CheckBoxPreference stubs

* Add setEnabled on Preference, Formatting again.

* Remove isEnabled. Thanks to API difference between androidx and v7 libs

* Initial support of their new site announcing algorithm.

What the heck is DDOS-GUARD

* Apply changes of announcing algorithm that can work with tachi >_<

It will uses main thread that cause temp freeze when enter browse

* Clean up codes little bit.

* Simplify Decoder

* Finalize update.

* Try-Catch on req failed.
* Update build.gradle

* Use regular network client.
This commit is contained in:
DitFranXX 2020-02-01 13:12:34 +09:00 committed by GitHub
parent c86e12aadd
commit 44c1ebba51
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 213 additions and 43 deletions

View File

@ -0,0 +1,9 @@
package android.support.v7.preference;
import android.content.Context;
public class CheckBoxPreference extends Preference {
public CheckBoxPreference(Context context) { throw new RuntimeException("Stub!"); }
}

View File

@ -26,6 +26,10 @@ public class Preference {
throw new RuntimeException("Stub!"); throw new RuntimeException("Stub!");
} }
public void setEnabled(boolean enabled) {
throw new RuntimeException("Stub!");
}
public String getKey() { public String getKey() {
throw new RuntimeException("Stub!"); throw new RuntimeException("Stub!");
} }

View File

@ -0,0 +1,25 @@
package android.support.v7.preference;
import android.content.Context;
public class TwoStatePreference extends Preference {
public TwoStatePreference(Context context) { throw new RuntimeException("Stub!"); }
public boolean isChecked() { throw new RuntimeException("Stub!"); }
public void setChecked(boolean checked) { throw new RuntimeException("Stub!"); }
public CharSequence getSummaryOn() { throw new RuntimeException("Stub!"); }
public void setSummaryOn(CharSequence summary) { throw new RuntimeException("Stub!"); }
public CharSequence getSummaryOff() { throw new RuntimeException("Stub!"); }
public void setSummaryOff(CharSequence summary) { throw new RuntimeException("Stub!"); }
public boolean getDisableDependentsState() { throw new RuntimeException("Stub!"); }
public void setDisableDependentsState(boolean disableDependentsState) { throw new RuntimeException("Stub!"); }
}

View File

@ -0,0 +1,11 @@
package androidx.preference;
import android.content.Context;
public class CheckBoxPreference extends Preference {
public CheckBoxPreference(Context context) {
throw new RuntimeException("Stub!");
}
}

View File

@ -26,6 +26,10 @@ public class Preference {
throw new RuntimeException("Stub!"); throw new RuntimeException("Stub!");
} }
public void setEnabled(boolean enabled) {
throw new RuntimeException("Stub!");
}
public String getKey() { public String getKey() {
throw new RuntimeException("Stub!"); throw new RuntimeException("Stub!");
} }

View File

@ -0,0 +1,25 @@
package androidx.preference;
import android.content.Context;
public class TwoStatePreference extends Preference {
public TwoStatePreference(Context context) { throw new RuntimeException("Stub!"); }
public boolean isChecked() { throw new RuntimeException("Stub!"); }
public void setChecked(boolean checked) { throw new RuntimeException("Stub!"); }
public CharSequence getSummaryOn() { throw new RuntimeException("Stub!"); }
public void setSummaryOn(CharSequence summary) { throw new RuntimeException("Stub!"); }
public CharSequence getSummaryOff() { throw new RuntimeException("Stub!"); }
public void setSummaryOff(CharSequence summary) { throw new RuntimeException("Stub!"); }
public boolean getDisableDependentsState() { throw new RuntimeException("Stub!"); }
public void setDisableDependentsState(boolean disableDependentsState) { throw new RuntimeException("Stub!"); }
}

View File

@ -5,7 +5,7 @@ ext {
appName = 'Tachiyomi: ManaMoa' appName = 'Tachiyomi: ManaMoa'
pkgNameSuffix = 'ko.mangashowme' pkgNameSuffix = 'ko.mangashowme'
extClass = '.ManaMoa' extClass = '.ManaMoa'
extVersionCode = 16 extVersionCode = 17
libVersion = '1.2' libVersion = '1.2'
} }

View File

@ -11,6 +11,11 @@ import okhttp3.ResponseBody
import java.io.ByteArrayOutputStream import java.io.ByteArrayOutputStream
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
import kotlin.math.cos
import kotlin.math.floor
import kotlin.math.sin
import kotlin.math.tan
/* /*
* `v1` means url padding of image host. * `v1` means url padding of image host.
@ -19,7 +24,7 @@ import java.io.InputStream
internal class ImageDecoder(scripts: String) { internal class ImageDecoder(scripts: String) {
private val cnt = substringBetween(scripts, "var view_cnt = ", ";") private val cnt = substringBetween(scripts, "var view_cnt = ", ";")
.toIntOrNull() ?: 0 .toIntOrNull() ?: 0
private val chapter = substringBetween(scripts, "var chapter = ", ";") private val chapter = substringBetween(scripts, "var chapter = ", ";")
.toIntOrNull() ?: 0 .toIntOrNull() ?: 0
@ -73,28 +78,27 @@ internal class ImageDecoderInterceptor : Interceptor {
* *
* MIT License * MIT License
* *
*
* Copyright (c) 2019 junheah * Copyright (c) 2019 junheah
*/ */
private fun imageDecoder(input: Bitmap, chapter: Int, view_cnt: Int, half: Int = 0, _CX: Int = ManaMoa.V1_CX, _CY: Int = ManaMoa.V1_CY): Bitmap { private fun imageDecoder(input: Bitmap, chapter: Int, view_cnt: Int, half: Int = 0): Bitmap {
if (view_cnt == 0) return input if (view_cnt == 0) return input
val viewCnt = view_cnt / 10 val viewCnt = view_cnt / 10
var CX = _CX var cx = ManaMoa.V1_CX
var CY = _CY var cy = ManaMoa.V1_CY
//view_cnt / 10 > 30000 ? (this._CX = 1, this._CY = 6) : view_cnt / 10 > 20000 ? this._CX = 1 : view_cnt / 10 > 10000 && (this._CY = 1) //view_cnt / 10 > 30000 ? (this._CX = 1, this._CY = 6) : view_cnt / 10 > 20000 ? this._CX = 1 : view_cnt / 10 > 10000 && (this._CY = 1)
// DO NOT (AUTOMATICALLY) REPLACE TO when USING IDEA. seems it doesn't detect correct condition // DO NOT (AUTOMATICALLY) REPLACE TO when USING IDEA. seems it doesn't detect correct condition
if (viewCnt > 30000) { if (viewCnt > 30000) {
CX = 1 cx = 1
CY = 6 cy = 6
} else if (viewCnt > 20000) { } else if (viewCnt > 20000) {
CX = 1 cx = 1
} else if (viewCnt > 10000) { } else if (viewCnt > 10000) {
CY = 1 cy = 1
} }
//decode image //decode image
val order = Array(CX * CY) { IntArray(2) } val order = Array(cx * cy) { IntArray(2) }
val oSize = order.size - 1 val oSize = order.size - 1
for (i in 0..oSize) { for (i in 0..oSize) {
@ -102,22 +106,22 @@ internal class ImageDecoderInterceptor : Interceptor {
order[i][1] = decoderRandom(chapter, viewCnt, i) order[i][1] = decoderRandom(chapter, viewCnt, i)
} }
java.util.Arrays.sort(order) { a, b -> java.lang.Double.compare(a[1].toDouble(), b[1].toDouble()) } java.util.Arrays.sort(order) { a, b -> a[1].toDouble().compareTo(b[1].toDouble()) }
//create new bitmap //create new bitmap
val outputWidth = if (half == 0) input.width else input.width / 2 val outputWidth = if (half == 0) input.width else input.width / 2
val output = Bitmap.createBitmap(outputWidth, input.height, Bitmap.Config.ARGB_8888) val output = Bitmap.createBitmap(outputWidth, input.height, Bitmap.Config.ARGB_8888)
val canvas = Canvas(output) val canvas = Canvas(output)
val rowWidth = input.width / CX val rowWidth = input.width / cx
val rowHeight = input.height / CY val rowHeight = input.height / cy
for (i in 0..oSize) { for (i in 0..oSize) {
val o = order[i] val o = order[i]
val ox = i % CX val ox = i % cx
val oy = i / CX val oy = i / cx
val tx = o[0] % CX val tx = o[0] % cx
val ty = o[0] / CX val ty = o[0] / cx
val sx = if (half == 2) -input.width / 2 else 0 val sx = if (half == 2) -input.width / 2 else 0
val srcX = ox * rowWidth val srcX = ox * rowWidth
@ -126,9 +130,9 @@ internal class ImageDecoderInterceptor : Interceptor {
val destY = ty * rowHeight val destY = ty * rowHeight
canvas.drawBitmap(input, canvas.drawBitmap(input,
Rect(srcX, srcY, srcX + rowWidth, srcY + rowHeight), Rect(srcX, srcY, srcX + rowWidth, srcY + rowHeight),
Rect(destX, destY, destX + rowWidth, destY + rowHeight), Rect(destX, destY, destX + rowWidth, destY + rowHeight),
null) null)
} }
return output return output
@ -144,18 +148,18 @@ internal class ImageDecoderInterceptor : Interceptor {
*/ */
private fun decoderRandom(chapter: Int, view_cnt: Int, index: Int): Int { private fun decoderRandom(chapter: Int, view_cnt: Int, index: Int): Int {
if (chapter < 554714) { if (chapter < 554714) {
val x = 10000 * Math.sin((view_cnt + index).toDouble()) val x = 10000 * sin((view_cnt + index).toDouble())
return Math.floor(100000 * (x - Math.floor(x))).toInt() return floor(100000 * (x - floor(x))).toInt()
} }
val seed = view_cnt + index + 1 val seed = view_cnt + index + 1
val t = 100 * Math.sin((10 * seed).toDouble()) val t = 100 * sin((10 * seed).toDouble())
val n = 1000 * Math.cos((13 * seed).toDouble()) val n = 1000 * cos((13 * seed).toDouble())
val a = 10000 * Math.tan((14 * seed).toDouble()) val a = 10000 * tan((14 * seed).toDouble())
return (Math.floor(100 * (t - Math.floor(t))) + return (floor(100 * (t - floor(t))) +
Math.floor(1000 * (n - Math.floor(n))) + floor(1000 * (n - floor(n))) +
Math.floor(10000 * (a - Math.floor(a)))).toInt() floor(10000 * (a - floor(a)))).toInt()
} }
} }

View File

@ -1,8 +1,11 @@
package eu.kanade.tachiyomi.extension.ko.mangashowme package eu.kanade.tachiyomi.extension.ko.mangashowme
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Application import android.app.Application
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.Build
import android.support.v7.preference.CheckBoxPreference
import android.support.v7.preference.EditTextPreference import android.support.v7.preference.EditTextPreference
import android.support.v7.preference.PreferenceScreen import android.support.v7.preference.PreferenceScreen
import android.widget.Toast import android.widget.Toast
@ -12,19 +15,20 @@ import eu.kanade.tachiyomi.source.ConfigurableSource
import eu.kanade.tachiyomi.source.model.* import eu.kanade.tachiyomi.source.model.*
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.OkHttpClient import okhttp3.*
import okhttp3.Request
import okhttp3.Response
import org.json.JSONArray import org.json.JSONArray
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.jsoup.nodes.Element import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get import uy.kohesive.injekt.api.get
import java.io.IOException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
/** /**
* ManaMoa Source * ManaMoa Source
* *
@ -39,9 +43,9 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
override val name = "ManaMoa" override val name = "ManaMoa"
// This keeps updating: https://twitter.com/manamoa20 // This keeps updating: https://twitter.com/manamoa24
private val defaultBaseUrl = "https://manamoa23.net" private val defaultBaseUrl = "https://manamoa26.net"
override val baseUrl by lazy { getPrefBaseUrl() } override val baseUrl by lazy { getCurrentBaseUrl() }
override val lang: String = "ko" override val lang: String = "ko"
@ -99,14 +103,14 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
override fun mangaDetailsParse(document: Document): SManga { override fun mangaDetailsParse(document: Document): SManga {
val info = document.select("div.left-info").first() val info = document.select("div.left-info").first()
val thumbnailElement = info.select("div.manga-thumbnail").first() val thumbnailElement = info.select("div.manga-thumbnail").first()
val publishTypeText = trimElementText(thumbnailElement.select("a.publish_type"), "Unknown") val publishTypeText = thumbnailElement.select("a.publish_type").trimText("Unknown")
val authorText = trimElementText(thumbnailElement.select("a.author")) val authorText = thumbnailElement.select("a.author").trimText()
val mangaStatus = info.select("div.recommend") val mangaStatus = info.select("div.recommend")
val mangaLike = trimElementText(mangaStatus.select(".fa-thumbs-up"), "0") val mangaLike = mangaStatus.select(".fa-thumbs-up").trimText("0")
//val mangaViews = trimElementText(mangaStatus.select(".fa-smile-o"), "0") //val mangaViews = trimElementText(mangaStatus.select(".fa-smile-o"), "0")
val mangaComments = trimElementText(mangaStatus.select(".fa-comment"), "0") val mangaComments = mangaStatus.select(".fa-comment").trimText("0")
val mangaBookmarks = trimElementText(info.select(".fa-bookmark"), "0") val mangaBookmarks = info.select(".fa-bookmark").trimText("0")
val mangaChaptersLike = mangaElementsSum(document.select(".title i.fa.fa-thumbs-up > span")) val mangaChaptersLike = mangaElementsSum(document.select(".title i.fa.fa-thumbs-up > span"))
val mangaChaptersComments = mangaElementsSum(document.select(".title i.fa.fa-comment > span")) val mangaChaptersComments = mangaElementsSum(document.select(".title i.fa.fa-comment > span"))
@ -269,8 +273,8 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
return style.substringAfter("background-image:url(").substringBefore(")") return style.substringAfter("background-image:url(").substringBefore(")")
} }
private fun trimElementText(element: Elements, fallback: String = ""): String { private fun Elements.trimText(fallback: String = ""): String {
return element.text()?.trim()?.takeUnless { it.isBlank() } ?: fallback return this.text()?.trim()?.takeUnless { it.isBlank() } ?: fallback
} }
private val preferences: SharedPreferences by lazy { private val preferences: SharedPreferences by lazy {
@ -298,7 +302,26 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
} }
} }
val autoFetchUrlPref = androidx.preference.CheckBoxPreference (screen.context).apply {
key = AUTOFETCH_URL_PREF_TITLE
title = AUTOFETCH_URL_PREF_TITLE
summary = AUTOFETCH_URL_PREF_SUMMARY
this.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
setOnPreferenceChangeListener { _, newValue ->
try {
val res = preferences.edit().putBoolean(AUTOFETCH_URL_PREF, newValue as Boolean).commit()
Toast.makeText(screen.context, RESTART_TACHIYOMI, Toast.LENGTH_LONG).show()
res
} catch (e: Exception) {
e.printStackTrace()
false
}
}
}
screen.addPreference(baseUrlPref) screen.addPreference(baseUrlPref)
screen.addPreference(autoFetchUrlPref)
} }
override fun setupPreferenceScreen(screen: PreferenceScreen) { override fun setupPreferenceScreen(screen: PreferenceScreen) {
@ -322,17 +345,82 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
} }
} }
val autoFetchUrlPref = CheckBoxPreference(screen.context).apply {
key = AUTOFETCH_URL_PREF_TITLE
title = AUTOFETCH_URL_PREF_TITLE
summary = AUTOFETCH_URL_PREF_SUMMARY
this.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
setOnPreferenceChangeListener { _, newValue ->
try {
val res = preferences.edit().putBoolean(AUTOFETCH_URL_PREF, newValue as Boolean).commit()
Toast.makeText(screen.context, RESTART_TACHIYOMI, Toast.LENGTH_LONG).show()
res
} catch (e: Exception) {
e.printStackTrace()
false
}
}
}
screen.addPreference(baseUrlPref) screen.addPreference(baseUrlPref)
screen.addPreference(autoFetchUrlPref)
} }
private fun getCurrentBaseUrl(): String {
val prefBaseUrl = getPrefBaseUrl()
if (!preferences.getBoolean(AUTOFETCH_URL_PREF, false)) {
return prefBaseUrl
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
try {
@TargetApi(Build.VERSION_CODES.N)
class CallbackFuture : CompletableFuture<Response?>(), Callback {
override fun onResponse(call: Call?, response: Response?) {
super.complete(response)
}
override fun onFailure(call: Call?, e: IOException?) {
super.completeExceptionally(e)
}
}
val request: Request = Request.Builder().get()
.url("http://13.229.223.203")
.build()
val future = CallbackFuture()
network.client.newCall(request).enqueue(future)
val response = future.get()!!
return "https://${response.request().url().host()}"
} catch (e: Exception) {
e.printStackTrace()
return prefBaseUrl
}
} else {
return prefBaseUrl
}
}
private fun getPrefBaseUrl(): String = preferences.getString(BASE_URL_PREF, defaultBaseUrl)!! private fun getPrefBaseUrl(): String = preferences.getString(BASE_URL_PREF, defaultBaseUrl)!!
override fun getFilterList() = getFilters() override fun getFilterList() = getFilters()
companion object { companion object {
// Setting: Override BaseUrl
private const val BASE_URL_PREF_TITLE = "Override BaseUrl" private const val BASE_URL_PREF_TITLE = "Override BaseUrl"
private const val BASE_URL_PREF = "overrideBaseUrl_v${BuildConfig.VERSION_NAME}" private const val BASE_URL_PREF = "overrideBaseUrl_v${BuildConfig.VERSION_NAME}"
private const val BASE_URL_PREF_SUMMARY = "For temporary uses. Update extension will erase this setting." private const val BASE_URL_PREF_SUMMARY = "For temporary uses. Update extension will erase this setting."
// Setting: Fetch Domain
private const val AUTOFETCH_URL_PREF_TITLE = "Automatically fetch new domain"
private const val AUTOFETCH_URL_PREF = "autoFetchNewUrl"
private const val AUTOFETCH_URL_PREF_SUMMARY =
"Experimental, May cause Tachiyomi unstable.\n" +
"Requires Android Nougat or newer."
private const val RESTART_TACHIYOMI = "Restart Tachiyomi to apply new setting." private const val RESTART_TACHIYOMI = "Restart Tachiyomi to apply new setting."
// Image Decoder // Image Decoder