From e59ff68443d28de5fb0cf1e4534615849bdb1d59 Mon Sep 17 00:00:00 2001 From: Sansui233 Date: Wed, 2 Dec 2020 03:49:15 +0800 Subject: [PATCH] add clash getter --- config/source.yaml | 7 +++- go.mod | 1 + internal/database/db.go | 2 +- log/log.go | 2 +- pkg/getter/base.go | 11 ++++++ pkg/getter/clash.go | 74 +++++++++++++++++++++++++++++++++++ pkg/getter/web_fuzz_sub.go | 6 ++- pkg/healthcheck/delaycheck.go | 4 +- pkg/healthcheck/speedcheck.go | 4 +- pkg/proxy/base.go | 40 +++++++++++++++++++ 10 files changed, 143 insertions(+), 8 deletions(-) create mode 100644 pkg/getter/clash.go diff --git a/config/source.yaml b/config/source.yaml index 5f1864ac..53d0bf5f 100644 --- a/config/source.yaml +++ b/config/source.yaml @@ -24,6 +24,11 @@ options: url: https://fanqiangdang.com/forum-48-1.html +# clash格式订阅链接 +- type: clash + options: + url: https://raw.githubusercontent.com/du5/free/master/file/0909/Clash.yaml + # 某个网站抓取 - type: web-freessrxyz - options: + options: \ No newline at end of file diff --git a/go.mod b/go.mod index 29da3837..1bcecbad 100644 --- a/go.mod +++ b/go.mod @@ -42,6 +42,7 @@ require ( gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect gopkg.in/sourcemap.v1 v1.0.5 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c gorm.io/driver/postgres v1.0.5 gorm.io/gorm v1.20.7 ) diff --git a/internal/database/db.go b/internal/database/db.go index ef0aad75..374a88d0 100644 --- a/internal/database/db.go +++ b/internal/database/db.go @@ -29,7 +29,7 @@ func connect() (err error) { log.Infoln("database: successfully connected to: %s", DB.Name()) } else { DB = nil - log.Warnln("database connection Infoln: %s \n\t\tUse cache to store proxies", err.Error()) + log.Warnln("database connection info: %s \n\t\tUse cache to store proxies", err.Error()) } return } diff --git a/log/log.go b/log/log.go index 6cf2069c..51fccafc 100644 --- a/log/log.go +++ b/log/log.go @@ -50,7 +50,7 @@ func Infoln(format string, v ...interface{}) { } func Warnln(format string, v ...interface{}) { - log.Errorln(fmt.Sprintf(format, v...)) + log.Warnln(fmt.Sprintf(format, v...)) logToFile(WARNING, fmt.Sprintf(format, v...)) } diff --git a/pkg/getter/base.go b/pkg/getter/base.go index 051ea29f..d58a1d79 100644 --- a/pkg/getter/base.go +++ b/pkg/getter/base.go @@ -45,6 +45,17 @@ func StringArray2ProxyArray(origin []string) proxy.ProxyList { return results } +func ClashProxy2ProxyArray(origin []map[string]interface{}) proxy.ProxyList { + results := make(proxy.ProxyList, 0, len(origin)) + for _, pjson := range origin { + p, err := proxy.ParseProxyFromClashProxy(pjson) + if err == nil && p != nil { + results = append(results, p) + } + } + return results +} + func GrepLinksFromString(text string) []string { results := proxy.GrepSSRLinkFromString(text) results = append(results, proxy.GrepVmessLinkFromString(text)...) diff --git a/pkg/getter/clash.go b/pkg/getter/clash.go new file mode 100644 index 00000000..d1842fe2 --- /dev/null +++ b/pkg/getter/clash.go @@ -0,0 +1,74 @@ +package getter + +import ( + "github.com/Sansui233/proxypool/log" + "github.com/Sansui233/proxypool/pkg/proxy" + "github.com/Sansui233/proxypool/pkg/tool" + "gopkg.in/yaml.v3" + "io/ioutil" + "sync" +) + +func init() { + Register("clash", NewClashGetter) +} + +type Clash struct { + Url string +} + +type config struct { + Proxy []map[string]interface{} `json:"proxies" yaml:"proxies"` +} + +func (c *Clash) Get() proxy.ProxyList { + resp, err := tool.GetHttpClient().Get(c.Url) + if err != nil { + return nil + } + defer resp.Body.Close() + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil + } + + conf := config{} + err = yaml.Unmarshal(body, &conf) + if err != nil { + return nil + } + + return ClashProxy2ProxyArray(conf.Proxy) + +} + +func (c *Clash) Get2Chan(pc chan proxy.Proxy) { + nodes := c.Get() + log.Infoln("STATISTIC: Clash\tcount=%d\turl=%s\n", len(nodes), c.Url) + for _, node := range nodes { + pc <- node + } +} + +func (c *Clash) Get2ChanWG(pc chan proxy.Proxy, wg *sync.WaitGroup) { + defer wg.Done() + nodes := c.Get() + log.Infoln("STATISTIC: Clash\tcount=%d\turl=%s\n", len(nodes), c.Url) + for _, node := range nodes { + pc <- node + } +} + +func NewClashGetter(options tool.Options) (getter Getter, err error) { + urlInterface, found := options["url"] + if found { + url, err := AssertTypeStringNotNull(urlInterface) + if err != nil { + return nil, err + } + return &Clash{ + Url: url, + }, nil + } + return nil, ErrorUrlNotFound +} diff --git a/pkg/getter/web_fuzz_sub.go b/pkg/getter/web_fuzz_sub.go index 281e7943..6e74fd79 100644 --- a/pkg/getter/web_fuzz_sub.go +++ b/pkg/getter/web_fuzz_sub.go @@ -32,7 +32,11 @@ func (w *WebFuzzSub) Get() proxy.ProxyList { subUrls := urlRe.FindAllString(text, -1) result := make(proxy.ProxyList, 0) for _, url := range subUrls { - result = append(result, (&Subscribe{Url: url}).Get()...) + newResult := (&Subscribe{Url: url}).Get() + if len(newResult) == 0 { + newResult = (&Clash{Url: url}).Get() + } + result = result.UniqAppendProxyList(newResult) } return result } diff --git a/pkg/healthcheck/delaycheck.go b/pkg/healthcheck/delaycheck.go index 7a91ff43..69ddcc7d 100644 --- a/pkg/healthcheck/delaycheck.go +++ b/pkg/healthcheck/delaycheck.go @@ -88,8 +88,8 @@ func testDelay(p proxy.Proxy) (delay uint16, err error) { pmap["port"] = int(pmap["port"].(float64)) if p.TypeName() == "vmess" { pmap["alterId"] = int(pmap["alterId"].(float64)) - if network := pmap["network"].(string); network == "h2" { - return 10, nil // todo 暂无方法测试h2的延迟,clash对于h2的connection会阻塞。但暂时不丢弃 + if network, ok := pmap["network"]; ok && network.(string) == "h2" { + return 0, nil // todo 暂无方法测试h2的延迟,clash对于h2的connection会阻塞 } } diff --git a/pkg/healthcheck/speedcheck.go b/pkg/healthcheck/speedcheck.go index 07cc9540..6c2c5aa9 100644 --- a/pkg/healthcheck/speedcheck.go +++ b/pkg/healthcheck/speedcheck.go @@ -135,8 +135,8 @@ func ProxySpeedTest(p proxy.Proxy) (speedResult float64, err error) { pmap["port"] = int(pmap["port"].(float64)) if p.TypeName() == "vmess" { pmap["alterId"] = int(pmap["alterId"].(float64)) - if network := pmap["network"].(string); network == "h2" { - return 0, nil // todo 暂无方法测试h2的延迟,clash对于h2的connection会阻塞。但暂时不丢弃 + if network, ok := pmap["network"]; ok && network.(string) == "h2" { + return 0, nil // todo 暂无方法测试h2的速度,clash对于h2的connection会阻塞 } } diff --git a/pkg/proxy/base.go b/pkg/proxy/base.go index 537ab01c..c329fedd 100644 --- a/pkg/proxy/base.go +++ b/pkg/proxy/base.go @@ -1,6 +1,7 @@ package proxy import ( + "encoding/json" "errors" "strings" ) @@ -99,3 +100,42 @@ func ParseProxyFromLink(link string) (p Proxy, err error) { //} return } + +func ParseProxyFromClashProxy(p map[string]interface{}) (proxy Proxy, err error) { + p["name"] = "" + pjson, err := json.Marshal(p) + if err != nil { + return nil, err + } + switch p["type"].(string) { + case "ss": + var proxy Shadowsocks + err := json.Unmarshal(pjson, &proxy) + if err != nil { + return nil, err + } + return &proxy, nil + case "ssr": + var proxy ShadowsocksR + err := json.Unmarshal(pjson, &proxy) + if err != nil { + return nil, err + } + return &proxy, nil + case "vmess": + var proxy Vmess + err := json.Unmarshal(pjson, &proxy) + if err != nil { + return nil, err + } + return &proxy, nil + case "trojan": + var proxy Trojan + err := json.Unmarshal(pjson, &proxy) + if err != nil { + return nil, err + } + return &proxy, nil + } + return nil, errors.New("clash json parse failed") +}