Inner uri#9245
Conversation
This comment was marked as outdated.
This comment was marked as outdated.
|
功能挺好,就是这个导出的名称看不懂; |
|
Done |
There was a problem hiding this comment.
Pull request overview
This PR introduces a v2rayN-specific “inner URI” (v2rayn://...) format for exporting/importing profiles (including extra/non-standard fields) and wires it into both the WPF and Avalonia UI as an export-to-clipboard action.
Changes:
- Add UI menu + command binding to export selected profiles as v2rayN internal share links to the clipboard.
- Implement
InnerFmtto serialize profiles tov2rayn://{type}/{urlsafe-b64-json}and to resolve/import them back (including policy-group reference rewriting). - Extend batch import to recognize and import
v2rayn://links; add a unit test for policy-group round-tripping.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| v2rayN/v2rayN/Views/ProfilesView.xaml.cs | Bind new Export2InnerUriCmd to the WPF menu item. |
| v2rayN/v2rayN/Views/ProfilesView.xaml | Add WPF menu entry for exporting internal share links. |
| v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml.cs | Bind new Export2InnerUriCmd to the Avalonia menu item. |
| v2rayN/v2rayN.Desktop/Views/ProfilesView.axaml | Add Avalonia menu entry for exporting internal share links. |
| v2rayN/ServiceLib/ViewModels/ProfilesViewModel.cs | Add Export2InnerUriCmd and export implementation using InnerFmt.ToUri. |
| v2rayN/ServiceLib/Resx/ResUI.resx | Add menuExport2InnerUri resource key (default locale). |
| v2rayN/ServiceLib/Resx/ResUI.zh-Hans.resx | Add Simplified Chinese translation for new menu label. |
| v2rayN/ServiceLib/Resx/ResUI.zh-Hant.resx | Add Traditional Chinese resource entry for new menu label. |
| v2rayN/ServiceLib/Resx/ResUI.ru.resx | Add Russian resource entry for new menu label (English fallback text). |
| v2rayN/ServiceLib/Resx/ResUI.hu.resx | Add Hungarian resource entry for new menu label (English fallback text). |
| v2rayN/ServiceLib/Resx/ResUI.fr.resx | Add French resource entry for new menu label (English fallback text). |
| v2rayN/ServiceLib/Resx/ResUI.fa-Ir.resx | Add Persian resource entry for new menu label (English fallback text). |
| v2rayN/ServiceLib/Resx/ResUI.Designer.cs | Expose menuExport2InnerUri via strongly-typed resource accessor. |
| v2rayN/ServiceLib/Handler/Fmt/InnerFmt.cs | New formatter/parser for the internal share-link format with group reference handling. |
| v2rayN/ServiceLib/Handler/ConfigHandler.cs | Add inner-URI batch import and invoke it from AddBatchServers. |
| v2rayN/ServiceLib/Global.cs | Define Global.InnerUriProtocol = "v2rayn://" constant. |
| v2rayN/ServiceLib.Tests/Fmt/InnerFmtTests.cs | Add unit test validating policy-group reference round-trip behavior. |
Files not reviewed (1)
- v2rayN/ServiceLib/Resx/ResUI.Designer.cs: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| var innerUriCount = await AddBatchServers4InnerUri(config, strData, subid, isSub); | ||
| if (innerUriCount > 0) | ||
| { | ||
| if (counter > 0) | ||
| { | ||
| counter += innerUriCount; | ||
| } | ||
| else | ||
| { | ||
| counter = innerUriCount; | ||
| } |
| EConfigType.VMess => await AddVMessServer(config, profileItem), | ||
| EConfigType.Shadowsocks => await AddShadowsocksServer(config, profileItem), | ||
| EConfigType.HTTP => await AddHttpServer(config, profileItem), | ||
| EConfigType.SOCKS => await AddSocksServer(config, profileItem), | ||
| EConfigType.Trojan => await AddTrojanServer(config, profileItem), | ||
| EConfigType.VLESS => await AddVlessServer(config, profileItem), | ||
| EConfigType.Hysteria2 => await AddHysteria2Server(config, profileItem), | ||
| EConfigType.TUIC => await AddTuicServer(config, profileItem), | ||
| EConfigType.WireGuard => await AddWireguardServer(config, profileItem), | ||
| EConfigType.Anytls => await AddAnytlsServer(config, profileItem), | ||
| EConfigType.Naive => await AddNaiveServer(config, profileItem), | ||
| EConfigType.PolicyGroup or EConfigType.ProxyChain => await AddServerCommon(config, profileItem), |
| var trimmedLine = line.Trim(); | ||
| if (!line.StartsWith(Global.InnerUriProtocol, StringComparison.OrdinalIgnoreCase)) | ||
| { | ||
| continue; | ||
| } | ||
| var profileItem = ResolveSingle(trimmedLine); | ||
| if (profileItem is null) |
|
CC @fscarmen [ -s ${WORK_DIR}/cert/cert_200.pem ] && local CERT_200_JSON2=$(awk '{printf "%s\\n", $0}' ${WORK_DIR}/cert/cert_200.pem)
v2rayn://anytls/$(echo -n "{\"ConfigType\":11,\"CoreType\":24,\"ConfigVersion\":4,\"Remarks\":\"${NODE_NAME[21]} ${NODE_TAG[10]}\",\"Address\":\"${SERVER_IP_1}\",\"Port\":${PORT_NAIVE},\"Password\":\"${UUID[21]}\",\"StreamSecurity\":\"tls\",\"AllowInsecure\":\"false\",\"Sni\":\"${TLS_SERVER}\",\"Fingerprint\":\"firefox\",\"Cert\":\"${CERT_200_JSON2}\"}" | base64 -w0 | tr '+/' '-_' | tr -d '=')
v2rayn://naive/$(echo -n "{\"ConfigType\":12,\"CoreType\":24,\"ConfigVersion\":4,\"Remarks\":\"${NODE_NAME[22]} ${NODE_TAG[11]} http2\",\"Address\":\"${SERVER_IP_1}\",\"Port\":${PORT_NAIVE},\"Password\":\"${UUID[22]}\",\"Username\":\"${UUID[22]}\",\"StreamSecurity\":\"tls\",\"AllowInsecure\":\"false\",\"Sni\":\"${TLS_SERVER}\",\"Cert\":\"${CERT_200_JSON2}\"}" | base64 -w0 | tr '+/' '-_' | tr -d '=')
v2rayn://naive/$(echo -n "{\"ConfigType\":12,\"CoreType\":24,\"ConfigVersion\":4,\"Remarks\":\"${NODE_NAME[22]} ${NODE_TAG[11]} quic\",\"Address\":\"${SERVER_IP_1}\",\"Port\":${PORT_NAIVE},\"Password\":\"${UUID[22]}\",\"Username\":\"${UUID[22]}\",\"StreamSecurity\":\"tls\",\"AllowInsecure\":\"false\",\"Sni\":\"${TLS_SERVER}\",\"Cert\":\"${CERT_200_JSON2}\",\"ProtoExtraObj\":{\"CongestionControl\":\"bbr\",\"NaiveQuic\":true}}" | base64 -w0 | tr '+/' '-_' | tr -d '=') |
|
Nice,一直觉得v2rayN应该有自己一套分享规则。这次把证书指纹处理了,谢谢大佬啊!我今晚更新一下脚本先。 |
证书解析只认 v2rayN/v2rayN/ServiceLib/Manager/CertPemManager.cs Lines 353 to 378 in 2dc967b |
可以的。这个小意思,我看导出的,有 /r/n 的,我用一模一样的格式可以了,在 tuic / anyTLS / naive 上试过都可以了。至于 hysteria2 / trojan 用 xray 内核,分享链接可以短一点。 另外我从导出的v2rayN专属链接 base64 解码后 {"IndexId":"G9enRw","ConfigType":8,"CoreType":24,"ConfigVersion":4,"IsSub":false,"DisplayLog":true,"Remarks":"\uD83C\uDDFA\uD83C\uDDF8 dartnode tuic","Address":"126.58.142.198","Port":8883,"Password":"3ea4a724-31ff-4bba-993d-7dc07d1b67aa","Username":"3ea4a724-31ff-4bba-993d-7dc07d1b67aa","StreamSecurity":"tls","AllowInsecure":"false","Sni":"addons.mozilla.org","Alpn":"h3","Cert":"-----BEGIN CERTIFICATE-----\r\nMIIBcTCCARagAwIBAgIUNoU6kcynHFQXOyb48Q8AMhsueG0wCgYIKoZIzj0EAwIw\r\nFjEUMBIGA1UEAwwLbW96aWxsYS5vcmcwIBcNMjYwNDI2MDcxMTMwWhgPMjEyNjA0\r\nMDIwNzExMzBaMBYxFDASBgNVBAMMC21vemlsbGEub3JnMFkwEwYHKoZIzj0CAQYI\r\nKoZIzj0DAQcDQgAEcyJ4UIMgBAUwT6s486g2cM/nKthnHOQfxsNDDFh507DsJ68Z\r\n/x0tUIcp1ojAXBp+kRSDlbukec9YcBJJn2ZHkaNAMD4wHQYDVR0RBBYwFIISYWRk\r\nb25zLm1vemlsbGEub3JnMB0GA1UdDgQWBBTojkmCuCz+esQcVVLL/ZhgiyRBLjAK\r\nBggqhkjOPQQDAgNJADBGAiEA3szKvP+M2XOKZc6kXGltW3BdgkY9sSr5Zy3OuBbu\r\nARACIQCHCrpYLnYg2MDRndLq/hHGMd2p/4c7mVdTUR5MWBmWog==\r\n-----END CERTIFICATE-----","CertSha":"AD43F6CF705E4C3FAB96AFFA9D58481D29AA908DB977973E8BBDBDA521565A05","AlterId":0,"ProtoExtraObj":{"CongestionControl":"bbr","VmessSecurity":"auto","VlessEncryption":"none","WgMtu":1280},"TransportExtraObj":{"RawHeaderType":"none","XhttpMode":"auto","GrpcMode":"gun","KcpHeaderType":"none"}} 我没有要 IndexId ,IsSub, DisplayLog 和 CertSha 及之后的,再编码导入 v2rayN,是可以通的,这些是不是都不需要的。
|
你问的对,是可以不要 tuic 的。 |
必须要啦,有了 v2rayN 专属的规范,N 和 NG 共用就方便了。 |
是的,必填字段只有 ConfigType,ConfigVersion,Remarks,否则导入失败
需要
目前是这样,只是给用户容易辨别是什么协议 |
|
原来各协议通过base64编码后弄成订阅是可以的,现在 如
结果有4个 v2rayn:// 的不行,分别是 anyTLS , tuic, naive 的两个 |
|
|
有个问题要讨论下, |
|
受限是 功能 兼容 还是与其他软件交互上的? |
|
|
个人意见, 所以如果再加个 DTO 也是要做到和 ProfileItem 字段一一映射,感觉好处不大? |
|
感觉二层结构不赖吧,层次更强 一层结构感觉不如直接用 URL query 序列化过去 |
|
为什么我会提出前面的讨论呢, 如果我们有不同的意见,那保持现在的先不动。 |
v2rayN 内部分享链接
用于备份配置,同时可用于分享协议标准提案外字段
概览
Json Payload
普通 http 节点:
{ "IndexId": "AIy0Iw", "ConfigType": 10, "ConfigVersion": 4, "Remarks": "example", "Address": "127.0.0.1", "Port": 8080, "Password": "pass", "Username": "user" }策略组:
指向其他节点 IndexId:
{ "IndexId": "oWjrYw", "ConfigType": 101, "CoreType": 2, "ConfigVersion": 4, "Remarks": "example_group", "ProtoExtraObj": { "ChildItems": "AIy0Iw", "MultipleLoad": 0 } }按其他节点 Remark 筛选:
{ "IndexId": "slDgGA", "ConfigType": 101, "CoreType": 2, "ConfigVersion": 4, "Remarks": "example_group", "ProtoExtraObj": { "SubChildItems": "self", "Filter": "example", "MultipleLoad": 0 } }注:
ProtoExtraObj.ChildItems指向其他节点的 IndexIdProtoExtraObj.SubChildItems为self,ProtoExtraObj.Filter筛选 支持正则示例