From 2e8d8097685168b3c26d9fef396778ebf2d48bbf Mon Sep 17 00:00:00 2001
From: wuhanqing <554553400@qq.com>
Date: Fri, 7 Jun 2024 14:42:55 +0800
Subject: [PATCH] UPDATE ParseShadowsocks
---
.github/workflows/release_tag.yml | 2 +-
CHANGELOG.md | 5 ++
decode/shadowsocks.go | 115 +++++++++++++++++-------------
decode/stream.go | 12 ++--
docs/coverpage.md | 2 +-
parse_nodes_test.go | 19 ++++-
proxy_node.go | 3 -
v2ray_parse.go | 2 +-
8 files changed, 94 insertions(+), 66 deletions(-)
diff --git a/.github/workflows/release_tag.yml b/.github/workflows/release_tag.yml
index 2d22c03..261291d 100644
--- a/.github/workflows/release_tag.yml
+++ b/.github/workflows/release_tag.yml
@@ -78,7 +78,7 @@ jobs:
- name: Build
run: |
mkdir -p build_assets
- go build -v -o build_assets/v2raypool -trimpath -ldflags "-s -w -buildid= -X 'main.AppVersion=v1.6.3'" ./main
+ go build -v -o build_assets/v2raypool -trimpath -ldflags "-s -w -buildid= -X 'main.AppVersion=v1.6.4'" ./main
- name: Rename Windows File
if: matrix.goos == 'windows'
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 92a1f6b..40df3d2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,10 @@
## 升级日志
+### v1.6.4
+
+1. 新增删除节点功能
+2. 更新ss://节点格式解析规则
+
### v1.6.3
- 添加清除应用缓存功能
diff --git a/decode/shadowsocks.go b/decode/shadowsocks.go
index 9e37214..1ee712d 100644
--- a/decode/shadowsocks.go
+++ b/decode/shadowsocks.go
@@ -15,52 +15,66 @@ type Shadowsocks struct {
Port int
}
-// ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTozNlpDSGVhYlVTZktqZlFFdko0SERW@185.242.86.156:54170#%E4%BF%84%E7%BD%97%E6%96%AF+V2CROSS.COM
-func ParseShadowsocks(u string) (ss Shadowsocks, err error) {
- // var t *nurl.URL
- // t, err = nurl.Parse(u)
- // if err != nil {
- // err = fmt.Errorf("invalid ss:// format")
- // return
- // }
- // ss.Title = t.Fragment
- // ss.Address = t.Hostname()
- // ss.Port, err = strconv.Atoi(t.Port())
- // if err != nil {
- // return
- // }
- // username := t.User.String()
- // username, _ = Base64URLDecode(username)
- // pwdinfos := strings.SplitN(username, ":", 2)
- // if len(pwdinfos) != 2 {
- // err = fmt.Errorf("parse password err")
- // return
- // }
- // ss.Cipher = pwdinfos[0]
- // ss.Password = pwdinfos[1]
-
- ninfo := strings.Split(u, "://")
- if len(ninfo) != 2 {
- err = fmt.Errorf("split :// err")
+func ssrParse(u string) (ss Shadowsocks, uu *nurl.URL, err error) {
+ uu, err = nurl.Parse(u)
+ if err != nil {
+ err = fmt.Errorf("invalid ss:// format")
return
}
- v := ninfo[1]
-
- pwdsplit := strings.Split(v, "@")
- pwdinfo := pwdsplit[0]
- var b1 string
- b1, err = Base64StdDecode(pwdinfo) // base64.StdEncoding.DecodeString(pwdinfo)
+ ss.Title = uu.Fragment
+ ss.Address = uu.Hostname()
+ ss.Port, err = strconv.Atoi(uu.Port())
if err != nil {
- err = fmt.Errorf("err(%v) for Base64StdDecode", err)
return
}
- pwdsplit2 := strings.Split(b1, ":")
- ss.Cipher = pwdsplit2[0]
- ss.Password = pwdsplit2[1]
- if strings.Contains(pwdsplit[1], "/?") {
- addrsplit := strings.Split(pwdsplit[1], `/?`)
- addrsplit2 := strings.Split(addrsplit[0], `:`)
- argspre, _ := nurl.QueryUnescape(addrsplit[1])
+ username := uu.User.String()
+ username, _ = Base64URLDecode(username)
+ pwdinfos := strings.SplitN(username, ":", 2)
+ if len(pwdinfos) != 2 {
+ err = fmt.Errorf("parse password err")
+ return
+ }
+ ss.Cipher = pwdinfos[0]
+ ss.Password = pwdinfos[1]
+ // ss.Plugin = uu.Query().Get("plugin")
+ ss.TransportStream.Path = uu.Query().Get("path")
+ ss.TransportStream.Protocol = uu.Query().Get("mode")
+ return
+}
+
+// ParseShadowsocks. parse shadowsocks protocol url string. begin with: ss://
+func ParseShadowsocks(u string) (ss Shadowsocks, err error) {
+ var uu *nurl.URL
+ ss, uu, err = ssrParse(u)
+ if err != nil {
+ u = u[5:]
+ var l, ps string
+ if ind := strings.Index(u, "#"); ind > -1 {
+ l = u[:ind]
+ ps = u[ind+1:]
+ } else {
+ l = u
+ }
+ l, err = Base64StdDecode(l)
+ if err != nil {
+ l, err = Base64URLDecode(l)
+ if err != nil {
+ return
+ }
+ }
+ u = "ss://" + l
+ if ps != "" {
+ u += "#" + ps
+ }
+ ss, uu, err = ssrParse(u)
+ if err != nil {
+ return
+ }
+ }
+
+ if uu.RawQuery != "" {
+ argspre, _ := nurl.QueryUnescape(uu.RawQuery)
+
args := strings.Split(argspre, `;`)
for _, arg := range args {
if strings.Contains(arg, "=") {
@@ -68,28 +82,27 @@ func ParseShadowsocks(u string) (ss Shadowsocks, err error) {
argval := argsplit[1]
// plugin=v2ray-plugin
if argsplit[0] == "mode" {
- if argval == "websocket" {
- argval = "ws"
+ if ss.TransportStream.Protocol == "" {
+ ss.TransportStream.Protocol = argval
}
- ss.TransportStream.Protocol = argval
}
if argsplit[0] == "path" {
- ss.TransportStream.Path = argval
+ if ss.TransportStream.Path == "" {
+ ss.TransportStream.Path = argval
+ }
}
// if argsplit[0] == "mux"{
// // mux=true
// }
}
- if strings.Contains(arg, "#") {
- ss.Title = strings.Replace(arg, "#", "", 1)
- }
if arg == "tls" {
ss.TransportStream.Security = arg
- // nd.Tls = "tls"
}
}
- ss.Address = addrsplit2[0]
- ss.Port, err = strconv.Atoi(addrsplit2[1])
+ }
+
+ if ss.TransportStream.Protocol == "websocket" {
+ ss.TransportStream.Protocol = "ws"
}
return
}
diff --git a/decode/stream.go b/decode/stream.go
index 2907b2f..e77413f 100644
--- a/decode/stream.go
+++ b/decode/stream.go
@@ -14,12 +14,12 @@ type StreamConfig struct {
Protocol, Security, Path string
}
-func NewStreamConfig(proto string) *StreamConfig {
- if proto == "ws" {
- proto = "websocket"
- }
- return &StreamConfig{Protocol: proto}
-}
+// func NewStreamConfig(proto string) *StreamConfig {
+// if proto == "ws" {
+// proto = "websocket"
+// }
+// return &StreamConfig{Protocol: proto}
+// }
// {
// "transport":"tcp",
diff --git a/docs/coverpage.md b/docs/coverpage.md
index 504be93..2e8d84e 100644
--- a/docs/coverpage.md
+++ b/docs/coverpage.md
@@ -1,6 +1,6 @@
-# V2rayPool v1.6.3
+# V2rayPool v1.6.4
> 简单易用的v2ray客户端和代理池服务
diff --git a/parse_nodes_test.go b/parse_nodes_test.go
index 95b598c..34a3fc5 100644
--- a/parse_nodes_test.go
+++ b/parse_nodes_test.go
@@ -9,9 +9,22 @@ import (
"github.com/iotames/v2raypool/decode"
)
-// func TestInitSubscribeData(t *testing.T) {}
-type TestSubscribeData1 struct {
- Protocol, Data string
+func TestParseShadowsocks(t *testing.T) {
+ rawnds := []string{
+ `ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTozNlpDSGVhYlVTZktqZlFFdko0SERW@ru1.abcd.com:1234/?plugin=v2ray-plugin%3bmode%3dwebsocket%3bpath%3d%2f%3bmux%3dtrue%3b#abcd-RU-Ru1`,
+ `ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTozNlpDSGVhYlVTZktqZlFFdko0SERW@usus.cdn.lifhgsgadjsad.xyz:47545#%F0%9F%87%BA%F0%9F%87%B8%20United%20States01`,
+ `ss://Y2hhY2hhMjAtaWV0Zi1wb2x5MTMwNTozNlpDSGVhYlVTZktqZlFFdko0SERW@185.242.86.156:54170#%E4%BF%84%E7%BD%97%E6%96%AF+V2CROSS.COM`,
+ }
+ rawdata := base64.StdEncoding.EncodeToString([]byte(strings.Join(rawnds, "\n")))
+ dt, err := decode.ParseSubscribeByRaw(rawdata)
+ if err != nil {
+ t.Error(err)
+ }
+ nds := ParseV2rayNodes(dt)
+ if len(nds) != len(rawnds) {
+ t.Error("ParseV2rayNodes err")
+ }
+ // t.Logf("---TestParseShadowsocks---Result(%+v)---", nds)
}
// trojan://telegram-id-directvpn@18.224.236.198:22222?security=tls&&%E7%BE%8E%E5%9B%BD+Amazon%E6%95%B0%E6%8D%AE%E4%B8%AD%E5%BF%83
diff --git a/proxy_node.go b/proxy_node.go
index 5a248ac..4c115de 100644
--- a/proxy_node.go
+++ b/proxy_node.go
@@ -88,9 +88,6 @@ func (p ProxyNode) IsOk() bool {
return time.Since(p.TestAt) < time.Hour*24
}
-// // {"add":"jp6.xxx.top","host":"","id":"0999AE93-1330-4A75-DBC1-0DD545F7DD60","net":"ws","path":"","port":"41444","ps":"xxx-v2-JP-Tokyo6(1)","tls":"","v":2,"aid":0,"type":"none"}
-// protocol, add, port id, net
-
type ProxyNodes []ProxyNode
func (s ProxyNodes) Len() int { return len(s) }
diff --git a/v2ray_parse.go b/v2ray_parse.go
index e5b3bef..c4a3d62 100644
--- a/v2ray_parse.go
+++ b/v2ray_parse.go
@@ -71,7 +71,7 @@ func parseNodeInfo(d string) (nd V2rayNode, err error) {
nd.Tls = ss.TransportStream.Security
nd.Path = ss.TransportStream.Path
nd.Ps = strings.TrimSpace(ss.Title)
- if nd.Id == "" || nd.Type == "" || ss.Port == 0 || nd.Add == "" || nd.Net == "" {
+ if nd.Id == "" || nd.Type == "" || ss.Port == 0 || nd.Add == "" {
err = fmt.Errorf("---parse--shadowsocks--err--ss://--raw(%s)---nd(%+v)", ssdata, nd)
return
}