1
0
mirror of https://github.com/nitezs/sub2sing-box.git synced 2024-12-24 11:14:41 -05:00

更改项目结构

This commit is contained in:
Nite07 2024-03-20 20:54:23 +08:00
parent 9e0068f4e1
commit eee361dcbf
27 changed files with 210 additions and 212 deletions

View File

@ -3,8 +3,8 @@ package handler
import ( import (
"encoding/json" "encoding/json"
"sub2sing-box/api/model" "sub2sing-box/api/model"
iutil "sub2sing-box/internal/util" "sub2sing-box/common"
putil "sub2sing-box/pkg/util" putil "sub2sing-box/util"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
@ -17,7 +17,7 @@ func Convert(c *gin.Context) {
}) })
return return
} }
j, err := iutil.DecodeBase64(c.Query("data")) j, err := putil.DecodeBase64(c.Query("data"))
if err != nil { if err != nil {
c.JSON(400, gin.H{ c.JSON(400, gin.H{
"error": "Invalid data", "error": "Invalid data",
@ -38,7 +38,7 @@ func Convert(c *gin.Context) {
}) })
return return
} }
result, err := putil.Convert( result, err := common.Convert(
data.Subscriptions, data.Subscriptions,
data.Proxies, data.Proxies,
data.Template, data.Template,

View File

@ -2,10 +2,9 @@ package cmd
import ( import (
"fmt" "fmt"
"os"
. "sub2sing-box/pkg/util"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"os"
. "sub2sing-box/common"
) )
var subscriptions []string var subscriptions []string

View File

@ -1,4 +1,4 @@
package util package common
import ( import (
"encoding/json" "encoding/json"
@ -9,10 +9,9 @@ import (
"regexp" "regexp"
"sort" "sort"
"strings" "strings"
model2 "sub2sing-box/model"
"sub2sing-box/internal/model" "sub2sing-box/parser"
"sub2sing-box/internal/util" "sub2sing-box/util"
"sub2sing-box/pkg/parser"
) )
func Convert( func Convert(
@ -57,14 +56,14 @@ func Convert(
keep := make(map[int]bool) keep := make(map[int]bool)
set := make(map[string]struct { set := make(map[string]struct {
Proxy model.Proxy Proxy model2.Proxy
Count int Count int
}) })
for i, p := range proxyList { for i, p := range proxyList {
if _, exists := set[p.Tag]; !exists { if _, exists := set[p.Tag]; !exists {
keep[i] = true keep[i] = true
set[p.Tag] = struct { set[p.Tag] = struct {
Proxy model.Proxy Proxy model2.Proxy
Count int Count int
}{p, 0} }{p, 0}
} else { } else {
@ -72,7 +71,7 @@ func Convert(
p2, _ := json.Marshal(set[p.Tag]) p2, _ := json.Marshal(set[p.Tag])
if string(p1) != string(p2) { if string(p1) != string(p2) {
set[p.Tag] = struct { set[p.Tag] = struct {
Proxy model.Proxy Proxy model2.Proxy
Count int Count int
}{p, set[p.Tag].Count + 1} }{p, set[p.Tag].Count + 1}
keep[i] = true keep[i] = true
@ -82,14 +81,14 @@ func Convert(
} }
} }
} }
var newProxyList []model.Proxy var newProxyList []model2.Proxy
for i, p := range proxyList { for i, p := range proxyList {
if keep[i] { if keep[i] {
newProxyList = append(newProxyList, p) newProxyList = append(newProxyList, p)
} }
} }
proxyList = newProxyList proxyList = newProxyList
var outbounds []model.Outbound var outbounds []model2.Outbound
ps, err := json.Marshal(&proxyList) ps, err := json.Marshal(&proxyList)
if err != nil { if err != nil {
return "", err return "", err
@ -117,16 +116,16 @@ func Convert(
return string(result), nil return string(result), nil
} }
func AddCountryGroup(proxies []model.Outbound, groupType string, sortKey string, sortType string) []model.Outbound { func AddCountryGroup(proxies []model2.Outbound, groupType string, sortKey string, sortType string) []model2.Outbound {
newGroup := make(map[string]model.Outbound) newGroup := make(map[string]model2.Outbound)
for _, p := range proxies { for _, p := range proxies {
if p.Type != "selector" && p.Type != "urltest" { if p.Type != "selector" && p.Type != "urltest" {
country := model.GetContryName(p.Tag) country := model2.GetContryName(p.Tag)
if group, ok := newGroup[country]; ok { if group, ok := newGroup[country]; ok {
group.Outbounds = append(group.Outbounds, p.Tag) group.Outbounds = append(group.Outbounds, p.Tag)
newGroup[country] = group newGroup[country] = group
} else { } else {
newGroup[country] = model.Outbound{ newGroup[country] = model2.Outbound{
Tag: country, Tag: country,
Type: groupType, Type: groupType,
Outbounds: []string{p.Tag}, Outbounds: []string{p.Tag},
@ -135,34 +134,34 @@ func AddCountryGroup(proxies []model.Outbound, groupType string, sortKey string,
} }
} }
} }
var groups []model.Outbound var groups []model2.Outbound
for _, p := range newGroup { for _, p := range newGroup {
groups = append(groups, p) groups = append(groups, p)
} }
if sortType == "asc" { if sortType == "asc" {
switch sortKey { switch sortKey {
case "tag": case "tag":
sort.Sort(model.SortByTag(groups)) sort.Sort(model2.SortByTag(groups))
case "num": case "num":
sort.Sort(model.SortByNumber(groups)) sort.Sort(model2.SortByNumber(groups))
default: default:
sort.Sort(model.SortByTag(groups)) sort.Sort(model2.SortByTag(groups))
} }
} else { } else {
switch sortKey { switch sortKey {
case "tag": case "tag":
sort.Sort(sort.Reverse(model.SortByTag(groups))) sort.Sort(sort.Reverse(model2.SortByTag(groups)))
case "num": case "num":
sort.Sort(sort.Reverse(model.SortByNumber(groups))) sort.Sort(sort.Reverse(model2.SortByNumber(groups)))
default: default:
sort.Sort(sort.Reverse(model.SortByTag(groups))) sort.Sort(sort.Reverse(model2.SortByTag(groups)))
} }
} }
return append(proxies, groups...) return append(proxies, groups...)
} }
func MergeTemplate(outbounds []model.Outbound, template string) (string, error) { func MergeTemplate(outbounds []model2.Outbound, template string) (string, error) {
var config model.Config var config model2.Config
var err error var err error
if strings.HasPrefix(template, "http") { if strings.HasPrefix(template, "http") {
data, err := util.Fetch(template, 3) data, err := util.Fetch(template, 3)
@ -183,12 +182,12 @@ func MergeTemplate(outbounds []model.Outbound, template string) (string, error)
} }
proxyTags := make([]string, 0) proxyTags := make([]string, 0)
groupTags := make([]string, 0) groupTags := make([]string, 0)
groups := make(map[string]model.Outbound) groups := make(map[string]model2.Outbound)
if err != nil { if err != nil {
return "", err return "", err
} }
for _, p := range outbounds { for _, p := range outbounds {
if model.IsCountryGroup(p.Tag) { if model2.IsCountryGroup(p.Tag) {
groupTags = append(groupTags, p.Tag) groupTags = append(groupTags, p.Tag)
reg := regexp.MustCompile("[A-Za-z]{2}") reg := regexp.MustCompile("[A-Za-z]{2}")
country := reg.FindString(p.Tag) country := reg.FindString(p.Tag)
@ -224,17 +223,17 @@ func MergeTemplate(outbounds []model.Outbound, template string) (string, error)
return string(data), nil return string(data), nil
} }
func ConvertCProxyToSProxy(proxy string) (model.Proxy, error) { func ConvertCProxyToSProxy(proxy string) (model2.Proxy, error) {
for prefix, parseFunc := range parser.ParserMap { for prefix, parseFunc := range parser.ParserMap {
if strings.HasPrefix(proxy, prefix) { if strings.HasPrefix(proxy, prefix) {
proxy, err := parseFunc(proxy) proxy, err := parseFunc(proxy)
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
return proxy, nil return proxy, nil
} }
} }
return model.Proxy{}, errors.New("Unknown proxy format") return model2.Proxy{}, errors.New("Unknown proxy format")
} }
func ConvertCProxyToJson(proxy string) (string, error) { func ConvertCProxyToJson(proxy string) (string, error) {
@ -249,8 +248,8 @@ func ConvertCProxyToJson(proxy string) (string, error) {
return string(data), nil return string(data), nil
} }
func ConvertSubscriptionsToSProxy(urls []string) ([]model.Proxy, error) { func ConvertSubscriptionsToSProxy(urls []string) ([]model2.Proxy, error) {
proxyList := make([]model.Proxy, 0) proxyList := make([]model2.Proxy, 0)
for _, url := range urls { for _, url := range urls {
data, err := util.Fetch(url, 3) data, err := util.Fetch(url, 3)
if err != nil { if err != nil {
@ -288,25 +287,25 @@ func ConvertSubscriptionsToJson(urls []string) (string, error) {
return string(result), nil return string(result), nil
} }
func ReadTemplate(path string) (model.Config, error) { func ReadTemplate(path string) (model2.Config, error) {
data, err := os.ReadFile(path) data, err := os.ReadFile(path)
if err != nil { if err != nil {
return model.Config{}, err return model2.Config{}, err
} }
var res model.Config var res model2.Config
err = json.Unmarshal(data, &res) err = json.Unmarshal(data, &res)
if err != nil { if err != nil {
return model.Config{}, err return model2.Config{}, err
} }
return res, nil return res, nil
} }
func DeleteProxy(proxies []model.Proxy, regex string) ([]model.Proxy, error) { func DeleteProxy(proxies []model2.Proxy, regex string) ([]model2.Proxy, error) {
reg, err := regexp.Compile(regex) reg, err := regexp.Compile(regex)
if err != nil { if err != nil {
return nil, err return nil, err
} }
var newProxies []model.Proxy var newProxies []model2.Proxy
for _, p := range proxies { for _, p := range proxies {
if !reg.MatchString(p.Tag) { if !reg.MatchString(p.Tag) {
newProxies = append(newProxies, p) newProxies = append(newProxies, p)
@ -315,7 +314,7 @@ func DeleteProxy(proxies []model.Proxy, regex string) ([]model.Proxy, error) {
return newProxies, nil return newProxies, nil
} }
func RenameProxy(proxies []model.Proxy, regex string, replaceText string) ([]model.Proxy, error) { func RenameProxy(proxies []model2.Proxy, regex string, replaceText string) ([]model2.Proxy, error) {
reg, err := regexp.Compile(regex) reg, err := regexp.Compile(regex)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@ -65,12 +65,12 @@ type LogOptions struct {
} }
type DNSOptions struct { type DNSOptions struct {
Servers Listable[DNSServerOptions] `json:"servers,omitempty"` Servers Listable[DNSServerOptions] `json:"servers,omitempty"`
Rules Listable[DNSRule] `json:"rules,omitempty"` Rules Listable[DNSRule] `json:"rules,omitempty"`
Final string `json:"final,omitempty"` Final string `json:"final,omitempty"`
ReverseMapping bool `json:"reverse_mapping,omitempty"` ReverseMapping bool `json:"reverse_mapping,omitempty"`
FakeIP *DNSFakeIPOptions `json:"fakeip,omitempty"` FakeIP *DNSFakeIPOptions `json:"fakeip,omitempty"`
Strategy string `json:"strategy,omitempty"` Strategy string `json:"strategy,omitempty"`
DisableCache bool `json:"disable_cache,omitempty"` DisableCache bool `json:"disable_cache,omitempty"`
DisableExpire bool `json:"disable_expire,omitempty"` DisableExpire bool `json:"disable_expire,omitempty"`
IndependentCache bool `json:"independent_cache,omitempty"` IndependentCache bool `json:"independent_cache,omitempty"`
@ -162,29 +162,29 @@ type Inbound struct {
Tag string `json:"tag,omitempty"` Tag string `json:"tag,omitempty"`
InterfaceName string `json:"interface_name,omitempty"` InterfaceName string `json:"interface_name,omitempty"`
MTU uint32 `json:"mtu,omitempty"` MTU uint32 `json:"mtu,omitempty"`
GSO bool `json:"gso,omitempty"` GSO bool `json:"gso,omitempty"`
Inet4Address Listable[string] `json:"inet4_address,omitempty"` Inet4Address Listable[string] `json:"inet4_address,omitempty"`
Inet6Address Listable[string] `json:"inet6_address,omitempty"` Inet6Address Listable[string] `json:"inet6_address,omitempty"`
AutoRoute bool `json:"auto_route,omitempty"` AutoRoute bool `json:"auto_route,omitempty"`
StrictRoute bool `json:"strict_route,omitempty"` StrictRoute bool `json:"strict_route,omitempty"`
Inet4RouteAddress Listable[string] `json:"inet4_route_address,omitempty"` Inet4RouteAddress Listable[string] `json:"inet4_route_address,omitempty"`
Inet6RouteAddress Listable[string] `json:"inet6_route_address,omitempty"` Inet6RouteAddress Listable[string] `json:"inet6_route_address,omitempty"`
Inet4RouteExcludeAddress Listable[string] `json:"inet4_route_exclude_address,omitempty"` Inet4RouteExcludeAddress Listable[string] `json:"inet4_route_exclude_address,omitempty"`
Inet6RouteExcludeAddress Listable[string] `json:"inet6_route_exclude_address,omitempty"` Inet6RouteExcludeAddress Listable[string] `json:"inet6_route_exclude_address,omitempty"`
IncludeInterface Listable[string] `json:"include_interface,omitempty"` IncludeInterface Listable[string] `json:"include_interface,omitempty"`
ExcludeInterface Listable[string] `json:"exclude_interface,omitempty"` ExcludeInterface Listable[string] `json:"exclude_interface,omitempty"`
IncludeUID Listable[uint32] `json:"include_uid,omitempty"` IncludeUID Listable[uint32] `json:"include_uid,omitempty"`
IncludeUIDRange Listable[string] `json:"include_uid_range,omitempty"` IncludeUIDRange Listable[string] `json:"include_uid_range,omitempty"`
ExcludeUID Listable[uint32] `json:"exclude_uid,omitempty"` ExcludeUID Listable[uint32] `json:"exclude_uid,omitempty"`
ExcludeUIDRange Listable[string] `json:"exclude_uid_range,omitempty"` ExcludeUIDRange Listable[string] `json:"exclude_uid_range,omitempty"`
IncludeAndroidUser Listable[int] `json:"include_android_user,omitempty"` IncludeAndroidUser Listable[int] `json:"include_android_user,omitempty"`
IncludePackage Listable[string] `json:"include_package,omitempty"` IncludePackage Listable[string] `json:"include_package,omitempty"`
ExcludePackage Listable[string] `json:"exclude_package,omitempty"` ExcludePackage Listable[string] `json:"exclude_package,omitempty"`
EndpointIndependentNat bool `json:"endpoint_independent_nat,omitempty"` EndpointIndependentNat bool `json:"endpoint_independent_nat,omitempty"`
UDPTimeout string `json:"udp_timeout,omitempty"` UDPTimeout string `json:"udp_timeout,omitempty"`
Stack string `json:"stack,omitempty"` Stack string `json:"stack,omitempty"`
Platform *TunPlatformOptions `json:"platform,omitempty"` Platform *TunPlatformOptions `json:"platform,omitempty"`
SniffEnabled bool `json:"sniff,omitempty"` SniffEnabled bool `json:"sniff,omitempty"`
SniffOverrideDestination bool `json:"sniff_override_destination,omitempty"` SniffOverrideDestination bool `json:"sniff_override_destination,omitempty"`
SniffTimeout string `json:"sniff_timeout,omitempty"` SniffTimeout string `json:"sniff_timeout,omitempty"`
DomainStrategy string `json:"domain_strategy,omitempty"` DomainStrategy string `json:"domain_strategy,omitempty"`
@ -227,53 +227,53 @@ type Outbound struct {
Version string `json:"version,omitempty"` Version string `json:"version,omitempty"`
Username string `json:"username,omitempty"` Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"` Password string `json:"password,omitempty"`
Network string `json:"network,omitempty"` Network string `json:"network,omitempty"`
UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"` UDPOverTCP *UDPOverTCPOptions `json:"udp_over_tcp,omitempty"`
TLS *OutboundTLSOptions `json:"tls,omitempty"` TLS *OutboundTLSOptions `json:"tls,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Headers map[string]Listable[string] `json:"headers,omitempty"` Headers map[string]Listable[string] `json:"headers,omitempty"`
Method string `json:"method,omitempty"` Method string `json:"method,omitempty"`
Plugin string `json:"plugin,omitempty"` Plugin string `json:"plugin,omitempty"`
PluginOptions string `json:"plugin_opts,omitempty"` PluginOptions string `json:"plugin_opts,omitempty"`
Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"` Multiplex *OutboundMultiplexOptions `json:"multiplex,omitempty"`
UUID string `json:"uuid,omitempty"` UUID string `json:"uuid,omitempty"`
Security string `json:"security,omitempty"` Security string `json:"security,omitempty"`
AlterId int `json:"alter_id,omitempty"` AlterId int `json:"alter_id,omitempty"`
GlobalPadding bool `json:"global_padding,omitempty"` GlobalPadding bool `json:"global_padding,omitempty"`
AuthenticatedLength bool `json:"authenticated_length,omitempty"` AuthenticatedLength bool `json:"authenticated_length,omitempty"`
PacketEncoding string `json:"packet_encoding,omitempty"` PacketEncoding string `json:"packet_encoding,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"` Transport *V2RayTransportOptions `json:"transport,omitempty"`
SystemInterface bool `json:"system_interface,omitempty"` SystemInterface bool `json:"system_interface,omitempty"`
GSO bool `json:"gso,omitempty"` GSO bool `json:"gso,omitempty"`
InterfaceName string `json:"interface_name,omitempty"` InterfaceName string `json:"interface_name,omitempty"`
LocalAddress Listable[string] `json:"local_address,omitempty"` LocalAddress Listable[string] `json:"local_address,omitempty"`
PrivateKey string `json:"private_key,omitempty"` PrivateKey string `json:"private_key,omitempty"`
Peers Listable[WireGuardPeer] `json:"peers,omitempty"` Peers Listable[WireGuardPeer] `json:"peers,omitempty"`
PeerPublicKey string `json:"peer_public_key,omitempty"` PeerPublicKey string `json:"peer_public_key,omitempty"`
PreSharedKey string `json:"pre_shared_key,omitempty"` PreSharedKey string `json:"pre_shared_key,omitempty"`
Reserved Listable[uint8] `json:"reserved,omitempty"` Reserved Listable[uint8] `json:"reserved,omitempty"`
Workers int `json:"workers,omitempty"` Workers int `json:"workers,omitempty"`
MTU uint32 `json:"mtu,omitempty"` MTU uint32 `json:"mtu,omitempty"`
Up string `json:"up,omitempty"` Up string `json:"up,omitempty"`
UpMbps int `json:"up_mbps,omitempty"` UpMbps int `json:"up_mbps,omitempty"`
Down string `json:"down,omitempty"` Down string `json:"down,omitempty"`
DownMbps int `json:"down_mbps,omitempty"` DownMbps int `json:"down_mbps,omitempty"`
Obfs *Obfs `json:"obfs,omitempty"` Obfs *Obfs `json:"obfs,omitempty"`
Auth Listable[byte] `json:"auth,omitempty"` Auth Listable[byte] `json:"auth,omitempty"`
AuthString string `json:"auth_str,omitempty"` AuthString string `json:"auth_str,omitempty"`
ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"` ReceiveWindowConn uint64 `json:"recv_window_conn,omitempty"`
ReceiveWindow uint64 `json:"recv_window,omitempty"` ReceiveWindow uint64 `json:"recv_window,omitempty"`
DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"` DisableMTUDiscovery bool `json:"disable_mtu_discovery,omitempty"`
ExecutablePath string `json:"executable_path,omitempty"` ExecutablePath string `json:"executable_path,omitempty"`
ExtraArgs Listable[string] `json:"extra_args,omitempty"` ExtraArgs Listable[string] `json:"extra_args,omitempty"`
DataDirectory string `json:"data_directory,omitempty"` DataDirectory string `json:"data_directory,omitempty"`
Options map[string]string `json:"torrc,omitempty"` Options map[string]string `json:"torrc,omitempty"`
User string `json:"user,omitempty"` User string `json:"user,omitempty"`
PrivateKeyPath string `json:"private_key_path,omitempty"` PrivateKeyPath string `json:"private_key_path,omitempty"`
PrivateKeyPassphrase string `json:"private_key_passphrase,omitempty"` PrivateKeyPassphrase string `json:"private_key_passphrase,omitempty"`
HostKey Listable[string] `json:"host_key,omitempty"` HostKey Listable[string] `json:"host_key,omitempty"`
HostKeyAlgorithms Listable[string] `json:"host_key_algorithms,omitempty"` HostKeyAlgorithms Listable[string] `json:"host_key_algorithms,omitempty"`
ClientVersion string `json:"client_version,omitempty"` ClientVersion string `json:"client_version,omitempty"`
ObfsParam string `json:"obfs_param,omitempty"` ObfsParam string `json:"obfs_param,omitempty"`
Protocol string `json:"protocol,omitempty"` Protocol string `json:"protocol,omitempty"`
ProtocolParam string `json:"protocol_param,omitempty"` ProtocolParam string `json:"protocol_param,omitempty"`
@ -284,9 +284,9 @@ type Outbound struct {
ZeroRTTHandshake bool `json:"zero_rtt_handshake,omitempty"` ZeroRTTHandshake bool `json:"zero_rtt_handshake,omitempty"`
Heartbeat string `json:"heartbeat,omitempty"` Heartbeat string `json:"heartbeat,omitempty"`
BrutalDebug bool `json:"brutal_debug,omitempty"` BrutalDebug bool `json:"brutal_debug,omitempty"`
Default string `json:"default,omitempty"` Default string `json:"default,omitempty"`
Outbounds Listable[string] `json:"outbounds,omitempty"` Outbounds Listable[string] `json:"outbounds,omitempty"`
URL string `json:"url,omitempty"` URL string `json:"url,omitempty"`
Interval string `json:"interval,omitempty"` Interval string `json:"interval,omitempty"`
Tolerance uint16 `json:"tolerance,omitempty"` Tolerance uint16 `json:"tolerance,omitempty"`
IdleTimeout string `json:"idle_timeout,omitempty"` IdleTimeout string `json:"idle_timeout,omitempty"`
@ -303,11 +303,11 @@ type WireGuardPeer struct {
} }
type RouteOptions struct { type RouteOptions struct {
GeoIP *GeoIPOptions `json:"geoip,omitempty"` GeoIP *GeoIPOptions `json:"geoip,omitempty"`
Geosite *GeositeOptions `json:"geosite,omitempty"` Geosite *GeositeOptions `json:"geosite,omitempty"`
Rules Listable[Rule] `json:"rules,omitempty"` Rules Listable[Rule] `json:"rules,omitempty"`
RuleSet Listable[RuleSet] `json:"rule_set,omitempty"` RuleSet Listable[RuleSet] `json:"rule_set,omitempty"`
Final string `json:"final,omitempty"` Final string `json:"final,omitempty"`
FindProcess bool `json:"find_process,omitempty"` FindProcess bool `json:"find_process,omitempty"`
AutoDetectInterface bool `json:"auto_detect_interface,omitempty"` AutoDetectInterface bool `json:"auto_detect_interface,omitempty"`
OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"` OverrideAndroidVPN bool `json:"override_android_vpn,omitempty"`

View File

@ -53,8 +53,8 @@ func (o *V2RayTransportOptions) MarshalJSON() ([]byte, error) {
} }
type V2RayHTTPOptions struct { type V2RayHTTPOptions struct {
Host Listable[string] `json:"host,omitempty"` Host Listable[string] `json:"host,omitempty"`
Path string `json:"path,omitempty"` Path string `json:"path,omitempty"`
Method string `json:"method,omitempty"` Method string `json:"method,omitempty"`
Headers map[string]string `json:"headers,omitempty"` Headers map[string]string `json:"headers,omitempty"`
IdleTimeout string `json:"idle_timeout,omitempty"` IdleTimeout string `json:"idle_timeout,omitempty"`

View File

@ -5,7 +5,7 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
) )
//hysteria://host:port?protocol=udp&auth=123456&peer=sni.domain&insecure=1&upmbps=100&downmbps=100&alpn=hysteria&obfs=xplus&obfsParam=123456#remarks //hysteria://host:port?protocol=udp&auth=123456&peer=sni.domain&insecure=1&upmbps=100&downmbps=100&alpn=hysteria&obfs=xplus&obfsParam=123456#remarks
@ -23,23 +23,23 @@ import (
//- obfsParam: Obfuscation password (optional) //- obfsParam: Obfuscation password (optional)
//- remarks: remarks (optional) //- remarks: remarks (optional)
func ParseHysteria(proxy string) (model.Proxy, error) { func ParseHysteria(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "hysteria://") { if !strings.HasPrefix(proxy, "hysteria://") {
return model.Proxy{}, errors.New("invalid hysteria Url") return model2.Proxy{}, errors.New("invalid hysteria Url")
} }
parts := strings.SplitN(strings.TrimPrefix(proxy, "hysteria://"), "?", 2) parts := strings.SplitN(strings.TrimPrefix(proxy, "hysteria://"), "?", 2)
serverInfo := strings.SplitN(parts[0], ":", 2) serverInfo := strings.SplitN(parts[0], ":", 2)
if len(serverInfo) != 2 { if len(serverInfo) != 2 {
return model.Proxy{}, errors.New("invalid hysteria Url") return model2.Proxy{}, errors.New("invalid hysteria Url")
} }
params, err := url.ParseQuery(parts[1]) params, err := url.ParseQuery(parts[1])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid hysteria Url") return model2.Proxy{}, errors.New("invalid hysteria Url")
} }
host := serverInfo[0] host := serverInfo[0]
port, err := strconv.Atoi(serverInfo[1]) port, err := strconv.Atoi(serverInfo[1])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid hysteria Url") return model2.Proxy{}, errors.New("invalid hysteria Url")
} }
protocol := params.Get("protocol") protocol := params.Get("protocol")
auth := params.Get("auth") auth := params.Get("auth")
@ -64,12 +64,12 @@ func ParseHysteria(proxy string) (model.Proxy, error) {
} }
insecureBool, err := strconv.ParseBool(insecure) insecureBool, err := strconv.ParseBool(insecure)
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid hysteria Url") return model2.Proxy{}, errors.New("invalid hysteria Url")
} }
result := model.Proxy{ result := model2.Proxy{
Type: "hysteria", Type: "hysteria",
Tag: remarks, Tag: remarks,
Hysteria: model.Hysteria{ Hysteria: model2.Hysteria{
Server: host, Server: host,
ServerPort: uint16(port), ServerPort: uint16(port),
Up: upmbps, Up: upmbps,
@ -77,7 +77,7 @@ func ParseHysteria(proxy string) (model.Proxy, error) {
Auth: []byte(auth), Auth: []byte(auth),
Obfs: obfs, Obfs: obfs,
Network: protocol, Network: protocol,
TLS: &model.OutboundTLSOptions{ TLS: &model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
Insecure: insecureBool, Insecure: insecureBool,
ALPN: alpn, ALPN: alpn,

View File

@ -5,14 +5,14 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
) )
// hysteria2://letmein@example.com/?insecure=1&obfs=salamander&obfs-password=gawrgura&pinSHA256=deadbeef&sni=real.example.com // hysteria2://letmein@example.com/?insecure=1&obfs=salamander&obfs-password=gawrgura&pinSHA256=deadbeef&sni=real.example.com
func ParseHysteria2(proxy string) (model.Proxy, error) { func ParseHysteria2(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "hysteria2://") && !strings.HasPrefix(proxy, "hy2://") { if !strings.HasPrefix(proxy, "hysteria2://") && !strings.HasPrefix(proxy, "hy2://") {
return model.Proxy{}, errors.New("invalid hysteria2 Url") return model2.Proxy{}, errors.New("invalid hysteria2 Url")
} }
parts := strings.SplitN(strings.TrimPrefix(proxy, "hysteria2://"), "@", 2) parts := strings.SplitN(strings.TrimPrefix(proxy, "hysteria2://"), "@", 2)
serverInfo := strings.SplitN(parts[1], "/?", 2) serverInfo := strings.SplitN(parts[1], "/?", 2)
@ -20,32 +20,32 @@ func ParseHysteria2(proxy string) (model.Proxy, error) {
if len(serverAndPort) == 1 { if len(serverAndPort) == 1 {
serverAndPort = append(serverAndPort, "443") serverAndPort = append(serverAndPort, "443")
} else if len(serverAndPort) != 2 { } else if len(serverAndPort) != 2 {
return model.Proxy{}, errors.New("invalid hysteria2 Url") return model2.Proxy{}, errors.New("invalid hysteria2 Url")
} }
params, err := url.ParseQuery(serverInfo[1]) params, err := url.ParseQuery(serverInfo[1])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid hysteria2 Url") return model2.Proxy{}, errors.New("invalid hysteria2 Url")
} }
port, err := strconv.Atoi(serverAndPort[1]) port, err := strconv.Atoi(serverAndPort[1])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid hysteria2 Url") return model2.Proxy{}, errors.New("invalid hysteria2 Url")
} }
remarks := params.Get("name") remarks := params.Get("name")
server := serverAndPort[0] server := serverAndPort[0]
password := parts[0] password := parts[0]
network := params.Get("network") network := params.Get("network")
result := model.Proxy{ result := model2.Proxy{
Type: "hysteria2", Type: "hysteria2",
Tag: remarks, Tag: remarks,
Hysteria2: model.Hysteria2{ Hysteria2: model2.Hysteria2{
Server: server, Server: server,
ServerPort: uint16(port), ServerPort: uint16(port),
Password: password, Password: password,
Obfs: &model.Hysteria2Obfs{ Obfs: &model2.Hysteria2Obfs{
Type: params.Get("obfs"), Type: params.Get("obfs"),
Password: params.Get("obfs-password"), Password: params.Get("obfs-password"),
}, },
TLS: &model.OutboundTLSOptions{ TLS: &model2.OutboundTLSOptions{
Enabled: params.Get("pinSHA256") != "", Enabled: params.Get("pinSHA256") != "",
Insecure: params.Get("insecure") == "1", Insecure: params.Get("insecure") == "1",
ServerName: params.Get("sni"), ServerName: params.Get("sni"),

View File

@ -1,7 +1,7 @@
package parser package parser
import ( import (
"sub2sing-box/internal/model" "sub2sing-box/model"
) )
var ParserMap map[string]func(string) (model.Proxy, error) = map[string]func(string) (model.Proxy, error){ var ParserMap map[string]func(string) (model.Proxy, error) = map[string]func(string) (model.Proxy, error){

View File

@ -5,43 +5,43 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
"sub2sing-box/internal/util" "sub2sing-box/util"
) )
func ParseShadowsocks(proxy string) (model.Proxy, error) { func ParseShadowsocks(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "ss://") { if !strings.HasPrefix(proxy, "ss://") {
return model.Proxy{}, errors.New("invalid ss Url") return model2.Proxy{}, errors.New("invalid ss Url")
} }
parts := strings.SplitN(strings.TrimPrefix(proxy, "ss://"), "@", 2) parts := strings.SplitN(strings.TrimPrefix(proxy, "ss://"), "@", 2)
if len(parts) != 2 { if len(parts) != 2 {
return model.Proxy{}, errors.New("invalid ss Url") return model2.Proxy{}, errors.New("invalid ss Url")
} }
if !strings.Contains(parts[0], ":") { if !strings.Contains(parts[0], ":") {
decoded, err := util.DecodeBase64(parts[0]) decoded, err := util.DecodeBase64(parts[0])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid ss Url" + err.Error()) return model2.Proxy{}, errors.New("invalid ss Url" + err.Error())
} }
parts[0] = decoded parts[0] = decoded
} }
credentials := strings.SplitN(parts[0], ":", 2) credentials := strings.SplitN(parts[0], ":", 2)
if len(credentials) != 2 { if len(credentials) != 2 {
return model.Proxy{}, errors.New("invalid ss Url") return model2.Proxy{}, errors.New("invalid ss Url")
} }
serverInfo := strings.SplitN(parts[1], "#", 2) serverInfo := strings.SplitN(parts[1], "#", 2)
serverAndPort := strings.SplitN(serverInfo[0], ":", 2) serverAndPort := strings.SplitN(serverInfo[0], ":", 2)
if len(serverAndPort) != 2 { if len(serverAndPort) != 2 {
return model.Proxy{}, errors.New("invalid ss Url") return model2.Proxy{}, errors.New("invalid ss Url")
} }
port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1])) port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1]))
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid ss Url" + err.Error()) return model2.Proxy{}, errors.New("invalid ss Url" + err.Error())
} }
remarks := "" remarks := ""
if len(serverInfo) == 2 { if len(serverInfo) == 2 {
unescape, err := url.QueryUnescape(serverInfo[1]) unescape, err := url.QueryUnescape(serverInfo[1])
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid ss Url" + err.Error()) return model2.Proxy{}, errors.New("invalid ss Url" + err.Error())
} }
remarks = strings.TrimSpace(unescape) remarks = strings.TrimSpace(unescape)
} else { } else {
@ -50,10 +50,10 @@ func ParseShadowsocks(proxy string) (model.Proxy, error) {
method := credentials[0] method := credentials[0]
password := credentials[1] password := credentials[1]
server := strings.TrimSpace(serverAndPort[0]) server := strings.TrimSpace(serverAndPort[0])
result := model.Proxy{ result := model2.Proxy{
Type: "shadowsocks", Type: "shadowsocks",
Tag: remarks, Tag: remarks,
Shadowsocks: model.Shadowsocks{ Shadowsocks: model2.Shadowsocks{
Method: method, Method: method,
Password: password, Password: password,
Server: server, Server: server,

View File

@ -5,30 +5,30 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
) )
func ParseTrojan(proxy string) (model.Proxy, error) { func ParseTrojan(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "trojan://") { if !strings.HasPrefix(proxy, "trojan://") {
return model.Proxy{}, errors.New("invalid trojan Url") return model2.Proxy{}, errors.New("invalid trojan Url")
} }
parts := strings.SplitN(strings.TrimPrefix(proxy, "trojan://"), "@", 2) parts := strings.SplitN(strings.TrimPrefix(proxy, "trojan://"), "@", 2)
if len(parts) != 2 { if len(parts) != 2 {
return model.Proxy{}, errors.New("invalid trojan Url") return model2.Proxy{}, errors.New("invalid trojan Url")
} }
serverInfo := strings.SplitN(parts[1], "#", 2) serverInfo := strings.SplitN(parts[1], "#", 2)
serverAndPortAndParams := strings.SplitN(serverInfo[0], "?", 2) serverAndPortAndParams := strings.SplitN(serverInfo[0], "?", 2)
serverAndPort := strings.SplitN(serverAndPortAndParams[0], ":", 2) serverAndPort := strings.SplitN(serverAndPortAndParams[0], ":", 2)
params, err := url.ParseQuery(serverAndPortAndParams[1]) params, err := url.ParseQuery(serverAndPortAndParams[1])
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
if len(serverAndPort) != 2 { if len(serverAndPort) != 2 {
return model.Proxy{}, errors.New("invalid trojan Url") return model2.Proxy{}, errors.New("invalid trojan Url")
} }
port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1])) port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1]))
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
remarks := "" remarks := ""
if len(serverInfo) == 2 { if len(serverInfo) == 2 {
@ -38,10 +38,10 @@ func ParseTrojan(proxy string) (model.Proxy, error) {
} }
server := strings.TrimSpace(serverAndPort[0]) server := strings.TrimSpace(serverAndPort[0])
password := strings.TrimSpace(parts[0]) password := strings.TrimSpace(parts[0])
result := model.Proxy{ result := model2.Proxy{
Type: "trojan", Type: "trojan",
Tag: remarks, Tag: remarks,
Trojan: model.Trojan{ Trojan: model2.Trojan{
Server: server, Server: server,
ServerPort: uint16(port), ServerPort: uint16(port),
Password: password, Password: password,
@ -55,31 +55,31 @@ func ParseTrojan(proxy string) (model.Proxy, error) {
} else { } else {
alpn = nil alpn = nil
} }
result.Trojan.TLS = &model.OutboundTLSOptions{ result.Trojan.TLS = &model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
ALPN: alpn, ALPN: alpn,
ServerName: params.Get("sni"), ServerName: params.Get("sni"),
} }
} }
if params.Get("security") == "reality" { if params.Get("security") == "reality" {
result.Trojan.TLS = &model.OutboundTLSOptions{ result.Trojan.TLS = &model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
ServerName: params.Get("sni"), ServerName: params.Get("sni"),
Reality: &model.OutboundRealityOptions{ Reality: &model2.OutboundRealityOptions{
Enabled: true, Enabled: true,
PublicKey: params.Get("pbk"), PublicKey: params.Get("pbk"),
ShortID: params.Get("sid"), ShortID: params.Get("sid"),
}, },
UTLS: &model.OutboundUTLSOptions{ UTLS: &model2.OutboundUTLSOptions{
Enabled: params.Get("fp") != "", Enabled: params.Get("fp") != "",
Fingerprint: params.Get("fp"), Fingerprint: params.Get("fp"),
}, },
} }
} }
if params.Get("type") == "ws" { if params.Get("type") == "ws" {
result.Trojan.Transport = &model.V2RayTransportOptions{ result.Trojan.Transport = &model2.V2RayTransportOptions{
Type: "ws", Type: "ws",
WebsocketOptions: model.V2RayWebsocketOptions{ WebsocketOptions: model2.V2RayWebsocketOptions{
Path: params.Get("path"), Path: params.Get("path"),
Headers: map[string]string{ Headers: map[string]string{
"Host": params.Get("host"), "Host": params.Get("host"),
@ -88,24 +88,24 @@ func ParseTrojan(proxy string) (model.Proxy, error) {
} }
} }
if params.Get("type") == "http" { if params.Get("type") == "http" {
result.Trojan.Transport = &model.V2RayTransportOptions{ result.Trojan.Transport = &model2.V2RayTransportOptions{
Type: "http", Type: "http",
HTTPOptions: model.V2RayHTTPOptions{ HTTPOptions: model2.V2RayHTTPOptions{
Host: []string{params.Get("host")}, Host: []string{params.Get("host")},
Path: params.Get("path"), Path: params.Get("path"),
}, },
} }
} }
if params.Get("type") == "quic" { if params.Get("type") == "quic" {
result.Trojan.Transport = &model.V2RayTransportOptions{ result.Trojan.Transport = &model2.V2RayTransportOptions{
Type: "quic", Type: "quic",
QUICOptions: model.V2RayQUICOptions{}, QUICOptions: model2.V2RayQUICOptions{},
} }
} }
if params.Get("type") == "grpc" { if params.Get("type") == "grpc" {
result.Trojan.Transport = &model.V2RayTransportOptions{ result.Trojan.Transport = &model2.V2RayTransportOptions{
Type: "grpc", Type: "grpc",
GRPCOptions: model.V2RayGRPCOptions{ GRPCOptions: model2.V2RayGRPCOptions{
ServiceName: params.Get("serviceName"), ServiceName: params.Get("serviceName"),
}, },
} }

View File

@ -5,30 +5,30 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
) )
func ParseVless(proxy string) (model.Proxy, error) { func ParseVless(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "vless://") { if !strings.HasPrefix(proxy, "vless://") {
return model.Proxy{}, errors.New("invalid vless Url") return model2.Proxy{}, errors.New("invalid vless Url")
} }
parts := strings.SplitN(strings.TrimPrefix(proxy, "vless://"), "@", 2) parts := strings.SplitN(strings.TrimPrefix(proxy, "vless://"), "@", 2)
if len(parts) != 2 { if len(parts) != 2 {
return model.Proxy{}, errors.New("invalid vless Url") return model2.Proxy{}, errors.New("invalid vless Url")
} }
serverInfo := strings.SplitN(parts[1], "#", 2) serverInfo := strings.SplitN(parts[1], "#", 2)
serverAndPortAndParams := strings.SplitN(serverInfo[0], "?", 2) serverAndPortAndParams := strings.SplitN(serverInfo[0], "?", 2)
serverAndPort := strings.SplitN(serverAndPortAndParams[0], ":", 2) serverAndPort := strings.SplitN(serverAndPortAndParams[0], ":", 2)
params, err := url.ParseQuery(serverAndPortAndParams[1]) params, err := url.ParseQuery(serverAndPortAndParams[1])
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
if len(serverAndPort) != 2 { if len(serverAndPort) != 2 {
return model.Proxy{}, errors.New("invalid vless Url") return model2.Proxy{}, errors.New("invalid vless Url")
} }
port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1])) port, err := strconv.Atoi(strings.TrimSpace(serverAndPort[1]))
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
remarks := "" remarks := ""
if len(serverInfo) == 2 { if len(serverInfo) == 2 {
@ -37,21 +37,21 @@ func ParseVless(proxy string) (model.Proxy, error) {
} else { } else {
remarks, err = url.QueryUnescape(serverInfo[1]) remarks, err = url.QueryUnescape(serverInfo[1])
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
} }
} else { } else {
remarks, err = url.QueryUnescape(serverAndPort[0]) remarks, err = url.QueryUnescape(serverAndPort[0])
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
} }
server := strings.TrimSpace(serverAndPort[0]) server := strings.TrimSpace(serverAndPort[0])
uuid := strings.TrimSpace(parts[0]) uuid := strings.TrimSpace(parts[0])
result := model.Proxy{ result := model2.Proxy{
Type: "vless", Type: "vless",
Tag: remarks, Tag: remarks,
VLESS: model.VLESS{ VLESS: model2.VLESS{
Server: server, Server: server,
ServerPort: uint16(port), ServerPort: uint16(port),
UUID: uuid, UUID: uuid,
@ -65,7 +65,7 @@ func ParseVless(proxy string) (model.Proxy, error) {
} else { } else {
alpn = nil alpn = nil
} }
result.VLESS.TLS = &model.OutboundTLSOptions{ result.VLESS.TLS = &model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
ALPN: alpn, ALPN: alpn,
Insecure: params.Get("allowInsecure") == "1", Insecure: params.Get("allowInsecure") == "1",
@ -78,14 +78,14 @@ func ParseVless(proxy string) (model.Proxy, error) {
} else { } else {
alpn = nil alpn = nil
} }
result.VLESS.TLS = &model.OutboundTLSOptions{ result.VLESS.TLS = &model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
ServerName: params.Get("sni"), ServerName: params.Get("sni"),
UTLS: &model.OutboundUTLSOptions{ UTLS: &model2.OutboundUTLSOptions{
Enabled: params.Get("fp") != "", Enabled: params.Get("fp") != "",
Fingerprint: params.Get("fp"), Fingerprint: params.Get("fp"),
}, },
Reality: &model.OutboundRealityOptions{ Reality: &model2.OutboundRealityOptions{
Enabled: true, Enabled: true,
PublicKey: params.Get("pbk"), PublicKey: params.Get("pbk"),
ShortID: params.Get("sid"), ShortID: params.Get("sid"),
@ -94,9 +94,9 @@ func ParseVless(proxy string) (model.Proxy, error) {
} }
} }
if params.Get("type") == "ws" { if params.Get("type") == "ws" {
result.VLESS.Transport = &model.V2RayTransportOptions{ result.VLESS.Transport = &model2.V2RayTransportOptions{
Type: "ws", Type: "ws",
WebsocketOptions: model.V2RayWebsocketOptions{ WebsocketOptions: model2.V2RayWebsocketOptions{
Path: params.Get("path"), Path: params.Get("path"),
Headers: map[string]string{ Headers: map[string]string{
"Host": params.Get("host"), "Host": params.Get("host"),
@ -105,15 +105,15 @@ func ParseVless(proxy string) (model.Proxy, error) {
} }
} }
if params.Get("type") == "quic" { if params.Get("type") == "quic" {
result.VLESS.Transport = &model.V2RayTransportOptions{ result.VLESS.Transport = &model2.V2RayTransportOptions{
Type: "quic", Type: "quic",
QUICOptions: model.V2RayQUICOptions{}, QUICOptions: model2.V2RayQUICOptions{},
} }
} }
if params.Get("type") == "grpc" { if params.Get("type") == "grpc" {
result.VLESS.Transport = &model.V2RayTransportOptions{ result.VLESS.Transport = &model2.V2RayTransportOptions{
Type: "grpc", Type: "grpc",
GRPCOptions: model.V2RayGRPCOptions{ GRPCOptions: model2.V2RayGRPCOptions{
ServiceName: params.Get("serviceName"), ServiceName: params.Get("serviceName"),
}, },
} }
@ -121,11 +121,11 @@ func ParseVless(proxy string) (model.Proxy, error) {
if params.Get("type") == "http" { if params.Get("type") == "http" {
host, err := url.QueryUnescape(params.Get("host")) host, err := url.QueryUnescape(params.Get("host"))
if err != nil { if err != nil {
return model.Proxy{}, err return model2.Proxy{}, err
} }
result.VLESS.Transport = &model.V2RayTransportOptions{ result.VLESS.Transport = &model2.V2RayTransportOptions{
Type: "http", Type: "http",
HTTPOptions: model.V2RayHTTPOptions{ HTTPOptions: model2.V2RayHTTPOptions{
Host: strings.Split(host, ","), Host: strings.Split(host, ","),
}, },
} }

View File

@ -6,29 +6,29 @@ import (
"net/url" "net/url"
"strconv" "strconv"
"strings" "strings"
"sub2sing-box/internal/model" model2 "sub2sing-box/model"
"sub2sing-box/internal/util" "sub2sing-box/util"
) )
func ParseVmess(proxy string) (model.Proxy, error) { func ParseVmess(proxy string) (model2.Proxy, error) {
if !strings.HasPrefix(proxy, "vmess://") { if !strings.HasPrefix(proxy, "vmess://") {
return model.Proxy{}, errors.New("invalid vmess url") return model2.Proxy{}, errors.New("invalid vmess url")
} }
base64, err := util.DecodeBase64(strings.TrimPrefix(proxy, "vmess://")) base64, err := util.DecodeBase64(strings.TrimPrefix(proxy, "vmess://"))
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid vmess url" + err.Error()) return model2.Proxy{}, errors.New("invalid vmess url" + err.Error())
} }
var vmess model.VmessJson var vmess model2.VmessJson
err = json.Unmarshal([]byte(base64), &vmess) err = json.Unmarshal([]byte(base64), &vmess)
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid vmess url" + err.Error()) return model2.Proxy{}, errors.New("invalid vmess url" + err.Error())
} }
port := 0 port := 0
switch vmess.Port.(type) { switch vmess.Port.(type) {
case string: case string:
port, err = strconv.Atoi(vmess.Port.(string)) port, err = strconv.Atoi(vmess.Port.(string))
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid vmess url" + err.Error()) return model2.Proxy{}, errors.New("invalid vmess url" + err.Error())
} }
case float64: case float64:
port = int(vmess.Port.(float64)) port = int(vmess.Port.(float64))
@ -38,7 +38,7 @@ func ParseVmess(proxy string) (model.Proxy, error) {
case string: case string:
aid, err = strconv.Atoi(vmess.Aid.(string)) aid, err = strconv.Atoi(vmess.Aid.(string))
if err != nil { if err != nil {
return model.Proxy{}, errors.New("invalid vmess url" + err.Error()) return model2.Proxy{}, errors.New("invalid vmess url" + err.Error())
} }
case float64: case float64:
aid = int(vmess.Aid.(float64)) aid = int(vmess.Aid.(float64))
@ -52,10 +52,10 @@ func ParseVmess(proxy string) (model.Proxy, error) {
name = vmess.Ps name = vmess.Ps
} }
result := model.Proxy{ result := model2.Proxy{
Type: "vmess", Type: "vmess",
Tag: name, Tag: name,
VMess: model.VMess{ VMess: model2.VMess{
Server: vmess.Add, Server: vmess.Add,
ServerPort: uint16(port), ServerPort: uint16(port),
UUID: vmess.Id, UUID: vmess.Id,
@ -71,9 +71,9 @@ func ParseVmess(proxy string) (model.Proxy, error) {
} else { } else {
alpn = nil alpn = nil
} }
tls := model.OutboundTLSOptions{ tls := model2.OutboundTLSOptions{
Enabled: true, Enabled: true,
UTLS: &model.OutboundUTLSOptions{ UTLS: &model2.OutboundUTLSOptions{
Fingerprint: vmess.Fp, Fingerprint: vmess.Fp,
}, },
ALPN: alpn, ALPN: alpn,
@ -88,13 +88,13 @@ func ParseVmess(proxy string) (model.Proxy, error) {
if vmess.Host == "" { if vmess.Host == "" {
vmess.Host = vmess.Add vmess.Host = vmess.Add
} }
ws := model.V2RayWebsocketOptions{ ws := model2.V2RayWebsocketOptions{
Path: vmess.Path, Path: vmess.Path,
Headers: map[string]string{ Headers: map[string]string{
"Host": vmess.Host, "Host": vmess.Host,
}, },
} }
transport := model.V2RayTransportOptions{ transport := model2.V2RayTransportOptions{
Type: "ws", Type: "ws",
WebsocketOptions: ws, WebsocketOptions: ws,
} }
@ -102,8 +102,8 @@ func ParseVmess(proxy string) (model.Proxy, error) {
} }
if vmess.Net == "quic" { if vmess.Net == "quic" {
quic := model.V2RayQUICOptions{} quic := model2.V2RayQUICOptions{}
transport := model.V2RayTransportOptions{ transport := model2.V2RayTransportOptions{
Type: "quic", Type: "quic",
QUICOptions: quic, QUICOptions: quic,
} }
@ -111,11 +111,11 @@ func ParseVmess(proxy string) (model.Proxy, error) {
} }
if vmess.Net == "grpc" { if vmess.Net == "grpc" {
grpc := model.V2RayGRPCOptions{ grpc := model2.V2RayGRPCOptions{
ServiceName: vmess.Path, ServiceName: vmess.Path,
PermitWithoutStream: true, PermitWithoutStream: true,
} }
transport := model.V2RayTransportOptions{ transport := model2.V2RayTransportOptions{
Type: "grpc", Type: "grpc",
GRPCOptions: grpc, GRPCOptions: grpc,
} }
@ -123,11 +123,11 @@ func ParseVmess(proxy string) (model.Proxy, error) {
} }
if vmess.Net == "h2" { if vmess.Net == "h2" {
httpOps := model.V2RayHTTPOptions{ httpOps := model2.V2RayHTTPOptions{
Host: strings.Split(vmess.Host, ","), Host: strings.Split(vmess.Host, ","),
Path: vmess.Path, Path: vmess.Path,
} }
transport := model.V2RayTransportOptions{ transport := model2.V2RayTransportOptions{
Type: "http", Type: "http",
HTTPOptions: httpOps, HTTPOptions: httpOps,
} }