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!");
}
public void setEnabled(boolean enabled) {
throw new RuntimeException("Stub!");
}
public String getKey() {
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!");
}
public void setEnabled(boolean enabled) {
throw new RuntimeException("Stub!");
}
public String getKey() {
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'
pkgNameSuffix = 'ko.mangashowme'
extClass = '.ManaMoa'
extVersionCode = 16
extVersionCode = 17
libVersion = '1.2'
}

View File

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

View File

@ -1,8 +1,11 @@
package eu.kanade.tachiyomi.extension.ko.mangashowme
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Application
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.PreferenceScreen
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.online.ParsedHttpSource
import eu.kanade.tachiyomi.util.asJsoup
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import okhttp3.*
import org.json.JSONArray
import org.jsoup.nodes.Document
import org.jsoup.nodes.Element
import org.jsoup.select.Elements
import uy.kohesive.injekt.Injekt
import uy.kohesive.injekt.api.get
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import java.util.concurrent.CompletableFuture
import java.util.concurrent.TimeUnit
/**
* ManaMoa Source
*
@ -39,9 +43,9 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
override val name = "ManaMoa"
// This keeps updating: https://twitter.com/manamoa20
private val defaultBaseUrl = "https://manamoa23.net"
override val baseUrl by lazy { getPrefBaseUrl() }
// This keeps updating: https://twitter.com/manamoa24
private val defaultBaseUrl = "https://manamoa26.net"
override val baseUrl by lazy { getCurrentBaseUrl() }
override val lang: String = "ko"
@ -99,14 +103,14 @@ class ManaMoa : ConfigurableSource, ParsedHttpSource() {
override fun mangaDetailsParse(document: Document): SManga {
val info = document.select("div.left-info").first()
val thumbnailElement = info.select("div.manga-thumbnail").first()
val publishTypeText = trimElementText(thumbnailElement.select("a.publish_type"), "Unknown")
val authorText = trimElementText(thumbnailElement.select("a.author"))
val publishTypeText = thumbnailElement.select("a.publish_type").trimText("Unknown")
val authorText = thumbnailElement.select("a.author").trimText()
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 mangaComments = trimElementText(mangaStatus.select(".fa-comment"), "0")
val mangaBookmarks = trimElementText(info.select(".fa-bookmark"), "0")
val mangaComments = mangaStatus.select(".fa-comment").trimText("0")
val mangaBookmarks = info.select(".fa-bookmark").trimText("0")
val mangaChaptersLike = mangaElementsSum(document.select(".title i.fa.fa-thumbs-up > 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(")")
}
private fun trimElementText(element: Elements, fallback: String = ""): String {
return element.text()?.trim()?.takeUnless { it.isBlank() } ?: fallback
private fun Elements.trimText(fallback: String = ""): String {
return this.text()?.trim()?.takeUnless { it.isBlank() } ?: fallback
}
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(autoFetchUrlPref)
}
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(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)!!
override fun getFilterList() = getFilters()
companion object {
// Setting: 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_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."
// Image Decoder