From cdaff4da06f2a92f8b1856ce2300f6bdbc2d2848 Mon Sep 17 00:00:00 2001 From: Vahid Farid Date: Fri, 9 Feb 2024 20:25:51 +0330 Subject: [PATCH] added support for multiple custom configs in subscriptions + remarks Accepting both single config and multiple configs i.e: {customConfig} or [{customConfig1}, {customConfig2} ...] Furtheremore added an optional 'remarks' field to v2rayConfig class to keep remote customConfig name. --- .../kotlin/com/v2ray/ang/dto/V2rayConfig.kt | 14 +++++++- .../com/v2ray/ang/util/AngConfigManager.kt | 34 +++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt index 4464ed0c..94d3848d 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/dto/V2rayConfig.kt @@ -10,6 +10,7 @@ import com.google.gson.reflect.TypeToken import java.lang.reflect.Type data class V2rayConfig( + var remarks: String? = null, var stats: Any? = null, val log: LogBean, var policy: PolicyBean?, @@ -69,6 +70,7 @@ data class V2rayConfig( val mux: MuxBean? = MuxBean(false)) { data class OutSettingsBean(var vnext: List? = null, + var fragment: FragmentBean? = null, var servers: List? = null, /*Blackhole*/ var response: Response? = null, @@ -101,6 +103,10 @@ data class V2rayConfig( var flow: String = "") } + data class FragmentBean(var packets: String = "", + var length: String = "10-20", + var interval: String = "10-20") + data class ServersBean(var address: String = "", var method: String = "chacha20-poly1305", var ota: Boolean = false, @@ -135,7 +141,7 @@ data class V2rayConfig( var realitySettings: TlsSettingsBean? = null, var grpcSettings: GrpcSettingsBean? = null, val dsSettings: Any? = null, - val sockopt: Any? = null + val sockopt: SockoptBean? = null ) { data class TcpSettingsBean(var header: HeaderBean = HeaderBean(), @@ -181,6 +187,12 @@ data class V2rayConfig( data class HttpSettingsBean(var host: List = ArrayList(), var path: String = "") + data class SockoptBean(var TcpNoDelay: Boolean? = null, + var tcpKeepAliveIdle: Int? = null, + var tcpFastOpen: Boolean? = null, + var tproxy: String? = null, + var mark: Int? = null) + data class TlsSettingsBean(var allowInsecure: Boolean = false, var serverName: String = "", val alpn: List? = null, diff --git a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt index c3dea69a..aa49aa9e 100644 --- a/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt +++ b/V2rayNG/app/src/main/kotlin/com/v2ray/ang/util/AngConfigManager.kt @@ -7,6 +7,7 @@ import android.text.TextUtils import android.util.Log import androidx.preference.PreferenceManager import com.google.gson.Gson +import com.google.gson.GsonBuilder import com.tencent.mmkv.MMKV import com.v2ray.ang.AppConfig import com.v2ray.ang.AppConfig.ANG_CONFIG @@ -985,13 +986,32 @@ object AngConfigManager { && server.contains("outbounds") && server.contains("routing") ) { - val config = ServerConfig.create(EConfigType.CUSTOM) - config.remarks = System.currentTimeMillis().toString() - config.subscriptionId = subid - config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java) - val key = MmkvManager.encodeServerConfig("", config) - serverRawStorage?.encode(key, server) - return 1 + val gson = GsonBuilder().setPrettyPrinting().create() + val serverList: Array = Gson().fromJson(server, Array::class.java) + if (serverList.size > 0) { + var count = 0 + for (srv in serverList) { + if (srv.inbounds != null && srv.outbounds != null && srv.routing != null) { + var config = ServerConfig.create(EConfigType.CUSTOM) + config.remarks = srv.remarks ?: "%04d-".format(count + 1) + System.currentTimeMillis().toString() + config.subscriptionId = subid + config.fullConfig = srv + var key = MmkvManager.encodeServerConfig("", config) + serverRawStorage?.encode(key, gson.toJson(srv)) + count = count + 1 + } + } + return count + } else { // For compatibility + val config = ServerConfig.create(EConfigType.CUSTOM) + config.subscriptionId = subid + config.fullConfig = Gson().fromJson(server, V2rayConfig::class.java) + config.remarks = System.currentTimeMillis().toString() + // config.remarks = config.fullConfig?.remarks ?: System.currentTimeMillis().toString() + val key = MmkvManager.encodeServerConfig("", config) + serverRawStorage?.encode(key, server) + return 1 + } } else { return 0 }