This commit is contained in:
DHR60 authored and GitHub committed 2026-08-29 11:05:07 +08:00
1 parent a1b45bbfb2
commit 38da97e031
3 files changed
+51 -23

No files matched your search

@@ -7,7 +7,7 @@ import com.v2ray.ang.enums.NetworkType
@Suppress("PropertyName")
data class V2rayNShareItem(
// val IndexId: String?,
val IndexId: String?,
val ConfigType: Int?,
// val CoreType: Int?,
val ConfigVersion: Int?,
@@ -3,20 +3,46 @@ package com.v2ray.ang.fmt
import com.v2ray.ang.AppConfig
import com.v2ray.ang.dto.V2rayNShareItem
import com.v2ray.ang.dto.entities.ProfileItem
import com.v2ray.ang.extension.isNotNullEmpty
import com.v2ray.ang.util.JsonUtil
import com.v2ray.ang.util.LogUtil
import com.v2ray.ang.util.Utils
object V2rayNFmt : FmtBase() {
fun parse(str: String): ProfileItem? {
try {
val jsonBase64Payload = str.substringAfterLast('/')
val jsonPayload = Utils.decode(jsonBase64Payload)
val v2rayNShareItem = JsonUtil.fromJson(jsonPayload, V2rayNShareItem::class.java)
return v2rayNShareItem?.toProfileItem()
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to parse V2rayN format", e)
fun parse(list: List<String>, subId: String): List<ProfileItem> {
val idMap = mutableMapOf<String, V2rayNShareItem>()
list.mapNotNull(::parseShareItem).forEach { item ->
idMap.putIfAbsent(item.IndexId.orEmpty(), item)
}
return null
return idMap.values.map { item ->
item.toProfileItem().apply {
val proto = item.ProtoExtraObj
policyGroupSubscriptionId = if (proto?.SubChildItems == "self") {
subId
} else {
null
}
proto?.ChildItems?.takeIf { it.isNotNullEmpty() }?.let { ids ->
val remarks = ids.split(",")
.mapNotNull { idMap[it]?.Remarks }
.filter { it.isNotNullEmpty() }
if (remarks.isNotEmpty()) {
when (item.ConfigType) {
101 -> policyGroupFilter = remarks.joinToString("|", "^(", ")$") { Regex.escape(it) }
102 -> proxyChainProfiles = remarks.joinToString(",")
}
}
}
}
}
}
private fun parseShareItem(str: String): V2rayNShareItem? = try {
JsonUtil.fromJson(Utils.decode(str.substringAfterLast('/')), V2rayNShareItem::class.java)
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to parse V2rayN share item", e)
null
}
}
@@ -48,7 +48,6 @@ object AngConfigManager {
EConfigType.WIREGUARD.protocolScheme to WireguardFmt::parse,
EConfigType.HYSTERIA2.protocolScheme to Hysteria2Fmt::parse,
AppConfig.HY2 to Hysteria2Fmt::parse,
AppConfig.V2RAYNFMTS to V2rayNFmt::parse
)
}
@@ -249,25 +248,34 @@ object AngConfigManager {
// Parse all configs first (no I/O during parsing)
val configs = mutableListOf<ProfileItem>()
val v2raynLines = mutableListOf<String>()
servers.lines()
.distinct()
.reversed()
.forEach {
val config = parseConfig(it, subid, subItem)
if (config != null) {
configs.add(config)
if (it.startsWith(AppConfig.V2RAYNFMTS, ignoreCase = true)) {
v2raynLines.add(it)
} else {
val config = parseConfig(it, subid, subItem)
if (config != null) {
configs.add(config)
}
}
}
if (configs.isNotEmpty()) {
val v2raynConfigs = V2rayNFmt.parse(v2raynLines, subid)
val allConfigs = v2raynConfigs + configs
if (allConfigs.isNotEmpty()) {
commitProfiles(
configs = configs.map(::ParsedProfile),
configs = allConfigs.map(::ParsedProfile),
subid = subid,
append = append,
)
}
return configs.size
return allConfigs.size
} catch (e: ProfileStorageException) {
throw e
} catch (e: Exception) {
@@ -420,12 +428,6 @@ object AngConfigManager {
config.subscriptionId = subid
config.description = generateDescription(config)
if (str.startsWith(AppConfig.V2RAYNFMTS, ignoreCase = true)
&& config.policyGroupSubscriptionId == "self"
) {
config.policyGroupSubscriptionId = subid
}
return config
} catch (e: Exception) {
LogUtil.e(AppConfig.TAG, "Failed to parse config", e)