Compare commits

...

10 Commits

Author SHA1 Message Date
zu1k
49e1105763 try to fix ssr base64 2020-09-04 17:51:15 +08:00
zu1k
5fde0b6658 add link for all proxies 2020-09-04 17:13:19 +08:00
zu1k
6b769ef998 fix preFilter error & mod sssub 2020-09-04 17:08:43 +08:00
zu1k
458ba6dd35 fix bugs 2020-09-04 16:49:32 +08:00
zu1k
82f6e1dae8 add sub support 2020-09-04 16:40:50 +08:00
zu1k
9de327fb29 add link export for vmess 2020-09-04 16:40:50 +08:00
zu1k
0e88bb62b5 add link export support for ssr 2020-09-04 16:40:50 +08:00
zu1k
ef1b6eab6b add link export for ss & trojan 2020-09-04 16:40:50 +08:00
dependabot[bot]
fb90213e33 Bump github.com/cloudflare/cloudflare-go from 0.13.1 to 0.13.2
Bumps [github.com/cloudflare/cloudflare-go](https://github.com/cloudflare/cloudflare-go) from 0.13.1 to 0.13.2.
- [Release notes](https://github.com/cloudflare/cloudflare-go/releases)
- [Commits](https://github.com/cloudflare/cloudflare-go/compare/v0.13.1...v0.13.2)

Signed-off-by: dependabot[bot] <support@github.com>
2020-09-04 16:40:50 +08:00
zu1k
a87e298002 check all proxies's health every time 2020-08-30 15:02:19 +08:00
17 changed files with 440 additions and 92 deletions

View File

@@ -4,6 +4,7 @@ import (
"html/template"
"net/http"
"os"
"strconv"
"github.com/gin-gonic/gin"
_ "github.com/heroku/x/hmetrics/onload"
@@ -13,7 +14,7 @@ import (
"github.com/zu1k/proxypool/pkg/provider"
)
const version = "v0.3.4"
const version = "v0.3.5"
var router *gin.Engine
@@ -75,41 +76,124 @@ func setupRouter() {
text = cache.GetString("clashproxies")
if text == "" {
proxies := cache.GetProxies("proxies")
clash := provider.Clash{Proxies: proxies}
clash := provider.Clash{
provider.Base{
Proxies: &proxies,
},
}
text = clash.Provide()
cache.SetString("clashproxies", text)
}
} else if proxyTypes == "all" {
proxies := cache.GetProxies("allproxies")
clash := provider.Clash{
Proxies: proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
provider.Base{
Proxies: &proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
},
}
text = clash.Provide()
} else {
proxies := cache.GetProxies("proxies")
clash := provider.Clash{
Proxies: proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
provider.Base{
Proxies: &proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
},
}
text = clash.Provide()
}
c.String(200, text)
})
router.GET("/surge/proxies", func(c *gin.Context) {
text := cache.GetString("surgeproxies")
if text == "" {
proxies := cache.GetProxies("proxies")
surge := provider.Surge{Proxies: proxies}
proxyTypes := c.DefaultQuery("type", "")
proxyCountry := c.DefaultQuery("c", "")
proxyNotCountry := c.DefaultQuery("nc", "")
text := ""
if proxyTypes == "" && proxyCountry == "" && proxyNotCountry == "" {
text = cache.GetString("surgeproxies")
if text == "" {
proxies := cache.GetProxies("proxies")
surge := provider.Surge{
provider.Base{
Proxies: &proxies,
},
}
text = surge.Provide()
cache.SetString("surgeproxies", text)
}
} else if proxyTypes == "all" {
proxies := cache.GetProxies("allproxies")
surge := provider.Surge{
provider.Base{
Proxies: &proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
},
}
text = surge.Provide()
} else {
proxies := cache.GetProxies("proxies")
surge := provider.Surge{
provider.Base{
Proxies: &proxies,
Types: proxyTypes,
Country: proxyCountry,
NotCountry: proxyNotCountry,
},
}
text = surge.Provide()
cache.SetString("surgeproxies", text)
}
c.String(200, text)
})
router.GET("/ss/sub", func(c *gin.Context) {
proxies := cache.GetProxies("proxies")
ssSub := provider.SSSub{
provider.Base{
Proxies: &proxies,
Types: "ss",
},
}
c.String(200, ssSub.Provide())
})
router.GET("/ssr/sub", func(c *gin.Context) {
proxies := cache.GetProxies("proxies")
ssrSub := provider.SSRSub{
provider.Base{
Proxies: &proxies,
Types: "ssr",
},
}
c.String(200, ssrSub.Provide())
})
router.GET("/vmess/sub", func(c *gin.Context) {
proxies := cache.GetProxies("proxies")
vmessSub := provider.VmessSub{
provider.Base{
Proxies: &proxies,
Types: "vmess",
},
}
c.String(200, vmessSub.Provide())
})
router.GET("/link/:id", func(c *gin.Context) {
idx := c.Param("id")
proxies := cache.GetProxies("allproxies")
id, err := strconv.Atoi(idx)
if err != nil {
c.String(500, err.Error())
}
if id >= proxies.Len() {
c.String(500, "id too big")
}
c.String(200, proxies[id].Link())
})
}
func Run() {

2
go.mod
View File

@@ -9,7 +9,7 @@ require (
github.com/antchfx/htmlquery v1.2.3 // indirect
github.com/antchfx/xmlquery v1.2.4 // indirect
github.com/antchfx/xpath v1.1.8 // indirect
github.com/cloudflare/cloudflare-go v0.13.1
github.com/cloudflare/cloudflare-go v0.13.2
github.com/ghodss/yaml v1.0.0
github.com/gin-gonic/gin v1.6.3
github.com/go-bindata/go-bindata v3.1.2+incompatible // indirect

3
go.sum
View File

@@ -30,6 +30,8 @@ github.com/cloudflare/cloudflare-go v0.13.0 h1:Mx2gNz/r4H0eHETENq5ZPtc/kOX/uzEfT
github.com/cloudflare/cloudflare-go v0.13.0/go.mod h1:6rZ6s/XWxP8WIWMATgDM7aUop0Z0ZOAfcm/4rEd0lOY=
github.com/cloudflare/cloudflare-go v0.13.1 h1:8i8E5CubfAlD/2zWM7VGKoIPS2/x/lO/nRnqDl0j5Dk=
github.com/cloudflare/cloudflare-go v0.13.1/go.mod h1:27kfc1apuifUmJhp069y0+hwlKDg4bd8LWlu7oKeZvM=
github.com/cloudflare/cloudflare-go v0.13.2 h1:bhMGoNhAg21DuqJjU9jQepRRft6vYfo6pejT3NN4V6A=
github.com/cloudflare/cloudflare-go v0.13.2/go.mod h1:27kfc1apuifUmJhp069y0+hwlKDg4bd8LWlu7oKeZvM=
github.com/codegangsta/negroni v1.0.0/go.mod h1:v0y3T5G7Y1UlFfyxFn/QLRU4a2EuNau2iZY63YTKWo0=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -201,6 +203,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a h1:pa8hGb/2YqsZKovtsgrwcDH1RZhVbTKCjLp47XpqCDs=
github.com/smartystreets/goconvey v0.0.0-20190330032615-68dc04aab96a/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/soveran/redisurl v0.0.0-20180322091936-eb325bc7a4b8/go.mod h1:FVJ8jbHu7QrNFs3bZEsv/L5JjearIAY9N0oXh2wk+6Y=
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=

View File

@@ -19,7 +19,7 @@ func CrawlGo() {
wg.Add(1)
go g.Get2Chan(pc, wg)
}
proxies := cache.GetProxies("proxies")
proxies := cache.GetProxies("allproxies")
go func() {
wg.Wait()
close(pc)
@@ -32,7 +32,11 @@ func CrawlGo() {
// 节点去重
proxies = proxies.Deduplication()
log.Println("CrawlGo node count:", len(proxies))
proxies = provider.Clash{Proxies: proxies}.CleanProxies()
proxies = provider.Clash{
provider.Base{
Proxies: &proxies,
},
}.CleanProxies()
log.Println("CrawlGo cleaned node count:", len(proxies))
proxies.NameAddCounrty().Sort().NameAddIndex().NameAddTG()
log.Println("Proxy rename DONE!")
@@ -58,6 +62,14 @@ func CrawlGo() {
cache.SetProxies("proxies", proxies)
cache.UsefullProxiesCount = proxies.Len()
cache.SetString("clashproxies", provider.Clash{Proxies: proxies}.Provide())
cache.SetString("surgeproxies", provider.Surge{Proxies: proxies}.Provide())
cache.SetString("clashproxies", provider.Clash{
provider.Base{
Proxies: &proxies,
},
}.Provide())
cache.SetString("surgeproxies", provider.Surge{
provider.Base{
Proxies: &proxies,
},
}.Provide())
}

View File

@@ -1,5 +1,11 @@
package provider
import (
"strings"
"github.com/zu1k/proxypool/pkg/proxy"
)
type Provider interface {
Provide() string
}
@@ -12,3 +18,72 @@ func checkInList(list []string, item string) bool {
}
return false
}
type Base struct {
Proxies *proxy.ProxyList `yaml:"proxies"`
Types string `yaml:"type"`
Country string `yaml:"country"`
NotCountry string `yaml:"not_country"`
}
func (b *Base) preFilter() {
proxies := make(proxy.ProxyList, 0)
needFilterType := true
needFilterCountry := true
needFilterNotCountry := true
if b.Types == "" || b.Types == "all" {
needFilterType = false
}
if b.Country == "" || b.Country == "all" {
needFilterCountry = false
}
if b.NotCountry == "" {
needFilterNotCountry = false
}
types := strings.Split(b.Types, ",")
countries := strings.Split(b.Country, ",")
notCountries := strings.Split(b.NotCountry, ",")
bProxies := *b.Proxies
for _, p := range bProxies {
if needFilterType {
typeOk := false
for _, t := range types {
if p.TypeName() == t {
typeOk = true
break
}
}
if !typeOk {
goto exclude
}
}
if needFilterNotCountry {
for _, c := range notCountries {
if strings.Contains(p.BaseInfo().Name, c) {
goto exclude
}
}
}
if needFilterCountry {
countryOk := false
for _, c := range countries {
if strings.Contains(p.BaseInfo().Name, c) {
countryOk = true
break
}
}
if !countryOk {
goto exclude
}
}
proxies = append(proxies, p)
exclude:
}
b.Proxies = &proxies
}

View File

@@ -7,15 +7,12 @@ import (
)
type Clash struct {
Proxies proxy.ProxyList `yaml:"proxies"`
Types string `yaml:"type"`
Country string `yaml:"country"`
NotCountry string `yaml:"not_country"`
Base
}
func (c Clash) CleanProxies() (proxies proxy.ProxyList) {
proxies = make(proxy.ProxyList, 0)
for _, p := range c.Proxies {
for _, p := range *c.Proxies {
if checkClashSupport(p) {
proxies = append(proxies, p)
}
@@ -24,68 +21,15 @@ func (c Clash) CleanProxies() (proxies proxy.ProxyList) {
}
func (c Clash) Provide() string {
c.preFilter()
var resultBuilder strings.Builder
resultBuilder.WriteString("proxies:\n")
needFilterType := true
needFilterCountry := true
needFilterNotCountry := true
if c.Types == "" || c.Types == "all" {
needFilterType = false
}
if c.Country == "" || c.Country == "all" {
needFilterCountry = false
}
if c.NotCountry == "" {
needFilterNotCountry = false
}
types := strings.Split(c.Types, ",")
countries := strings.Split(c.Country, ",")
notCountries := strings.Split(c.NotCountry, ",")
for _, p := range c.Proxies {
if !checkClashSupport(p) {
continue
for _, p := range *c.Proxies {
if checkClashSupport(p) {
resultBuilder.WriteString(p.ToClash() + "\n")
}
if needFilterType {
typeOk := false
for _, t := range types {
if p.TypeName() == t {
typeOk = true
break
}
}
if !typeOk {
goto exclude
}
}
if needFilterNotCountry {
for _, c := range notCountries {
if strings.Contains(p.BaseInfo().Name, c) {
goto exclude
}
}
}
if needFilterCountry {
countryOk := false
for _, c := range countries {
if strings.Contains(p.BaseInfo().Name, c) {
countryOk = true
break
}
}
if !countryOk {
goto exclude
}
}
resultBuilder.WriteString(p.ToClash() + "\n")
exclude:
}
return resultBuilder.String()
}

21
pkg/provider/ssrsub.go Normal file
View File

@@ -0,0 +1,21 @@
package provider
import (
"strings"
"github.com/zu1k/proxypool/pkg/tool"
)
type SSRSub struct {
Base
}
func (sub SSRSub) Provide() string {
sub.Types = "ssr"
sub.preFilter()
var resultBuilder strings.Builder
for _, p := range *sub.Proxies {
resultBuilder.WriteString(p.Link() + "\n")
}
return tool.Base64EncodeString(resultBuilder.String(), false)
}

45
pkg/provider/sssub.go Normal file
View File

@@ -0,0 +1,45 @@
package provider
import (
"encoding/json"
"strconv"
"github.com/zu1k/proxypool/pkg/proxy"
)
type SSSub struct {
Base
}
type ssJson struct {
Remarks string `json:"remarks"`
Server string `json:"server"`
ServerPort string `json:"server_port"`
Method string `json:"method"`
Password string `json:"password"`
Plugin string `json:"plugin"`
PluginOpts map[string]interface{} `json:"plugin_opts"`
}
func (sub SSSub) Provide() string {
sub.Types = "ss"
sub.preFilter()
proxies := make([]ssJson, 0, sub.Proxies.Len())
for _, p := range *sub.Proxies {
pp := p.(*proxy.Shadowsocks)
proxies = append(proxies, ssJson{
Remarks: pp.Name,
Server: pp.Server,
ServerPort: strconv.Itoa(pp.Port),
Method: pp.Cipher,
Password: pp.Password,
Plugin: pp.Plugin,
PluginOpts: pp.PluginOpts,
})
}
text, err := json.Marshal(proxies)
if err != nil {
return ""
}
return string(text)
}

View File

@@ -7,18 +7,18 @@ import (
)
type Surge struct {
Proxies proxy.ProxyList `yaml:"proxies"`
Base
}
func (s Surge) Provide() string {
var resultBuilder strings.Builder
s.preFilter()
for _, p := range s.Proxies {
var resultBuilder strings.Builder
for _, p := range *s.Proxies {
if checkSurgeSupport(p) {
resultBuilder.WriteString(p.ToSurge() + "\n")
resultBuilder.WriteString(p.ToClash() + "\n")
}
}
return resultBuilder.String()
}

21
pkg/provider/vmesssub.go Normal file
View File

@@ -0,0 +1,21 @@
package provider
import (
"strings"
"github.com/zu1k/proxypool/pkg/tool"
)
type VmessSub struct {
Base
}
func (sub VmessSub) Provide() string {
sub.Types = "vmess"
sub.preFilter()
var resultBuilder strings.Builder
for _, p := range *sub.Proxies {
resultBuilder.WriteString(p.Link() + "\n")
}
return tool.Base64EncodeString(resultBuilder.String(), false)
}

View File

@@ -36,6 +36,7 @@ type Proxy interface {
String() string
ToClash() string
ToSurge() string
Link() string
Identifier() string
SetName(name string)
SetIP(ip string)

62
pkg/proxy/link_test.go Normal file
View File

@@ -0,0 +1,62 @@
package proxy
import (
"fmt"
"testing"
)
func TestSSLink(t *testing.T) {
ss, err := ParseSSLink("ss://YWVzLTI1Ni1jZmI6ZUlXMERuazY5NDU0ZTZuU3d1c3B2OURtUzIwMXRRMERAMTcyLjEwNC4xNjEuNTQ6ODA5OQ==#翻墙党223.13新加坡")
if err != nil {
t.Error(err)
}
fmt.Println(ss)
fmt.Println(ss.Link())
ss, err = ParseSSLink(ss.Link())
if err != nil {
t.Error(err)
}
fmt.Println(ss)
}
func TestSSRLink(t *testing.T) {
ssr, err := ParseSSRLink("ssr://MTcyLjEwNC4xNjEuNTQ6ODA5OTpvcmlnaW46YWVzLTI1Ni1jZmI6cGxhaW46WlVsWE1FUnVhelk1TkRVMFpUWnVVM2QxYzNCMk9VUnRVekl3TVhSUk1FUT0vP29iZnNwYXJhbT0mcHJvdG9wYXJhbT0mcmVtYXJrcz01Ny03NWFLWjVZV2FNakl6TGpFejVwYXc1WXFnNVoyaCZncm91cD01cGF3NVlxZzVaMmg=")
if err != nil {
t.Error(err)
}
fmt.Println(ssr)
fmt.Println(ssr.Link())
ssr, err = ParseSSRLink(ssr.Link())
if err != nil {
t.Error(err)
}
fmt.Println(ssr)
}
func TestTrojanLink(t *testing.T) {
trojan, err := ParseTrojanLink("trojan://65474277@sqcu.hostmsu.ru:55551?allowinsecure=0&peer=mza.hkfq.xyz&mux=1&ws=0&wspath=&wshost=&ss=0&ssmethod=aes-128-gcm&sspasswd=&group=#%E9%A6%99%E6%B8%AFCN2-MZA%E8%8A%82%E7%82%B9-%E5%AE%BF%E8%BF%81%E8%81%94%E9%80%9A%E4%B8%AD%E8%BD%AC")
if err != nil {
t.Error(err)
}
fmt.Println(trojan)
fmt.Println(trojan.Link())
trojan, err = ParseTrojanLink(trojan.Link())
if err != nil {
t.Error(err)
}
fmt.Println(trojan)
}
func TestVmessLink(t *testing.T) {
v, err := ParseVmessLink("vmess://ew0KICAidiI6ICIyIiwNCiAgInBzIjogIuW+ruS/oeWFrOS8l+WPtyDlpJrlvannmoTlpKfljYPkuJbnlYwiLA0KICAiYWRkIjogInMyNzEuc25vZGUueHl6IiwNCiAgInBvcnQiOiAiNDQzIiwNCiAgImlkIjogIjZhOTAwZDYzLWNiOTItMzVhMC1hZWYwLTNhMGMxMWFhODUyMyIsDQogICJhaWQiOiAiMSIsDQogICJuZXQiOiAid3MiLA0KICAidHlwZSI6ICJub25lIiwNCiAgImhvc3QiOiAiczI3MS5zbm9kZS54eXoiLA0KICAicGF0aCI6ICIvcGFuZWwiLA0KICAidGxzIjogInRscyINCn0=")
if err != nil {
t.Error(err)
}
fmt.Println(v)
fmt.Println(v.Link())
v, err = ParseVmessLink(v.Link())
if err != nil {
t.Error(err)
}
fmt.Println(v)
}

View File

@@ -65,6 +65,13 @@ func (ss Shadowsocks) Clone() Proxy {
return &ss
}
// https://shadowsocks.org/en/config/quick-guide.html
func (ss Shadowsocks) Link() (link string) {
payload := fmt.Sprintf("%s:%s@%s:%d", ss.Cipher, ss.Password, ss.Server, ss.Port)
payload = tool.Base64EncodeString(payload, false)
return fmt.Sprintf("ss://%s#%s", payload, ss.Name)
}
func ParseSSLink(link string) (*Shadowsocks, error) {
if !strings.HasPrefix(link, "ss://") {
return nil, ErrorNotSSRLink

View File

@@ -3,6 +3,7 @@ package proxy
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"net"
"net/url"
@@ -61,6 +62,19 @@ func (ssr ShadowsocksR) Clone() Proxy {
return &ssr
}
// https://github.com/HMBSbige/ShadowsocksR-Windows/wiki/SSR-QRcode-scheme
func (ssr ShadowsocksR) Link() (link string) {
payload := fmt.Sprintf("%s:%d:%s:%s:%s:%s",
ssr.Server, ssr.Port, ssr.Protocol, ssr.Cipher, ssr.Obfs, tool.Base64EncodeString(ssr.Password, true))
query := url.Values{}
query.Add("obfsparam", tool.Base64EncodeString(ssr.ObfsParam, true))
query.Add("protoparam", tool.Base64EncodeString(ssr.ProtocolParam, true))
query.Add("remarks", tool.Base64EncodeString(ssr.Name, true))
query.Add("group", tool.Base64EncodeString("proxy.tgbot.co", true))
payload = tool.Base64EncodeString(fmt.Sprintf("%s/?%s", payload, query.Encode()), true)
return fmt.Sprintf("ssr://%s", payload)
}
func ParseSSRLink(link string) (*ShadowsocksR, error) {
if !strings.HasPrefix(link, "ssr") {
return nil, ErrorNotSSRLink

View File

@@ -66,6 +66,24 @@ func (t Trojan) Clone() Proxy {
return &t
}
// https://p4gefau1t.github.io/trojan-go/developer/url/
func (t Trojan) Link() (link string) {
query := url.Values{}
if t.SNI != "" {
query.Set("sni", url.QueryEscape(t.SNI))
}
uri := url.URL{
Scheme: "trojan",
User: url.User(url.QueryEscape(t.Password)),
Host: net.JoinHostPort(t.Server, strconv.Itoa(t.Port)),
RawQuery: query.Encode(),
Fragment: t.Name,
}
return uri.String()
}
func ParseTrojanLink(link string) (*Trojan, error) {
if !strings.HasPrefix(link, "trojan://") && !strings.HasPrefix(link, "trojan-go://") {
return nil, ErrorNotTrojanink

View File

@@ -86,6 +86,14 @@ func (v Vmess) Clone() Proxy {
return &v
}
func (v Vmess) Link() (link string) {
vjv, err := json.Marshal(v.toLinkJson())
if err != nil {
return
}
return fmt.Sprintf("vmess://%s", tool.Base64EncodeBytes(vjv))
}
type vmessLinkJson struct {
Add string `json:"add"`
V string `json:"v"`
@@ -100,6 +108,27 @@ type vmessLinkJson struct {
Tls string `json:"tls"`
}
func (v Vmess) toLinkJson() vmessLinkJson {
vj := vmessLinkJson{
Add: v.Server,
Ps: v.Name,
Port: v.Port,
Id: v.UUID,
Aid: strconv.Itoa(v.AlterID),
Net: v.Network,
Path: v.WSPath,
Host: v.ServerName,
V: "2",
}
if v.TLS {
vj.Tls = "tls"
}
if host, ok := v.WSHeaders["HOST"]; ok && host != "" {
vj.Host = host
}
return vj
}
func ParseVmessLink(link string) (*Vmess, error) {
if !strings.HasPrefix(link, "vmess") {
return nil, ErrorNotVmessLink
@@ -190,10 +219,11 @@ func ParseVmessLink(link string) (*Vmess, error) {
}
port := 443
portInterface := vmessJson.Port
if i, ok := portInterface.(int); ok {
port = i
} else if s, ok := portInterface.(string); ok {
port, _ = strconv.Atoi(s)
switch portInterface.(type) {
case int:
port = portInterface.(int)
case string:
port, _ = strconv.Atoi(portInterface.(string))
}
alterId, err := strconv.Atoi(vmessJson.Aid)

View File

@@ -26,3 +26,14 @@ func Base64DecodeString(src string) (dst string, err error) {
dst = string(dstbytes)
return
}
func Base64EncodeString(origin string, urlsafe bool) (result string) {
if urlsafe {
return base64.URLEncoding.EncodeToString([]byte(origin))
}
return base64.StdEncoding.EncodeToString([]byte(origin))
}
func Base64EncodeBytes(origin []byte) (result string) {
return base64.StdEncoding.EncodeToString([]byte(origin))
}