更新扩展连接协议字段并且新增邀请码展示

This commit is contained in:
2025-10-22 21:49:57 +08:00
parent 0d91ce138d
commit 17ea51b583
8 changed files with 252 additions and 67 deletions
+29 -6
View File
@@ -41,19 +41,24 @@ class KROutboundItem {
tag = nodeListItem.name; // 设置标签
serverAddr = nodeListItem.serverAddr; // 设置服务器地址
// 将 config 字符串转换为 Map<String, dynamic>
city = nodeListItem.city; // 设置城市
country = nodeListItem.country; // 设置国家
// 安全解析 config 字段
// 新API格式:config为空,直接使用节点字段构建配置
// 旧API格式:config包含JSON配置
if (nodeListItem.config.isEmpty) {
// 🔧 优先使用直接字段构建配置(新API格式)
// 判断条件:如果有 port 和 serverAddr,说明是新格式
if (nodeListItem.port > 0 && nodeListItem.serverAddr.isNotEmpty) {
print('️ 节点 ${nodeListItem.name} 使用直接字段构建配置');
_buildConfigFromFields(nodeListItem);
return;
}
// 兜底:尝试解析 config 字段(旧API格式)
if (nodeListItem.config.isEmpty) {
print('❌ 节点 ${nodeListItem.name} 缺少配置信息(无port或config)');
config = {};
return;
}
late Map<String, dynamic> json;
try {
json = jsonDecode(nodeListItem.config) as Map<String, dynamic>;
@@ -228,17 +233,31 @@ class KROutboundItem {
/// 直接从节点字段构建配置(新API格式)
void _buildConfigFromFields(KrNodeListItem nodeListItem) {
print('🔧 开始构建节点配置 - 协议: ${nodeListItem.protocol}, 名称: ${nodeListItem.name}');
print('📋 节点详细信息:');
print(' - serverAddr: ${nodeListItem.serverAddr}');
print(' - port: ${nodeListItem.port}');
print(' - uuid: ${nodeListItem.uuid}');
print(' - method: ${nodeListItem.method}');
switch (nodeListItem.protocol) {
case "shadowsocks":
// 优先使用 protocols 解析出来的 cipher,其次是 method 字段,最后才是默认值
String finalMethod = nodeListItem.method.isNotEmpty
? nodeListItem.method
: "2022-blake3-aes-256-gcm";
config = {
"type": "shadowsocks",
"tag": nodeListItem.name,
"server": nodeListItem.serverAddr,
"server_port": nodeListItem.port,
"method": "chacha20-ietf-poly1305", // 默认加密方法
"method": finalMethod,
"password": nodeListItem.uuid
};
print('✅ Shadowsocks 节点配置构建成功: ${nodeListItem.name}');
print('📄 使用加密方法: $finalMethod');
print('📄 完整配置: $config');
break;
case "vless":
config = {
@@ -258,6 +277,7 @@ class KROutboundItem {
}
};
print('✅ VLESS 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break;
case "vmess":
config = {
@@ -276,6 +296,7 @@ class KROutboundItem {
}
};
print('✅ VMess 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break;
case "trojan":
config = {
@@ -292,6 +313,7 @@ class KROutboundItem {
}
};
print('✅ Trojan 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break;
case "hysteria2":
config = {
@@ -310,6 +332,7 @@ class KROutboundItem {
}
};
print('✅ Hysteria2 节点配置构建成功: ${nodeListItem.name}');
print('📄 完整配置: $config');
break;
default:
print('⚠️ 不支持的协议类型: ${nodeListItem.protocol}');
+35 -3
View File
@@ -1,3 +1,4 @@
import 'dart:convert';
import 'package:kaer_with_panels/app/utils/kr_log_util.dart';
class KRNodeList {
@@ -54,7 +55,9 @@ class KrNodeListItem {
final String relayMode;
final String relayNode;
final String serverAddr;
final int port; // 新增:端口字段
final int port; // 端口字段
final String method; // 加密方法(用于Shadowsocks等)
final String protocols; // 协议配置JSON字符串(新API格式)
final int speedLimit;
final List<String> tags;
final int traffic;
@@ -81,6 +84,8 @@ class KrNodeListItem {
this.relayNode = '',
required this.serverAddr,
this.port = 0, // 默认值
this.method = '', // 默认空字符串
this.protocols = '', // 默认空字符串
required this.speedLimit,
required this.tags,
required this.traffic,
@@ -102,10 +107,33 @@ class KrNodeListItem {
factory KrNodeListItem.fromJson(Map<String, dynamic> json) {
try {
// 支持新旧两种API格式
// 新格式: address, port
// 新格式: protocols 字段包含协议配置数组
// 新格式: address, port, method(直接字段)
// 旧格式: server_addr, config 中包含 port
final serverAddr = json['address']?.toString() ?? json['server_addr']?.toString() ?? '';
final port = _parseIntSafely(json['port']);
int port = _parseIntSafely(json['port']);
String method = json['method']?.toString() ?? ''; // 加密方法(Shadowsocks等)
final protocols = json['protocols']?.toString() ?? ''; // 协议配置JSON
// 🔧 如果有 protocols 字段,从中解析 port 和 cipher
if (protocols.isNotEmpty) {
try {
final protocolsList = jsonDecode(protocols) as List;
if (protocolsList.isNotEmpty) {
final firstProtocol = protocolsList[0] as Map<String, dynamic>;
// 优先使用 protocols 中的配置
if (firstProtocol['port'] != null) {
port = _parseIntSafely(firstProtocol['port']);
}
if (firstProtocol['cipher'] != null && firstProtocol['cipher'].toString().isNotEmpty) {
method = firstProtocol['cipher'].toString();
}
KRLogUtil.kr_i('从 protocols 解析: port=$port, cipher=$method', tag: 'NodeList');
}
} catch (e) {
KRLogUtil.kr_w('解析 protocols 字段失败: $e', tag: 'NodeList');
}
}
return KrNodeListItem(
id: _parseIntSafely(json['id']),
@@ -116,6 +144,8 @@ class KrNodeListItem {
relayNode: json['relay_node']?.toString() ?? '',
serverAddr: serverAddr,
port: port,
method: method,
protocols: protocols,
speedLimit: _parseIntSafely(json['speed_limit']),
tags: _parseStringList(json['tags']),
traffic: _parseIntSafely(json['traffic']),
@@ -142,6 +172,8 @@ class KrNodeListItem {
protocol: '',
serverAddr: '',
port: 0,
method: '',
protocols: '',
speedLimit: 0,
tags: [],
traffic: 0,
+15 -3
View File
@@ -6,7 +6,11 @@ class KRUserInfo {
final String avatar;
final String areaCode;
final String telephone;
final int balance;
final int balance;
final int commission;
final int referralPercentage;
final bool onlyFirstPurchase;
final int giftAmount;
KRUserInfo({
required this.id,
@@ -16,7 +20,11 @@ class KRUserInfo {
this.avatar = '',
this.areaCode = '',
this.telephone = '',
this.balance = 0
this.balance = 0,
this.commission = 0,
this.referralPercentage = 0,
this.onlyFirstPurchase = false,
this.giftAmount = 0,
});
factory KRUserInfo.fromJson(Map<String, dynamic> json) {
@@ -28,7 +36,11 @@ class KRUserInfo {
avatar: json['avatar'] ?? '',
areaCode: json['area_code'] ?? '',
telephone: json['telephone'] ?? '',
balance: json['balance'] ?? 0,
balance: json['balance'] ?? 0,
commission: json['commission'] ?? 0,
referralPercentage: json['referral_percentage'] ?? 0,
onlyFirstPurchase: json['only_first_purchase'] ?? false,
giftAmount: json['gift_amount'] ?? 0,
);
}
}