From e853527587e04df123691829e1665d985cdc10aa Mon Sep 17 00:00:00 2001 From: peakedshout <93729380+peakedshout@users.noreply.github.com> Date: Fri, 25 Apr 2025 01:11:07 +0800 Subject: [PATCH] Picacomic: Fix Channel logic error (#8555) * Adding a Referer value to the request header increases the possibility of circumventing Cloudflare. * Adding a Referer value to the request header increases the possibility of circumventing Cloudflare. * Adding a Referer value to the request header increases the possibility of circumventing Cloudflare. * Update src/zh/jinmantiantang/src/eu/kanade/tachiyomi/extension/zh/jinmantiantang/Jinmantiantang.kt * Fix: Channel logic error * Fix: Channel logic error * Fix: Channel logic error * Fix: Channel logic error --------- Co-authored-by: Vetle Ledaal --- src/zh/picacomic/build.gradle | 2 +- .../extension/zh/picacomic/ChannelDns.kt | 75 +++++++++++++++++++ .../extension/zh/picacomic/PicaApiSchemas.kt | 6 ++ .../extension/zh/picacomic/Picacomic.kt | 21 +++++- 4 files changed, 101 insertions(+), 3 deletions(-) create mode 100644 src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/ChannelDns.kt diff --git a/src/zh/picacomic/build.gradle b/src/zh/picacomic/build.gradle index a2ad6790e..cdea28e69 100644 --- a/src/zh/picacomic/build.gradle +++ b/src/zh/picacomic/build.gradle @@ -1,7 +1,7 @@ ext { extName = 'Picacomic' extClass = '.Picacomic' - extVersionCode = 6 + extVersionCode = 7 isNsfw = true } diff --git a/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/ChannelDns.kt b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/ChannelDns.kt new file mode 100644 index 000000000..acdcf88dc --- /dev/null +++ b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/ChannelDns.kt @@ -0,0 +1,75 @@ +package eu.kanade.tachiyomi.extension.zh.picacomic + +import android.content.SharedPreferences +import eu.kanade.tachiyomi.network.GET +import keiyoushi.utils.parseAs +import okhttp3.Dns +import okhttp3.Headers +import okhttp3.OkHttpClient +import okio.IOException +import java.net.InetAddress + +class ChannelDns( + private val baseHost: String, + private val client: OkHttpClient, + private val preferences: SharedPreferences, +) : Dns { + + private val defaultInitUrl = "http://68.183.234.72/init" + + private var channel = listOf() + + override fun lookup(hostname: String): List { + if (!hostname.endsWith(baseHost)) { + return Dns.SYSTEM.lookup(hostname) + } + val ch = preferences.getString(APP_CHANNEL, "2")!! + return when (ch) { + "2" -> listOf(InetAddress.getByName(getChannelHost(0))) + "3" -> listOf(InetAddress.getByName(getChannelHost(1))) + else -> Dns.SYSTEM.lookup(hostname) + } + } + + private fun getChannelHost(index: Int): String { + if (channel.size > index) { + return channel[index] + } + + val chUrl = + preferences.getString(APP_CHANNEL_URL, defaultInitUrl)?.takeIf { it.isNotBlank() } + ?: defaultInitUrl + + val request = GET( + url = chUrl, + headers = Headers.headersOf( + "Accept-Encoding", + "gzip", + "User-Agent", + "okhttp/3.8.1", + ), + ) + + try { + val response = client.newCall(request).execute() + if (!response.isSuccessful) { + throw Exception("Unexpected ${request.url} code ${response.code}") + } + + val responseBody = response.body.string() + + val ch = responseBody.parseAs() + if (ch.status != "ok") { + throw Exception("Unexpected ${request.url} status ${ch.status}") + } + + channel = ch.addresses + if (channel.size <= index) { + throw Exception("Unexpected ${request.url} unable to obtain the target channel address") + } + return channel[index] + } catch (e: Exception) { + throw IOException(e.message) + } + } +} diff --git a/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/PicaApiSchemas.kt b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/PicaApiSchemas.kt index 6af7d7647..fcf8aec54 100644 --- a/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/PicaApiSchemas.kt +++ b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/PicaApiSchemas.kt @@ -99,3 +99,9 @@ data class PicaImage( val path: String, val fileServer: String, ) + +@Serializable +data class PicaChannel( + val status: String, + val addresses: List, +) diff --git a/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/Picacomic.kt b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/Picacomic.kt index 4e86715bb..aa2f4c6da 100644 --- a/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/Picacomic.kt +++ b/src/zh/picacomic/src/eu/kanade/tachiyomi/extension/zh/picacomic/Picacomic.kt @@ -23,6 +23,7 @@ import kotlinx.serialization.json.decodeFromJsonElement import okhttp3.Headers import okhttp3.Headers.Companion.toHeaders import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient import okhttp3.Request import okhttp3.RequestBody.Companion.toRequestBody import okhttp3.Response @@ -41,12 +42,15 @@ class Picacomic : HttpSource(), ConfigurableSource { private val preferences: SharedPreferences = getPreferences() + override val client: OkHttpClient = network.client.newBuilder() + .dns(ChannelDns(baseUrl.removePrefix("https://picaapi."), network.client, preferences)).build() + private val blocklist = preferences.getString("BLOCK_GENRES", "")!! .split(',').map { it.trim() } private val basicHeaders = mapOf( "api-key" to "C69BAF41DA5ABD1FFEDC6D2FEA56B", - "app-channel" to preferences.getString("APP_CHANNEL", "2")!!, + "app-channel" to preferences.getString(APP_CHANNEL, "2")!!, "app-version" to "2.2.1.3.3.4", "app-uuid" to "defaultUuid", "app-platform" to "android", @@ -441,7 +445,7 @@ class Picacomic : HttpSource(), ConfigurableSource { }.let(screen::addPreference) ListPreference(screen.context).apply { - key = "APP_CHANNEL" + key = APP_CHANNEL title = "分流" entries = arrayOf("1", "2", "3") entryValues = entries @@ -451,5 +455,18 @@ class Picacomic : HttpSource(), ConfigurableSource { preferences.edit().putString(key, newValue as String).commit() } }.let(screen::addPreference) + + EditTextPreference(screen.context).apply { + key = APP_CHANNEL_URL + title = "分流url" + summary = + "自定义用于获取分流2、3的目标地址;分流1不受影响;(如果之前获取成功了需要重启才能生效,如果出现超时可以多重试几次)" + setOnPreferenceChangeListener { _, newValue -> + preferences.edit().putString(APP_CHANNEL_URL, newValue as String).commit() + } + }.let(screen::addPreference) } } + +const val APP_CHANNEL = "APP_CHANNEL" +const val APP_CHANNEL_URL = "APP_CHANNEL_URL"