修复JSON返回值
This commit is contained in:
@@ -96,7 +96,8 @@ func NodeConfig(c *gin.Context) {
|
||||
node := c.MustGet("node").(*model.Server)
|
||||
setNodeLastCheck(node)
|
||||
|
||||
config := service.BuildNodeConfig(node)
|
||||
config := service.BuildNodeConfigPayload(node)
|
||||
config["base_config"] = service.BuildNodeBaseConfigPayload()
|
||||
c.JSON(http.StatusOK, config)
|
||||
}
|
||||
|
||||
|
||||
@@ -351,6 +351,162 @@ func BuildNodeConfig(node *model.Server) NodeServerConfig {
|
||||
return response
|
||||
}
|
||||
|
||||
func BuildNodeConfigPayload(node *model.Server) map[string]any {
|
||||
settings := parseObject(node.ProtocolSettings)
|
||||
baseConfig := map[string]any{
|
||||
"protocol": node.Type,
|
||||
"listen_ip": "0.0.0.0",
|
||||
"server_port": node.ServerPort,
|
||||
"network": getMapAny(settings, "network"),
|
||||
"networkSettings": getMapAny(settings, "network_settings"),
|
||||
}
|
||||
|
||||
response := cloneNodePayload(baseConfig)
|
||||
|
||||
switch node.Type {
|
||||
case "shadowsocks":
|
||||
response["cipher"] = getMapAny(settings, "cipher")
|
||||
response["plugin"] = getMapAny(settings, "plugin")
|
||||
response["plugin_opts"] = getMapAny(settings, "plugin_opts")
|
||||
switch getMapString(settings, "cipher") {
|
||||
case "2022-blake3-aes-128-gcm":
|
||||
response["server_key"] = serverKey(node.CreatedAt, 16)
|
||||
case "2022-blake3-aes-256-gcm":
|
||||
response["server_key"] = serverKey(node.CreatedAt, 32)
|
||||
default:
|
||||
response["server_key"] = nil
|
||||
}
|
||||
case "vmess":
|
||||
response["tls"] = getMapInt(settings, "tls")
|
||||
response["multiplex"] = getMapAny(settings, "multiplex")
|
||||
case "trojan":
|
||||
response["host"] = node.Host
|
||||
response["server_name"] = getMapAny(settings, "server_name")
|
||||
response["multiplex"] = getMapAny(settings, "multiplex")
|
||||
response["tls"] = getMapInt(settings, "tls")
|
||||
if getMapInt(settings, "tls") == 2 {
|
||||
response["tls_settings"] = getMapAny(settings, "reality_settings")
|
||||
} else {
|
||||
response["tls_settings"] = nil
|
||||
}
|
||||
case "vless":
|
||||
response["tls"] = getMapInt(settings, "tls")
|
||||
response["flow"] = getMapAny(settings, "flow")
|
||||
response["multiplex"] = getMapAny(settings, "multiplex")
|
||||
response["decryption"] = nil
|
||||
if encryption, ok := settings["encryption"].(map[string]any); ok {
|
||||
if enabled, ok := encryption["enabled"].(bool); ok && enabled {
|
||||
response["decryption"] = encryption["decryption"]
|
||||
}
|
||||
}
|
||||
if getMapInt(settings, "tls") == 2 {
|
||||
response["tls_settings"] = getMapAny(settings, "reality_settings")
|
||||
} else {
|
||||
response["tls_settings"] = getMapAny(settings, "tls_settings")
|
||||
}
|
||||
case "hysteria":
|
||||
tls, _ := settings["tls"].(map[string]any)
|
||||
obfs, _ := settings["obfs"].(map[string]any)
|
||||
bandwidth, _ := settings["bandwidth"].(map[string]any)
|
||||
version := getMapInt(settings, "version")
|
||||
response["version"] = version
|
||||
response["host"] = node.Host
|
||||
response["server_name"] = getMapAny(tls, "server_name")
|
||||
response["up_mbps"] = mapAnyInt(bandwidth, "up")
|
||||
response["down_mbps"] = mapAnyInt(bandwidth, "down")
|
||||
switch version {
|
||||
case 1:
|
||||
response["obfs"] = getMapAny(obfs, "password")
|
||||
case 2:
|
||||
if open, ok := obfs["open"].(bool); ok && open {
|
||||
response["obfs"] = getMapAny(obfs, "type")
|
||||
} else {
|
||||
response["obfs"] = nil
|
||||
}
|
||||
response["obfs-password"] = getMapAny(obfs, "password")
|
||||
}
|
||||
case "tuic":
|
||||
tls, _ := settings["tls"].(map[string]any)
|
||||
response["version"] = getMapInt(settings, "version")
|
||||
response["server_name"] = getMapAny(tls, "server_name")
|
||||
response["congestion_control"] = getMapAny(settings, "congestion_control")
|
||||
response["tls_settings"] = getMapAny(settings, "tls_settings")
|
||||
response["auth_timeout"] = "3s"
|
||||
response["zero_rtt_handshake"] = false
|
||||
response["heartbeat"] = "3s"
|
||||
case "anytls":
|
||||
tls, _ := settings["tls"].(map[string]any)
|
||||
response["server_name"] = getMapAny(tls, "server_name")
|
||||
response["padding_scheme"] = getMapAny(settings, "padding_scheme")
|
||||
case "socks":
|
||||
// Base config already matches the original XBoard payload for socks.
|
||||
case "naive":
|
||||
response["tls"] = getMapInt(settings, "tls")
|
||||
response["tls_settings"] = getMapAny(settings, "tls_settings")
|
||||
case "http":
|
||||
response["tls"] = getMapInt(settings, "tls")
|
||||
response["tls_settings"] = getMapAny(settings, "tls_settings")
|
||||
case "mieru":
|
||||
transport := getMapString(settings, "transport")
|
||||
if strings.TrimSpace(transport) == "" {
|
||||
transport = "TCP"
|
||||
}
|
||||
response["transport"] = transport
|
||||
response["traffic_pattern"] = getMapAny(settings, "traffic_pattern")
|
||||
}
|
||||
|
||||
if routeIDs := parseIntSlice(node.RouteIDs); len(routeIDs) > 0 {
|
||||
var routes []model.ServerRoute
|
||||
if err := database.DB.Select("id", "`match`", "action", "action_value").Where("id IN ?", routeIDs).Find(&routes).Error; err == nil {
|
||||
response["routes"] = routes
|
||||
}
|
||||
}
|
||||
|
||||
if customOutbounds := parseGenericJSON(node.CustomOutbounds); hasNodePayloadValue(customOutbounds) {
|
||||
response["custom_outbounds"] = customOutbounds
|
||||
}
|
||||
if customRoutes := parseGenericJSON(node.CustomRoutes); hasNodePayloadValue(customRoutes) {
|
||||
response["custom_routes"] = customRoutes
|
||||
}
|
||||
if certConfig := parseObject(node.CertConfig); len(certConfig) > 0 && getMapString(certConfig, "cert_mode") != "none" {
|
||||
response["cert_config"] = certConfig
|
||||
}
|
||||
|
||||
return response
|
||||
}
|
||||
|
||||
func BuildNodeBaseConfigPayload() map[string]any {
|
||||
return map[string]any{
|
||||
"push_interval": MustGetInt("server_push_interval", 60),
|
||||
"pull_interval": MustGetInt("server_pull_interval", 60),
|
||||
}
|
||||
}
|
||||
|
||||
func cloneNodePayload(values map[string]any) map[string]any {
|
||||
result := make(map[string]any, len(values))
|
||||
for key, value := range values {
|
||||
result[key] = value
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func hasNodePayloadValue(value any) bool {
|
||||
switch typed := value.(type) {
|
||||
case nil:
|
||||
return false
|
||||
case string:
|
||||
return strings.TrimSpace(typed) != ""
|
||||
case []any:
|
||||
return len(typed) > 0
|
||||
case []map[string]any:
|
||||
return len(typed) > 0
|
||||
case map[string]any:
|
||||
return len(typed) > 0
|
||||
default:
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func ApplyTrafficDelta(userID int, node *model.Server, upload, download int64) {
|
||||
rate := CurrentRate(node)
|
||||
scaledUpload := int64(math.Round(float64(upload) * rate))
|
||||
|
||||
Reference in New Issue
Block a user