diff --git a/multisrc/overrides/madara/shinigami/src/Shinigami.kt b/multisrc/overrides/madara/shinigami/src/Shinigami.kt index 18ead1739..d44090147 100644 --- a/multisrc/overrides/madara/shinigami/src/Shinigami.kt +++ b/multisrc/overrides/madara/shinigami/src/Shinigami.kt @@ -1,28 +1,17 @@ package eu.kanade.tachiyomi.extension.id.shinigami -import android.app.Application -import android.content.SharedPreferences import android.util.Base64 -import android.widget.Toast -import androidx.preference.EditTextPreference -import androidx.preference.PreferenceScreen import eu.kanade.tachiyomi.lib.cryptoaes.CryptoAES import eu.kanade.tachiyomi.lib.synchrony.Deobfuscator import eu.kanade.tachiyomi.multisrc.madara.Madara -import eu.kanade.tachiyomi.network.GET +import eu.kanade.tachiyomi.network.interceptor.rateLimit import eu.kanade.tachiyomi.source.model.Page import eu.kanade.tachiyomi.source.model.SChapter import kotlinx.serialization.Serializable import kotlinx.serialization.decodeFromString -import okhttp3.Headers -import okhttp3.Interceptor import okhttp3.OkHttpClient -import okhttp3.Response import org.jsoup.nodes.Document import org.jsoup.nodes.Element -import uy.kohesive.injekt.Injekt -import uy.kohesive.injekt.api.get -import java.io.IOException import java.util.concurrent.TimeUnit class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") { @@ -33,92 +22,30 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") { override fun searchPage(page: Int): String = if (page == 1) "" else "page/$page/" - private val preferences: SharedPreferences by lazy { - Injekt.get().getSharedPreferences("source_$id", 0x0000) + override fun headersBuilder() = super.headersBuilder().apply { + add("Sec-Fetch-Dest", "document") + add("Sec-Fetch-Mode", "navigate") + add("Sec-Fetch-Site", "same-origin") + add("Upgrade-Insecure-Requests", "1") + add("X-Requested-With", "") // added for webview, and removed in interceptor for normal use } - private val encodedString = "AAA AaAAAAH QAAAB0 AAAAcA AAAHMAA AA6AAA ALwAAAC8AA " + "AB0AAAAYQA AAGM AAADoAAAAaQAAAH kAAABvAA AAbQAAA GkAAABvAAAA cgAAAGcAAAAuAAA AZwAAAGk " + "AAAB0AAAA aAAAAHUAA ABiAAAALgAAAGkAA ABvAAAAL wAAAHUAAABzA AAAZQAAAHIAAAAtA AAAYQAAAGcA " + "AABlyAtAAAbgA AAHQAAAB6AAAA LwAAAHUAAA BcAAAAZQ AAAHIAAAAtAAA AYQAAAGcAAABl AAAAbgAA AHQAAAB6AAAALgAAAG" + " oAhAntUAABzAA AAbwAAAG4=" - - private val tachiUaUrl = Base64.decode(encodedString.replace("\\s".toRegex(), "").replace("DoA", "BoA").replace("GoAhAntU", "GoA").replace("BlyAt", "BlA").replace("BcA", "BzA"), Base64.DEFAULT).toString(Charsets.UTF_32).replace("z", "s") - - private var secChUaMP: List? = null - private var userAgent: String? = null - private var checkedUa = false - - private val uaIntercept = object : Interceptor { - override fun intercept(chain: Interceptor.Chain): Response { - val customUa = preferences.getString(PREF_KEY_CUSTOM_UA, "") - try { - if (customUa!!.isNotBlank()) userAgent = customUa - - if (userAgent.isNullOrBlank() && checkedUa.not()) { - val uaResponse = chain.proceed(GET(tachiUaUrl)) - if (uaResponse.isSuccessful) { - val parseTachiUa = uaResponse.use { json.decodeFromString(it.body.string()) } - - var listUserAgentString = parseTachiUa.desktop + parseTachiUa.mobile - - listUserAgentString = listUserAgentString!!.filter { - listOf("windows", "android").any { filter -> - it.contains(filter, ignoreCase = true) - } - } - userAgent = listUserAgentString!!.random() - checkedUa = true - } - uaResponse.close() - } - - if (userAgent.isNullOrBlank().not()) { - secChUaMP = if (userAgent!!.contains("Windows")) { - listOf("?0", "Windows") - } else { - listOf("?1", "Android") - } - - val newRequest = chain.request().newBuilder() - .header("User-Agent", userAgent!!.trim()) - .header("Sec-CH-UA-Mobile", secChUaMP!![0]) - .header("Sec-CH-UA-Platform", secChUaMP!![1]) - .removeHeader("X-Requested-With") - .build() - - return chain.proceed(newRequest) - } - return chain.proceed(chain.request()) - } catch (e: Exception) { - throw IOException(e.message) - } - } - } - - @Serializable - data class TachiUaResponse( - val desktop: List = emptyList(), - val mobile: List = emptyList(), - ) - - // disable random ua in ext setting from multisrc (.setRandomUserAgent) override val client: OkHttpClient = network.cloudflareClient.newBuilder() - .addInterceptor(uaIntercept) + .addInterceptor { chain -> + val request = chain.request() + val headers = request.headers.newBuilder().apply { + if (request.header("X-Requested-With")?.isBlank() == true) { + removeAll("X-Requested-With") + } + }.build() + + chain.proceed(request.newBuilder().headers(headers).build()) + } .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(30, TimeUnit.SECONDS) + .rateLimit(2) .build() - override fun headersBuilder(): Headers.Builder { - val builder = super.headersBuilder() - .add("Sec-Fetch-Dest", "document") - .add("Sec-Fetch-Mode", "navigate") - .add("Sec-Fetch-Site", "same-origin") - .add("Upgrade-Insecure-Requests", "1") - .add("X-Requested-With", "") // added for webview, and removed in interceptor for normal use - - // used to flush tachi custom ua in webview and use system ua instead - if (userAgent.isNullOrBlank()) builder.removeAll("User-Agent") - - return builder - } - override val mangaSubString = "semua-series" // Tags are useless as they are just SEO keywords. @@ -148,13 +75,15 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") { val deobfuscated = Deobfuscator.deobfuscateScript(script) ?: throw Exception("Unable to deobfuscate chapter_data script") - val postId = script.substringAfter("var post_id = '").substringBefore("'") - val chapterData = json.decodeFromString( - script.substringAfter("var chapter_data = '").substringBefore("'"), - ) + val keyMatch = KEY_REGEX.find(deobfuscated)?.groupValues + ?: throw Exception("Unable to find key") - val keyMatch = KEY_REGEX.find(deobfuscated)!!.groupValues - val key = postId + keyMatch[1] + postId + keyMatch[2] + postId + val chapterData = json.decodeFromString( + CHAPTER_DATA_REGEX.find(script)?.groupValues?.get(1) ?: throw Exception("Unable to get chapter data"), + ) + val postId = POST_ID_REGEX.find(script)?.groupValues?.get(1) ?: throw Exception("Unable to get post_id") + val otherId = OTHER_ID_REGEX.findAll(script).firstOrNull { it.groupValues[1] != "post" }?.groupValues?.get(2) ?: throw Exception("Unable to get other id") + val key = otherId + keyMatch[1] + postId + keyMatch[2] + postId val salt = chapterData.s.decodeHex() val unsaltedCiphertext = Base64.decode(chapterData.ct, Base64.DEFAULT) @@ -176,36 +105,10 @@ class Shinigami : Madara("Shinigami", "https://shinigamitoon.com", "id") { .toByteArray() } - // remove random ua in setting ext from multisrc and use custom one - override fun setupPreferenceScreen(screen: PreferenceScreen) { - val prefCustomUserAgent = EditTextPreference(screen.context).apply { - key = PREF_KEY_CUSTOM_UA - title = TITLE_CUSTOM_UA - summary = (preferences.getString(PREF_KEY_CUSTOM_UA, "")!!.trim() + SUMMARY_STRING_CUSTOM_UA).trim() - setOnPreferenceChangeListener { _, newValue -> - val customUa = newValue as String - preferences.edit().putString(PREF_KEY_CUSTOM_UA, customUa).apply() - if (customUa.isNullOrBlank()) { - Toast.makeText(screen.context, RESTART_APP_STRING, Toast.LENGTH_LONG).show() - } else { - userAgent = null - } - summary = (customUa.trim() + SUMMARY_STRING2_CUSTOM_UA).trim() - - true - } - } - screen.addPreference(prefCustomUserAgent) - } - companion object { - const val TITLE_CUSTOM_UA = "Custom User-Agent" - const val PREF_KEY_CUSTOM_UA = "pref_key_custom_ua" - const val SUMMARY_STRING_CUSTOM_UA = "\n\nBiarkan kosong untuk menggunakan User-Agent secara random" - const val SUMMARY_STRING2_CUSTOM_UA = "\n\nKosongkan untuk menggunakan User-Agent secara random" - - const val RESTART_APP_STRING = "Restart Tachiyomi untuk menggunakan pengaturan baru." - - private val KEY_REGEX by lazy { Regex("""post_id\s+\+\s+'(.*?)'\s+\+\s+post_id\s+\+\s+'(.*?)'\s+\+\s+post_id""") } + private val KEY_REGEX by lazy { Regex("""_id\s+\+\s+'(.*?)'\s+\+\s+post_id\s+\+\s+'(.*?)'\s+\+\s+post_id""") } + private val CHAPTER_DATA_REGEX by lazy { Regex("""var chapter_data\s*=\s*'(.*?)'""") } + private val POST_ID_REGEX by lazy { Regex("""var post_id\s*=\s*'(.*?)'""") } + private val OTHER_ID_REGEX by lazy { Regex("""var (\w+)_id\s*=\s*'(.*?)'""") } } } diff --git a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt index 107d0669f..9c8ec33f2 100644 --- a/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt +++ b/multisrc/src/main/java/eu/kanade/tachiyomi/multisrc/madara/MadaraGenerator.kt @@ -440,7 +440,7 @@ class MadaraGenerator : ThemeSourceGenerator { SingleLang("Shayami", "https://shayami.com", "es"), SingleLang("Shiba Manga", "https://shibamanga.com", "en"), SingleLang("Shield Manga", "https://shieldmanga.io", "en", overrideVersionCode = 3), - SingleLang("Shinigami", "https://shinigamitoon.com", "id", overrideVersionCode = 11), + SingleLang("Shinigami", "https://shinigamitoon.com", "id", overrideVersionCode = 12), SingleLang("Shooting Star Scans", "https://shootingstarscans.com", "en"), SingleLang("ShoujoHearts", "https://shoujohearts.com", "en", overrideVersionCode = 2), SingleLang("Sinensis Scan", "https://sinensisscan.net", "pt-BR", pkgName = "sinensis", overrideVersionCode = 6),